Beispiel #1
0
        protected override void Prepare(AssetCompilerContext context, AssetItem assetItem, string targetUrlInStorage, AssetCompilerResult result)
        {
            var asset       = (SkeletonAsset)assetItem.Asset;
            var assetSource = GetAbsolutePath(assetItem, asset.Source);
            var extension   = assetSource.GetFileExtension();
            var buildStep   = new AssetBuildStep(assetItem);

            var importModelCommand = ImportModelCommand.Create(extension);

            if (importModelCommand == null)
            {
                result.Error($"No importer found for model extension '{extension}. The model '{assetSource}' can't be imported.");
                return;
            }

            importModelCommand.SourcePath    = assetSource;
            importModelCommand.Location      = targetUrlInStorage;
            importModelCommand.Mode          = ImportModelCommand.ExportMode.Skeleton;
            importModelCommand.ScaleImport   = asset.ScaleImport;
            importModelCommand.PivotPosition = asset.PivotPosition;
            importModelCommand.SkeletonNodesWithPreserveInfo = asset.NodesWithPreserveInfo;

            buildStep.Add(importModelCommand);

            result.BuildSteps = buildStep;
        }
        protected override void Compile(AssetCompilerContext context, string urlInStorage, UFile assetAbsolutePath, SkeletonAsset asset, AssetCompilerResult result)
        {
            if (!EnsureSourcesExist(result, asset, assetAbsolutePath))
            {
                return;
            }

            var assetSource = GetAbsolutePath(assetAbsolutePath, asset.Source);
            var extension   = assetSource.GetFileExtension();
            var buildStep   = new AssetBuildStep(AssetItem);

            var importModelCommand = ImportModelCommand.Create(extension);

            if (importModelCommand == null)
            {
                result.Error("No importer found for model extension '{0}. The model '{1}' can't be imported.", extension, assetSource);
                return;
            }

            importModelCommand.SourcePath    = assetSource;
            importModelCommand.Location      = urlInStorage;
            importModelCommand.Mode          = ImportModelCommand.ExportMode.Skeleton;
            importModelCommand.ScaleImport   = asset.ScaleImport;
            importModelCommand.PivotPosition = asset.PivotPosition;
            importModelCommand.SkeletonNodesWithPreserveInfo = asset.NodesWithPreserveInfo;

            buildStep.Add(importModelCommand);

            result.BuildSteps = buildStep;
        }
Beispiel #3
0
        protected override void Prepare(AssetCompilerContext context, AssetItem assetItem, string targetUrlInStorage, AssetCompilerResult result)
        {
            var asset             = (SpriteStudioModelAsset)assetItem.Asset;
            var gameSettingsAsset = context.GetGameSettingsAsset();
            var renderingSettings = gameSettingsAsset.GetOrCreate <RenderingSettings>(context.Platform);
            var colorSpace        = renderingSettings.ColorSpace;

            var cells  = new List <SpriteStudioCell>();
            var images = new List <UFile>();

            if (!SpriteStudioXmlImport.ParseCellMaps(asset.Source, images, cells))
            {
                throw new Exception("Failed to parse SpriteStudio cell textures.");
            }

            var texIndex = 0;

            asset.BuildTextures.Clear();
            foreach (var texture in images)
            {
                var textureAsset = new TextureAsset
                {
                    Id              = AssetId.Empty, // CAUTION: It is important to use an empty GUID here, as we don't want the command to be rebuilt (by default, a new asset is creating a new guid)
                    IsStreamable    = false,
                    IsCompressed    = false,
                    GenerateMipmaps = true,
                    Type            = new ColorTextureType
                    {
                        Alpha            = AlphaFormat.Auto,
                        PremultiplyAlpha = true,
                        UseSRgbSampling  = true,
                    }
                };

                var textureConvertParameters = new TextureConvertParameters(texture, textureAsset, context.Platform, context.GetGraphicsPlatform(assetItem.Package), renderingSettings.DefaultGraphicsProfile, gameSettingsAsset.GetOrCreate <TextureSettings>().TextureQuality, colorSpace);
                var textureConvertCommand    = new TextureAssetCompiler.TextureConvertCommand(targetUrlInStorage + texIndex, textureConvertParameters, assetItem.Package);
                result.BuildSteps.Add(textureConvertCommand);

                asset.BuildTextures.Add(targetUrlInStorage + texIndex);

                texIndex++;
            }

            var step = new AssetBuildStep(assetItem);

            step.Add(new SpriteStudioModelAssetCommand(targetUrlInStorage, asset, colorSpace, assetItem.Package));
            result.BuildSteps.Add(step);
        }
