Ejemplo n.º 1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="BuildDependencyInfo"/> structure.
 /// </summary>
 /// <param name="assetType">The type of asset targeted by this dependency info.</param>
 /// <param name="compilationContext">The compilation context in which to compile the target asset.</param>
 /// <param name="dependencyType">The type of dependency.</param>
 public BuildDependencyInfo(Type assetType, Type compilationContext, BuildDependencyType dependencyType)
 {
     if (!typeof(Asset).IsAssignableFrom(assetType))
     {
         throw new ArgumentException($@"{nameof(assetType)} should inherit from Asset", nameof(assetType));
     }
     if (!typeof(ICompilationContext).IsAssignableFrom(compilationContext))
     {
         throw new ArgumentException($@"{nameof(compilationContext)} should inherit from ICompilationContext", nameof(compilationContext));
     }
     AssetType          = assetType;
     CompilationContext = compilationContext;
     DependencyType     = dependencyType;
 }
Ejemplo n.º 2
0
        public async Task Build(AssetItem asset, BuildDependencyType dependencyType = BuildDependencyType.Runtime)
        {
            if (isDisposed)
            {
                throw new ObjectDisposedException(nameof(GameStudioDatabase));
            }

            var buildUnit = new EditorGameBuildUnit(asset, CompilerContext, AssetDependenciesCompiler);

            try
            {
                assetBuilderService.PushBuildUnit(buildUnit);
                await buildUnit.Wait();
            }
            catch (Exception e)
            {
                Logger?.Error($"An error occurred while building the scene: {e.Message}", e);
                return;
            }

            // Merge build result into the database
            using ((await databaseLock.ReserveSyncLock()).Lock())
            {
                if (isDisposed)
                {
                    return;
                }

                if (buildUnit.Failed)
                {
                    // Build failed => unregister object
                    // 1. If it is first-time scene loading and one of sub-asset failed, it will be in this state, but we don't care
                    // since database will be empty at that point (it won't have any effect)
                    // 2. The second case (the one we actually care about) happens when reloading a recently rebuilt individual asset (i.e. material or texture),
                    // this will actually remove it from database
                    database.Remove(new ObjectUrl(UrlType.Content, asset.Location));
                }

                foreach (var outputObject in buildUnit.OutputObjects)
                {
                    database[outputObject.Key] = outputObject.Value;
                }
            }
        }
Ejemplo n.º 3
0
 /// <summary>
 /// Indicates whether this <see cref="BuildAssetLink"/> has at all dependencies of the given flags.
 /// </summary>
 /// <param name="type">A bitset of <see cref="BuildDependencyType"/>.</param>
 /// <returns>True if it has all the given dependencies, false otherwise.</returns>
 public bool HasAll(BuildDependencyType type)
 {
     return((DependencyType & type) == type);
 }
Ejemplo n.º 4
0
 /// <summary>
 /// Indicates whether this <see cref="BuildAssetLink"/> has at least one of the dependency of the given flags.
 /// </summary>
 /// <param name="type">A bitset of <see cref="BuildDependencyType"/>.</param>
 /// <returns>True if it has at least one of the given dependencies, false otherwise.</returns>
 public bool HasOne(BuildDependencyType type)
 {
     return((DependencyType & type) != 0);
 }
Ejemplo n.º 5
0
 /// <summary>
 /// Initialize a new instance of the <see cref="BuildAssetLink"/> structure.
 /// </summary>
 /// <param name="source">The source asset of the dependency.</param>
 /// <param name="target">The target asset of the dependency.</param>
 /// <param name="dependencyType">The type of dependency.</param>
 public BuildAssetLink(BuildAssetNode source, BuildAssetNode target, BuildDependencyType dependencyType)
 {
     Source         = source;
     Target         = target;
     DependencyType = dependencyType;
 }
Ejemplo n.º 6
0
        private void Prepare(AssetCompilerResult finalResult, AssetCompilerContext context, AssetItem assetItem, [NotNull] Type compilationContext, HashSet <BuildAssetNode> visitedItems, Dictionary <AssetId, BuildStep> compiledItems, BuildStep parentBuildStep = null,
                             BuildDependencyType dependencyType = BuildDependencyType.Runtime)
        {
            if (compilationContext == null)
            {
                throw new ArgumentNullException(nameof(compilationContext));
            }
            var assetNode = BuildDependencyManager.FindOrCreateNode(assetItem, compilationContext);

            compiledItems.TryGetValue(assetNode.AssetItem.Id, out var assetBuildSteps);

            // Prevent re-entrancy in the same node
            if (visitedItems.Add(assetNode))
            {
                assetNode.Analyze(context);

                // Invoke the compiler to prepare the build step for this asset if the dependency needs to compile it (Runtime or CompileContent)
                if ((dependencyType & ~BuildDependencyType.CompileAsset) != 0 && assetBuildSteps == null)
                {
                    var mainCompiler = BuildDependencyManager.AssetCompilerRegistry.GetCompiler(assetItem.Asset.GetType(), assetNode.CompilationContext);
                    if (mainCompiler == null)
                    {
                        return;
                    }

                    var compilerResult = mainCompiler.Prepare(context, assetItem);

                    if ((dependencyType & BuildDependencyType.Runtime) == BuildDependencyType.Runtime && compilerResult.HasErrors) //allow Runtime dependencies to fail
                    {
                        //totally skip this asset but do not propagate errors!
                        return;
                    }

                    assetBuildSteps = compilerResult.BuildSteps;
                    compiledItems.Add(assetNode.AssetItem.Id, assetBuildSteps);

                    // Copy the log to the final result (note: this does not copy or forward the build steps)
                    compilerResult.CopyTo(finalResult);
                    if (compilerResult.HasErrors)
                    {
                        finalResult.Error($"Failed to prepare asset {assetItem.Location}");
                        return;
                    }

                    // Add the resulting build steps to the final
                    finalResult.BuildSteps.Add(assetBuildSteps);

                    AssetCompiled?.Invoke(this, new AssetCompiledArgs(assetItem, compilerResult));
                }

                // Go through the dependencies of the node and prepare them as well
                foreach (var reference in assetNode.References)
                {
                    var target = reference.Target;
                    Prepare(finalResult, context, target.AssetItem, target.CompilationContext, visitedItems, compiledItems, assetBuildSteps, reference.DependencyType);
                    if (finalResult.HasErrors)
                    {
                        return;
                    }
                }

                // If we didn't prepare any build step for this asset let's exit here.
                if (assetBuildSteps == null)
                {
                    return;
                }
            }

            // Link the created build steps to their parent step.
            if (parentBuildStep != null && assetBuildSteps != null && (dependencyType & BuildDependencyType.CompileContent) == BuildDependencyType.CompileContent) //only if content is required Content.Load
            {
                BuildStep.LinkBuildSteps(assetBuildSteps, parentBuildStep);
            }
        }