Beispiel #4
0
        protected override void Prepare(AssetCompilerContext context, AssetItem assetItem, string targetUrlInStorage, AssetCompilerResult result)
        {
            var asset             = (SpriteSheetAsset)assetItem.Asset;
            var gameSettingsAsset = context.GetGameSettingsAsset();
            var renderingSettings = gameSettingsAsset.GetOrCreate <RenderingSettings>(context.Platform);

            result.BuildSteps = new ListBuildStep();

            var prereqSteps = new Queue <BuildStep>();

            // create the registry containing the sprite assets texture index association
            var imageToTextureUrl = new Dictionary <SpriteInfo, string>();

            var colorSpace = context.GetColorSpace();

            // create and add import texture commands
            if (asset.Sprites != null && !asset.Packing.Enabled)
            {
                // sort sprites by referenced texture.
                var spriteByTextures = asset.Sprites.GroupBy(x => x.Source).ToArray();
                for (int i = 0; i < spriteByTextures.Length; i++)
                {
                    // skip the texture if the file is not valid.
                    var textureFile = spriteByTextures[i].Key;
                    if (!TextureFileIsValid(textureFile))
                    {
                        continue;
                    }

                    var textureUrl = SpriteSheetAsset.BuildTextureUrl(assetItem.Location, i);

                    var spriteAssetArray = spriteByTextures[i].ToArray();
                    foreach (var spriteAsset in spriteAssetArray)
                    {
                        imageToTextureUrl[spriteAsset] = textureUrl;
                    }

                    // create an texture asset.
                    var textureAsset = new TextureAsset
                    {
                        Id              = AssetId.Empty, // CAUTION: It is important to use an empty GUID here, as we don't want the command to be rebuilt (by default, a new asset is creating a new guid)
                        IsStreamable    = asset.IsStreamable && asset.Type != SpriteSheetType.UI,
                        IsCompressed    = asset.IsCompressed,
                        GenerateMipmaps = asset.GenerateMipmaps,
                        Type            = new ColorTextureType
                        {
                            Alpha            = asset.Alpha,
                            PremultiplyAlpha = asset.PremultiplyAlpha,
                            ColorKeyColor    = asset.ColorKeyColor,
                            ColorKeyEnabled  = asset.ColorKeyEnabled,
                            UseSRgbSampling  = true,
                        }
                    };

                    // Get absolute path of asset source on disk
                    var assetDirectory = assetItem.FullPath.GetParent();
                    var assetSource    = UPath.Combine(assetDirectory, spriteAssetArray[0].Source);

                    // add the texture build command.
                    var textureConvertParameters = new TextureConvertParameters(assetSource, textureAsset, context.Platform, context.GetGraphicsPlatform(assetItem.Package), renderingSettings.DefaultGraphicsProfile, gameSettingsAsset.GetOrCreate <TextureSettings>().TextureQuality, colorSpace);
                    var textureConvertCommand    = new TextureAssetCompiler.TextureConvertCommand(textureUrl, textureConvertParameters, assetItem.Package);
                    var assetBuildStep           = new AssetBuildStep(new AssetItem(textureUrl, textureAsset));
                    assetBuildStep.Add(textureConvertCommand);
                    prereqSteps.Enqueue(assetBuildStep);
                    result.BuildSteps.Add(assetBuildStep);
                }
            }

            if (!result.HasErrors)
            {
                var parameters = new SpriteSheetParameters(asset, imageToTextureUrl, context.Platform, context.GetGraphicsPlatform(assetItem.Package), renderingSettings.DefaultGraphicsProfile, gameSettingsAsset.GetOrCreate <TextureSettings>().TextureQuality, colorSpace);

                var assetBuildStep = new AssetBuildStep(assetItem);
                assetBuildStep.Add(new SpriteSheetCommand(targetUrlInStorage, parameters, assetItem.Package));
                result.BuildSteps.Add(assetBuildStep);

                while (prereqSteps.Count > 0)
                {
                    var prereq = prereqSteps.Dequeue();
                    BuildStep.LinkBuildSteps(prereq, assetBuildStep);
                }
            }
        }
Beispiel #5
0
        protected override void Prepare(AssetCompilerContext context, AssetItem assetItem, string targetUrlInStorage, AssetCompilerResult result)
        {
            var asset             = (AnimationAsset)assetItem.Asset;
            var assetAbsolutePath = assetItem.FullPath;
            // Get absolute path of asset source on disk
            var assetDirectory = assetAbsolutePath.GetParent();
            var assetSource    = GetAbsolutePath(assetItem, asset.Source);
            var extension      = assetSource.GetFileExtension();
            var buildStep      = new AssetBuildStep(assetItem);

            // Find skeleton asset, if any
            AssetItem skeleton = null;

            if (asset.Skeleton != null)
            {
                skeleton = assetItem.Package.FindAssetFromProxyObject(asset.Skeleton);
            }

            var sourceBuildCommand = ImportModelCommand.Create(extension);

            if (sourceBuildCommand == null)
            {
                result.Error($"No importer found for model extension '{extension}. The model '{assetSource}' can't be imported.");
                return;
            }

            sourceBuildCommand.Mode                   = ImportModelCommand.ExportMode.Animation;
            sourceBuildCommand.SourcePath             = assetSource;
            sourceBuildCommand.Location               = targetUrlInStorage;
            sourceBuildCommand.AnimationRepeatMode    = asset.RepeatMode;
            sourceBuildCommand.AnimationRootMotion    = asset.RootMotion;
            sourceBuildCommand.ImportCustomAttributes = asset.ImportCustomAttributes;
            if (asset.ClipDuration.Enabled)
            {
                sourceBuildCommand.StartFrame = asset.ClipDuration.StartAnimationTime;
                sourceBuildCommand.EndFrame   = asset.ClipDuration.EndAnimationTime;
            }
            else
            {
                sourceBuildCommand.StartFrame = TimeSpan.Zero;
                sourceBuildCommand.EndFrame   = AnimationAsset.LongestTimeSpan;
            }
            sourceBuildCommand.ScaleImport   = asset.ScaleImport;
            sourceBuildCommand.PivotPosition = asset.PivotPosition;

            if (skeleton != null)
            {
                sourceBuildCommand.SkeletonUrl = skeleton.Location;
                // Note: skeleton override values
                sourceBuildCommand.ScaleImport   = ((SkeletonAsset)skeleton.Asset).ScaleImport;
                sourceBuildCommand.PivotPosition = ((SkeletonAsset)skeleton.Asset).PivotPosition;
            }

            if (asset.Type.Type == AnimationAssetTypeEnum.AnimationClip)
            {
                // Import the main animation
                buildStep.Add(sourceBuildCommand);
            }
            else if (asset.Type.Type == AnimationAssetTypeEnum.DifferenceClip)
            {
                var diffAnimationAsset = ((DifferenceAnimationAssetType)asset.Type);
                var referenceClip      = diffAnimationAsset.BaseSource;
                var rebaseMode         = diffAnimationAsset.Mode;

                var baseUrlInStorage   = targetUrlInStorage + RefClipSuffix;
                var sourceUrlInStorage = targetUrlInStorage + SrcClipSuffix;

                var baseAssetSource = UPath.Combine(assetDirectory, referenceClip);
                var baseExtension   = baseAssetSource.GetFileExtension();

                sourceBuildCommand.Location = sourceUrlInStorage;

                var baseBuildCommand = ImportModelCommand.Create(extension);
                if (baseBuildCommand == null)
                {
                    result.Error($"No importer found for model extension '{baseExtension}. The model '{baseAssetSource}' can't be imported.");
                    return;
                }

                baseBuildCommand.FailOnEmptyAnimation = false;
                baseBuildCommand.Mode                = ImportModelCommand.ExportMode.Animation;
                baseBuildCommand.SourcePath          = baseAssetSource;
                baseBuildCommand.Location            = baseUrlInStorage;
                baseBuildCommand.AnimationRepeatMode = asset.RepeatMode;
                baseBuildCommand.AnimationRootMotion = asset.RootMotion;

                if (diffAnimationAsset.ClipDuration.Enabled)
                {
                    baseBuildCommand.StartFrame = diffAnimationAsset.ClipDuration.StartAnimationTimeBox;
                    baseBuildCommand.EndFrame   = diffAnimationAsset.ClipDuration.EndAnimationTimeBox;
                }
                else
                {
                    baseBuildCommand.StartFrame = TimeSpan.Zero;
                    baseBuildCommand.EndFrame   = AnimationAsset.LongestTimeSpan;
                }

                baseBuildCommand.ScaleImport   = asset.ScaleImport;
                baseBuildCommand.PivotPosition = asset.PivotPosition;

                if (skeleton != null)
                {
                    baseBuildCommand.SkeletonUrl = skeleton.Location;
                    // Note: skeleton override values
                    baseBuildCommand.ScaleImport   = ((SkeletonAsset)skeleton.Asset).ScaleImport;
                    baseBuildCommand.PivotPosition = ((SkeletonAsset)skeleton.Asset).PivotPosition;
                }

                // Import base and main animation
                var sourceStep = new CommandBuildStep(sourceBuildCommand);
                buildStep.Add(sourceStep);
                var baseStep = new CommandBuildStep(baseBuildCommand);
                buildStep.Add(baseStep);

                IEnumerable <ObjectUrl> InputFilesGetter()
                {
                    yield return(new ObjectUrl(UrlType.File, GetAbsolutePath(assetItem, diffAnimationAsset.BaseSource)));
                }

                var diffCommand = new AdditiveAnimationCommand(targetUrlInStorage, new AdditiveAnimationParameters(baseUrlInStorage, sourceUrlInStorage, rebaseMode), assetItem.Package)
                {
                    InputFilesGetter = InputFilesGetter
                };

                var diffStep = new CommandBuildStep(diffCommand);

                BuildStep.LinkBuildSteps(sourceStep, diffStep);
                BuildStep.LinkBuildSteps(baseStep, diffStep);

                // Generate the diff of those two animations
                buildStep.Add(diffStep);
            }
            else
            {
                throw new NotImplementedException("This type of animation asset is not supported yet!");
            }

            result.BuildSteps = buildStep;
        }
Beispiel #6
0
        protected override void Prepare(AssetCompilerContext context, AssetItem assetItem, string targetUrlInStorage, AssetCompilerResult result)
        {
            var asset = (SkyboxAsset)assetItem.Asset;

            var colorSpace = context.GetColorSpace();

            result.BuildSteps = new AssetBuildStep(assetItem);

            var prereqs = new Queue <BuildStep>();

            // build the textures for windows (needed for skybox compilation)
            foreach (var dependency in asset.GetDependencies())
            {
                var dependencyItem = assetItem.Package.Assets.Find(dependency.Id);
                if (dependencyItem?.Asset is TextureAsset)
                {
                    var textureAsset = (TextureAsset)dependencyItem.Asset;

                    // Get absolute path of asset source on disk
                    var assetSource = GetAbsolutePath(dependencyItem, textureAsset.Source);

                    // Create a synthetic url
                    var textureUrl = SkyboxGenerator.BuildTextureForSkyboxGenerationLocation(dependencyItem.Location);

                    var gameSettingsAsset = context.GetGameSettingsAsset();
                    var renderingSettings = gameSettingsAsset.GetOrCreate <RenderingSettings>(context.Platform);

                    // Select the best graphics profile
                    var graphicsProfile = renderingSettings.DefaultGraphicsProfile >= GraphicsProfile.Level_10_0 ? renderingSettings.DefaultGraphicsProfile : GraphicsProfile.Level_10_0;

                    var textureAssetItem = new AssetItem(textureUrl, textureAsset);

                    // Create and add the texture command.
                    var textureParameters = new TextureConvertParameters(assetSource, textureAsset, PlatformType.Windows, GraphicsPlatform.Direct3D11, graphicsProfile, gameSettingsAsset.GetOrCreate <TextureSettings>().TextureQuality, colorSpace);
                    var prereqStep        = new AssetBuildStep(textureAssetItem);
                    prereqStep.Add(new TextureAssetCompiler.TextureConvertCommand(textureUrl, textureParameters, assetItem.Package));
                    result.BuildSteps.Add(prereqStep);
                    prereqs.Enqueue(prereqStep);
                }
            }

            // add the skybox command itself.
            IEnumerable <ObjectUrl> InputFilesGetter()
            {
                var skyboxAsset = (SkyboxAsset)assetItem.Asset;

                foreach (var dependency in skyboxAsset.GetDependencies())
                {
                    var dependencyItem = assetItem.Package.Assets.Find(dependency.Id);
                    if (dependencyItem?.Asset is TextureAsset)
                    {
                        yield return(new ObjectUrl(UrlType.Content, dependency.Location));
                    }
                }
            }

            var assetStep = new CommandBuildStep(new SkyboxCompileCommand(targetUrlInStorage, asset, assetItem.Package)
            {
                InputFilesGetter = InputFilesGetter
            });

            result.BuildSteps.Add(assetStep);
            while (prereqs.Count > 0)
            {
                var prereq = prereqs.Dequeue();
                BuildStep.LinkBuildSteps(prereq, assetStep);
            }
        }
Beispiel #7
0
        protected override void Compile(AssetCompilerContext context, AssetItem assetItem, string targetUrlInStorage, AssetCompilerResult result)
        {
            var asset             = (AnimationAsset)assetItem.Asset;
            var assetAbsolutePath = assetItem.FullPath;
            // Get absolute path of asset source on disk
            var assetDirectory = assetAbsolutePath.GetParent();
            var assetSource    = GetAbsolutePath(assetItem, asset.Source);
            var extension      = assetSource.GetFileExtension();
            var buildStep      = new AssetBuildStep(assetItem);

            // Find skeleton asset, if any
            AssetItem skeleton = null;

            if (asset.Skeleton != null)
            {
                skeleton = assetItem.Package.FindAssetFromProxyObject(asset.Skeleton);
            }

            var sourceBuildStep = ImportModelCommand.Create(extension);

            if (sourceBuildStep == null)
            {
                result.Error($"No importer found for model extension '{extension}. The model '{assetSource}' can't be imported.");
                return;
            }

            sourceBuildStep.Mode                = ImportModelCommand.ExportMode.Animation;
            sourceBuildStep.SourcePath          = assetSource;
            sourceBuildStep.Location            = targetUrlInStorage;
            sourceBuildStep.AnimationRepeatMode = asset.RepeatMode;
            sourceBuildStep.AnimationRootMotion = asset.RootMotion;
            if (asset.ClipDuration.Enabled)
            {
                sourceBuildStep.StartFrame = asset.ClipDuration.StartAnimationTime;
                sourceBuildStep.EndFrame   = asset.ClipDuration.EndAnimationTime;
            }
            else
            {
                sourceBuildStep.StartFrame = TimeSpan.Zero;
                sourceBuildStep.EndFrame   = AnimationAsset.LongestTimeSpan;
            }
            sourceBuildStep.ScaleImport   = asset.ScaleImport;
            sourceBuildStep.PivotPosition = asset.PivotPosition;
            sourceBuildStep.SkeletonUrl   = skeleton?.Location;

            if (asset.Type.Type == AnimationAssetTypeEnum.AnimationClip)
            {
                // Import the main animation
                buildStep.Add(sourceBuildStep);
            }
            else if (asset.Type.Type == AnimationAssetTypeEnum.DifferenceClip)
            {
                var diffAnimationAsset = ((DifferenceAnimationAssetType)asset.Type);
                var referenceClip      = diffAnimationAsset.BaseSource;
                var rebaseMode         = diffAnimationAsset.Mode;

                var baseUrlInStorage   = targetUrlInStorage + RefClipSuffix;
                var sourceUrlInStorage = targetUrlInStorage + SrcClipSuffix;

                var baseAssetSource = UPath.Combine(assetDirectory, referenceClip);
                var baseExtension   = baseAssetSource.GetFileExtension();

                sourceBuildStep.Location = sourceUrlInStorage;

                var baseBuildStep = ImportModelCommand.Create(extension);
                if (baseBuildStep == null)
                {
                    result.Error($"No importer found for model extension '{baseExtension}. The model '{baseAssetSource}' can't be imported.");
                    return;
                }

                baseBuildStep.Mode                = ImportModelCommand.ExportMode.Animation;
                baseBuildStep.SourcePath          = baseAssetSource;
                baseBuildStep.Location            = baseUrlInStorage;
                baseBuildStep.AnimationRepeatMode = asset.RepeatMode;
                baseBuildStep.AnimationRootMotion = asset.RootMotion;

                if (diffAnimationAsset.ClipDuration.Enabled)
                {
                    baseBuildStep.StartFrame = diffAnimationAsset.ClipDuration.StartAnimationTimeBox;
                    baseBuildStep.EndFrame   = diffAnimationAsset.ClipDuration.EndAnimationTimeBox;
                }
                else
                {
                    baseBuildStep.StartFrame = TimeSpan.Zero;
                    baseBuildStep.EndFrame   = AnimationAsset.LongestTimeSpan;
                }

                baseBuildStep.ScaleImport   = asset.ScaleImport;
                baseBuildStep.PivotPosition = asset.PivotPosition;
                baseBuildStep.SkeletonUrl   = skeleton?.Location;

                // Import base and main animation
                buildStep.Add(sourceBuildStep);
                buildStep.Add(baseBuildStep);

                // Wait for both import fbx commands to be completed
                buildStep.Add(new WaitBuildStep());

                // Generate the diff of those two animations
                buildStep.Add(new AdditiveAnimationCommand(targetUrlInStorage, new AdditiveAnimationParameters(baseUrlInStorage, sourceUrlInStorage, rebaseMode)));
            }
            else
            {
                throw new NotImplementedException("This type of animation asset is not supported yet!");
            }


            result.BuildSteps = buildStep;
        }
Beispiel #8
0
        protected override void Compile(AssetCompilerContext context, string urlInStorage, UFile assetAbsolutePath, AnimationAsset asset, AssetCompilerResult result)
        {
            if (!EnsureSourceExists(result, asset, assetAbsolutePath))
            {
                return;
            }

            // Get absolute path of asset source on disk
            var assetDirectory = assetAbsolutePath.GetParent();
            var assetSource    = GetAbsolutePath(assetAbsolutePath, asset.Source);
            var extension      = assetSource.GetFileExtension();
            var buildStep      = new AssetBuildStep(AssetItem);

            // Find skeleton asset, if any
            AssetItem skeleton = null;

            if (asset.Skeleton != null)
            {
                skeleton = AssetItem.Package.FindAssetFromAttachedReference(asset.Skeleton);
            }

            var sourceBuildStep = ImportModelCommand.Create(extension);

            if (sourceBuildStep == null)
            {
                result.Error("No importer found for model extension '{0}. The model '{1}' can't be imported.", extension, assetSource);
                return;
            }

            sourceBuildStep.Mode                = ImportModelCommand.ExportMode.Animation;
            sourceBuildStep.SourcePath          = assetSource;
            sourceBuildStep.Location            = urlInStorage;
            sourceBuildStep.AnimationRepeatMode = asset.RepeatMode;
            sourceBuildStep.AnimationRootMotion = asset.RootMotion;
            sourceBuildStep.ScaleImport         = asset.ScaleImport;
            sourceBuildStep.SkeletonUrl         = skeleton?.Location;

            var additiveAnimationAsset = asset as AdditiveAnimationAsset;

            if (additiveAnimationAsset != null)
            {
                var baseUrlInStorage   = urlInStorage + "_animation_base";
                var sourceUrlInStorage = urlInStorage + "_animation_source";

                var baseAssetSource = UPath.Combine(assetDirectory, additiveAnimationAsset.BaseSource);
                var baseExtension   = baseAssetSource.GetFileExtension();

                sourceBuildStep.Location = sourceUrlInStorage;

                var baseBuildStep = ImportModelCommand.Create(extension);
                if (baseBuildStep == null)
                {
                    result.Error("No importer found for model extension '{0}. The model '{1}' can't be imported.", baseExtension, baseAssetSource);
                    return;
                }

                baseBuildStep.Mode                = ImportModelCommand.ExportMode.Animation;
                baseBuildStep.SourcePath          = baseAssetSource;
                baseBuildStep.Location            = baseUrlInStorage;
                baseBuildStep.AnimationRepeatMode = asset.RepeatMode;
                baseBuildStep.AnimationRootMotion = asset.RootMotion;
                baseBuildStep.ScaleImport         = asset.ScaleImport;
                baseBuildStep.SkeletonUrl         = skeleton?.Location;

                // Import base and main animation
                buildStep.Add(sourceBuildStep);
                buildStep.Add(baseBuildStep);

                // Wait for both import fbx commands to be completed
                buildStep.Add(new WaitBuildStep());

                // Generate the diff of those two animations
                buildStep.Add(new AdditiveAnimationCommand(urlInStorage, new AdditiveAnimationParameters(baseUrlInStorage, sourceUrlInStorage, additiveAnimationAsset.Mode)));
            }
            else
            {
                // Import the main animation
                buildStep.Add(sourceBuildStep);
            }

            result.BuildSteps = buildStep;
        }
        protected override void Compile(AssetCompilerContext context, string urlInStorage, UFile assetAbsolutePath, AnimationAsset asset, AssetCompilerResult result)
        {
            if (!EnsureSourceExists(result, asset, assetAbsolutePath))
            {
                return;
            }

            // Get absolute path of asset source on disk
            var assetDirectory = assetAbsolutePath.GetParent();
            var assetSource    = GetAbsolutePath(assetAbsolutePath, asset.Source);
            var extension      = assetSource.GetFileExtension();
            var buildStep      = new AssetBuildStep(AssetItem);

            var additiveAnimationAsset = asset as AdditiveAnimationAsset;

            if (additiveAnimationAsset != null)
            {
                var baseUrlInStorage   = urlInStorage + "_animation_base";
                var sourceUrlInStorage = urlInStorage + "_animation_source";

                var baseAssetSource = UPath.Combine(assetDirectory, additiveAnimationAsset.BaseSource);

                // Import base and main animation
                if (ImportFbxCommand.IsSupportingExtensions(extension))
                {
                    buildStep.Add(new ImportFbxCommand {
                        SourcePath = assetSource, Location = sourceUrlInStorage, ExportType = "animation", AnimationRepeatMode = asset.RepeatMode, ScaleImport = asset.ScaleImport
                    });
                    buildStep.Add(new ImportFbxCommand {
                        SourcePath = baseAssetSource, Location = baseUrlInStorage, ExportType = "animation", AnimationRepeatMode = asset.RepeatMode, ScaleImport = asset.ScaleImport
                    });
                }
                else if (ImportAssimpCommand.IsSupportingExtensions(extension))
                {
                    buildStep.Add(new ImportAssimpCommand {
                        SourcePath = assetSource, Location = sourceUrlInStorage, ExportType = "animation", AnimationRepeatMode = asset.RepeatMode, ScaleImport = asset.ScaleImport
                    });
                    buildStep.Add(new ImportAssimpCommand {
                        SourcePath = baseAssetSource, Location = baseUrlInStorage, ExportType = "animation", AnimationRepeatMode = asset.RepeatMode, ScaleImport = asset.ScaleImport
                    });
                }
                // Wait for both import fbx commands to be completed
                buildStep.Add(new WaitBuildStep());

                // Generate the diff of those two animations
                buildStep.Add(new AdditiveAnimationCommand(urlInStorage, new AdditiveAnimationParameters(baseUrlInStorage, sourceUrlInStorage, additiveAnimationAsset.Mode)));
            }
            else
            {
                // Import the main animation
                if (ImportFbxCommand.IsSupportingExtensions(extension))
                {
                    buildStep.Add(new ImportFbxCommand {
                        SourcePath = assetSource, Location = urlInStorage, ExportType = "animation", AnimationRepeatMode = asset.RepeatMode, ScaleImport = asset.ScaleImport
                    });
                }
                else if (ImportAssimpCommand.IsSupportingExtensions(extension))
                {
                    buildStep.Add(new ImportAssimpCommand {
                        SourcePath = assetSource, Location = urlInStorage, ExportType = "animation", AnimationRepeatMode = asset.RepeatMode, ScaleImport = asset.ScaleImport
                    });
                }
            }

            result.BuildSteps = buildStep;
        }