示例#1
0
        /// <inheritdoc />
        public Hash128 GetHash128(IBuildLogger log)
        {
#if UNITY_2019_3_OR_NEWER
            CacheEntry entry = BuildCacheUtility.GetCacheEntry(Scene);
#else
            CacheEntry entry = BuildCacheUtility.GetCacheEntry(ProcessedScene);
#endif
            HashSet <CacheEntry> hashObjects = new HashSet <CacheEntry>();
            using (log.ScopedStep(LogLevel.Verbose, $"Gather Objects", Command.fileName))
                Command.GatherSerializedObjectCacheEntries(hashObjects);

            List <Hash128> hashes = new List <Hash128>();
            using (log.ScopedStep(LogLevel.Verbose, $"Hashing Command", Command.fileName))
                hashes.Add(Command.GetHash128());
            using (log.ScopedStep(LogLevel.Verbose, $"Hashing UsageSet", Command.fileName))
                hashes.Add(UsageSet.GetHash128());
            using (log.ScopedStep(LogLevel.Verbose, $"Hashing ReferenceMap", Command.fileName))
                hashes.Add(ReferenceMap.GetHash128());
            using (log.ScopedStep(LogLevel.Verbose, $"Hashing Objects", Command.fileName))
                hashes.Add(HashingMethods.Calculate(hashObjects).ToHash128());
            hashes.Add(new Hash128(0, 0, 0, (uint)QualitySettingsApi.GetNumberOfLODsStripped()));
            hashes.Add(DependencyHash);

            return(HashingMethods.Calculate(hashes, Scene, entry).ToHash128());
        }
示例#2
0
        /// <inheritdoc />
        public Hash128 GetHash128(IBuildLogger log)
        {
            HashSet <CacheEntry> hashObjects = new HashSet <CacheEntry>();

            using (log.ScopedStep(LogLevel.Verbose, $"Gather Objects {GetType().Name}", Command.fileName))
            {
                if (Command.serializeObjects != null)
                {
                    foreach (var serializeObject in Command.serializeObjects)
                    {
                        hashObjects.Add(BuildCacheUtility.GetCacheEntry(serializeObject.serializationObject));
                    }
                }
            }

            List <Hash128> hashes = new List <Hash128>();

            using (log.ScopedStep(LogLevel.Verbose, $"Hashing Command", Command.fileName))
                hashes.Add(Command.GetHash128());
            using (log.ScopedStep(LogLevel.Verbose, $"Hashing UsageSet", Command.fileName))
                hashes.Add(UsageSet.GetHash128());
            using (log.ScopedStep(LogLevel.Verbose, $"Hashing ReferenceMap", Command.fileName))
                hashes.Add(ReferenceMap.GetHash128());
            using (log.ScopedStep(LogLevel.Verbose, $"Hashing Objects", Command.fileName))
                hashes.Add(HashingMethods.Calculate(hashObjects).ToHash128());
            hashes.Add(DependencyHash);

            return(HashingMethods.Calculate(hashes).ToHash128());
        }
示例#3
0
 CacheEntry GetCacheEntry(IWriteOperation operation, BuildSettings settings, BuildUsageTagGlobal globalUsage, bool onlySaveFirstSerializedObject)
 {
     using (m_Log.ScopedStep(LogLevel.Verbose, "GetCacheEntry", operation.Command.fileName))
     {
         var entry = new CacheEntry();
         entry.Type    = CacheEntry.EntryType.Data;
         entry.Guid    = HashingMethods.Calculate("WriteSerializedFiles", operation.Command.fileName).ToGUID();
         entry.Hash    = HashingMethods.Calculate(Version, operation.GetHash128(m_Log), settings.GetHash128(), globalUsage, onlySaveFirstSerializedObject, GetPlayerSettingsHash128(settings.target)).ToHash128();
         entry.Version = Version;
         return(entry);
     }
 }
示例#4
0
        static void CopyFileWithTimestampIfDifferent(string srcPath, string destPath, IBuildLogger log)
        {
            if (srcPath == destPath)
            {
                return;
            }

            DateTime time     = File.GetLastWriteTime(srcPath);
            DateTime destTime = File.Exists(destPath) ? File.GetLastWriteTime(destPath) : new DateTime();

            if (destTime == time)
            {
                return;
            }

            using (log.ScopedStep(LogLevel.Verbose, $"Copying File {srcPath} -> {destPath}"))
            {
                var directory = Path.GetDirectoryName(destPath);
                if (!string.IsNullOrEmpty(directory))
                {
                    Directory.CreateDirectory(directory);
                }
                File.Copy(srcPath, destPath, true);
            }
        }
示例#5
0
        /// <inheritdoc />
        public ReturnCode Run()
        {
            m_CustomAssets = new CustomAssets();
            m_GlobalUsage  = m_DependencyData.GlobalUsage;
            foreach (SceneDependencyInfo sceneInfo in m_DependencyData.SceneInfo.Values)
            {
                m_GlobalUsage |= sceneInfo.globalUsage;
            }

            foreach (CustomContent info in m_Content.CustomAssets)
            {
                if (!m_Tracker.UpdateInfoUnchecked(info.Asset.ToString()))
                {
                    return(ReturnCode.Canceled);
                }

                using (m_Log.ScopedStep(LogLevel.Verbose, "CustomAssetDependency", info.Asset.ToString()))
                    info.Processor(info.Asset, this);
            }

            // Add all the additional global usage for custom assets back into the dependency data result
            // for use in the write serialized file build task
            m_DependencyData.GlobalUsage |= m_CustomUsage;
            return(ReturnCode.Success);
        }
        static void AddLocalFilesToTreeIfNotEnumerated(AddressableAssetTree tree, string path, IBuildLogger logger)
        {
            AddressableAssetTree.TreeNode pathNode = tree.FindNode(path, true);

            if (pathNode == null || pathNode.HasEnumerated) // Already enumerated
            {
                return;
            }

            pathNode.HasEnumerated = true;
            using (logger.ScopedStep(LogLevel.Info, $"Enumerating {path}"))
            {
                foreach (string filename in Directory.EnumerateFileSystemEntries(path, "*.*", SearchOption.AllDirectories))
                {
                    if (!AddressableAssetUtility.IsPathValidForEntry(filename))
                    {
                        continue;
                    }
                    string convertedPath = filename.Replace('\\', '/');
                    var    node          = tree.FindNode(convertedPath, true);
                    node.IsFolder      = AssetDatabase.IsValidFolder(filename);
                    node.HasEnumerated = true;
                }
            }
        }
示例#7
0
        private static void ProcessCatalogEntriesForBuild(AddressableAssetsBuildContext aaContext, IBuildLogger log,
                                                          IEnumerable <AddressableAssetGroup> validGroups, AddressablesDataBuilderInput builderInput, IBundleWriteData writeData,
                                                          List <CachedAssetState> carryOverCachedState, Dictionary <string, string> bundleToInternalId)
        {
            using (log.ScopedStep(LogLevel.Info, "Catalog Entries."))
                using (var progressTracker = new UnityEditor.Build.Pipeline.Utilities.ProgressTracker())
                {
                    progressTracker.UpdateTask("Post Processing Catalog Entries");
                    Dictionary <string, ContentCatalogDataEntry> locationIdToCatalogEntryMap = BuildLocationIdToCatalogEntryMap(aaContext.locations);
                    if (builderInput.PreviousContentState != null)
                    {
                        ContentUpdateContext contentUpdateContext = new ContentUpdateContext()
                        {
                            BundleToInternalBundleIdMap = bundleToInternalId,
                            GuidToPreviousAssetStateMap = BuildGuidToCachedAssetStateMap(builderInput.PreviousContentState, aaContext.settings),
                            IdToCatalogDataEntryMap     = locationIdToCatalogEntryMap,
                            WriteData    = writeData,
                            ContentState = builderInput.PreviousContentState,
                            Registry     = builderInput.Registry,
                            PreviousAssetStateCarryOver = carryOverCachedState
                        };

                        RevertUnchangedAssetsToPreviousAssetState.Run(aaContext, contentUpdateContext);
                    }
                    else
                    {
                        foreach (var assetGroup in validGroups)
                        {
                            SetAssetEntriesBundleFileIdToCatalogEntryBundleFileId(assetGroup.entries, bundleToInternalId, writeData, locationIdToCatalogEntryMap);
                        }
                    }
                }

            bundleToInternalId.Clear();
        }
        public static List <string> EnumerateAddressableFolder(string path, AddressableAssetSettings settings, bool recurseAll, IBuildLogger logger = null)
        {
            if (!AssetDatabase.IsValidFolder(path))
            {
                throw new Exception($"Path {path} cannot be enumerated because it does not exist");
            }

            AddressableAssetTree tree = m_PrecomputedTree != null ? m_PrecomputedTree : BuildAddressableTree(settings, logger);

            if (tree == null)
            {
                return(new List <string>());
            }

            AddLocalFilesToTreeIfNotEnumerated(tree, path, logger);

            List <string> files = new List <string>();

            using (logger.ScopedStep(LogLevel.Info, $"Enumerating Addressables Tree {path}"))
            {
                foreach (string file in tree.Enumerate(path, recurseAll))
                {
                    if (BuiltinSceneCache.Contains(file))
                    {
                        continue;
                    }
                    files.Add(file);
                }
            }
            return(files);
        }
示例#9
0
        /// <summary>
        /// Build the specified data with the provided builderInput.  This is the public entry point.
        ///  Child class overrides should use <see cref="BuildDataImplementation{TResult}"/>
        /// </summary>
        /// <typeparam name="TResult">The type of data to build.</typeparam>
        /// <param name="builderInput">The builderInput object used in the build.</param>
        /// <returns>The build data result.</returns>
        public TResult BuildData <TResult>(AddressablesDataBuilderInput builderInput) where TResult : IDataBuilderResult
        {
            if (!CanBuildData <TResult>())
            {
                var message = "Data builder " + Name + " cannot build requested type: " + typeof(TResult);
                Debug.LogError(message);
                return(AddressableAssetBuildResult.CreateResult <TResult>(null, 0, message));
            }

            m_Log = (builderInput.Logger != null) ? builderInput.Logger : new BuildLog();

            AddressablesRuntimeProperties.ClearCachedPropertyValues();

            TResult result;

            // Append the file registry to the results
            using (m_Log.ScopedStep(LogLevel.Info, $"Building {this.Name}"))
            {
                result = BuildDataImplementation <TResult>(builderInput);
                if (result != null)
                {
                    result.FileRegistry = builderInput.Registry;
                }
            }

            if (builderInput.Logger == null && m_Log != null)
            {
                WriteBuildLog((BuildLog)m_Log, Path.GetDirectoryName(Application.dataPath) + "/Library/com.unity.addressables");
            }

            return(result);
        }
 static void BeginPrecomputedEnumerationSession(AddressableAssetSettings settings, bool prepopulateAssetsFolder, IBuildLogger logger)
 {
     using (logger.ScopedStep(LogLevel.Info, "AddressablesFileEnumeration.BeginPrecomputedEnumerationSession"))
     {
         m_PrecomputedTree = BuildAddressableTree(settings, logger);
         if (m_PrecomputedTree != null && prepopulateAssetsFolder)
         {
             AddLocalFilesToTreeIfNotEnumerated(m_PrecomputedTree, "Assets", logger);
         }
     }
 }
示例#11
0
 static void CopyToOutputLocation(string writePath, string finalPath, IBuildLogger log)
 {
     if (finalPath != writePath)
     {
         using (log.ScopedStep(LogLevel.Verbose, $"Copying From Cache {writePath} -> {finalPath}"))
         {
             var directory = Path.GetDirectoryName(finalPath);
             Directory.CreateDirectory(directory);
             File.Copy(writePath, finalPath, true);
         }
     }
 }
示例#12
0
        /// <inheritdoc />
        public Hash128 GetHash128(IBuildLogger log)
        {
            HashSet <CacheEntry> hashObjects = new HashSet <CacheEntry>();

            using (log.ScopedStep(LogLevel.Verbose, $"Gather Objects {GetType().Name}", Command.fileName))
                Command.GatherSerializedObjectCacheEntries(hashObjects);

            List <Hash128> hashes = new List <Hash128>();

            using (log.ScopedStep(LogLevel.Verbose, $"Hashing Command", Command.fileName))
                hashes.Add(Command.GetHash128());
            using (log.ScopedStep(LogLevel.Verbose, $"Hashing UsageSet", Command.fileName))
                hashes.Add(UsageSet.GetHash128());
            using (log.ScopedStep(LogLevel.Verbose, $"Hashing ReferenceMap", Command.fileName))
                hashes.Add(ReferenceMap.GetHash128());
            using (log.ScopedStep(LogLevel.Verbose, $"Hashing Objects", Command.fileName))
                hashes.Add(HashingMethods.Calculate(hashObjects).ToHash128());
            hashes.Add(DependencyHash);

            return(HashingMethods.Calculate(hashes).ToHash128());
        }
 static void PostArchiveProcessing(List <ArchiveWorkItem> items, List <List <string> > assetFileList, Dictionary <string, string> filenameToBundleName, IBuildLogger log)
 {
     using (log.ScopedStep(LogLevel.Info, "PostArchiveProcessing"))
     {
         Dictionary <string, string[]> bundleDependencies = CalculateBundleDependencies(assetFileList, filenameToBundleName);
         foreach (ArchiveWorkItem item in items)
         {
             // apply bundle dependencies
             item.ResultDetails.Dependencies = bundleDependencies.ContainsKey(item.BundleName) ? bundleDependencies[item.BundleName] : new string[0];
             item.ResultDetails.Hash         = CalculateHashVersion(item, item.ResultDetails.Dependencies);
         }
     }
 }
        /// <summary>
        /// Build the specified data with the provided builderInput.  This is the public entry point.
        ///  Child class overrides should use <see cref="BuildDataImplementation{TResult}"/>
        /// </summary>
        /// <typeparam name="TResult">The type of data to build.</typeparam>
        /// <param name="builderInput">The builderInput object used in the build.</param>
        /// <returns>The build data result.</returns>
        public TResult BuildData <TResult>(AddressablesDataBuilderInput builderInput) where TResult : IDataBuilderResult
        {
            if (!CanBuildData <TResult>())
            {
                var message = "Data builder " + Name + " cannot build requested type: " + typeof(TResult);
                Debug.LogError(message);
                return(AddressableAssetBuildResult.CreateResult <TResult>(null, 0, message));
            }

            m_Log = (builderInput.Logger != null) ? builderInput.Logger : new BuildLog();

            AddressablesRuntimeProperties.ClearCachedPropertyValues();

            TResult result = default;

            // Append the file registry to the results
            using (m_Log.ScopedStep(LogLevel.Info, $"Building {this.Name}"))
            {
                try
                {
                    result = BuildDataImplementation <TResult>(builderInput);
                }
                catch (Exception e)
                {
                    string errMessage;
                    if (e.Message == "path")
                    {
                        errMessage = "Invalid path detected during build. Check for unmatched brackets in your active profile's variables.";
                    }
                    else
                    {
                        errMessage = e.Message;
                    }

                    Debug.LogError(errMessage);
                    return(AddressableAssetBuildResult.CreateResult <TResult>(null, 0, errMessage));
                }
                if (result != null)
                {
                    result.FileRegistry = builderInput.Registry;
                }
            }

            if (builderInput.Logger == null && m_Log != null)
            {
                WriteBuildLog((BuildLog)m_Log, Path.GetDirectoryName(Application.dataPath) + "/" + Addressables.LibraryPath);
            }

            return(result);
        }
示例#15
0
        static void PostArchiveProcessing(List <ArchiveWorkItem> items, List <List <string> > assetFileList, Dictionary <string, string> filenameToBundleName, IBuildLogger log)
        {
            using (log.ScopedStep(LogLevel.Info, "PostArchiveProcessing"))
            {
                Dictionary <string, string[]> bundleDependencies = CalculateBundleDependencies(assetFileList, filenameToBundleName);
                foreach (ArchiveWorkItem item in items)
                {
                    // apply bundle dependencies
                    item.ResultDetails.Dependencies = bundleDependencies.ContainsKey(item.BundleName) ? bundleDependencies[item.BundleName] : new string[0];

                    // set the hash on the bundle result. must be applied here because the ToString of the Hash128 can't be called on a thread
                    item.ResultDetails.Hash = item.ResultHash;
                }
            }
        }
        internal static AddressableAssetTree BuildAddressableTree(AddressableAssetSettings settings, IBuildLogger logger = null)
        {
            using (logger.ScopedStep(LogLevel.Verbose, "BuildAddressableTree"))
            {
                if (!ExtractAddressablePaths(settings, out HashSet <string> paths))
                {
                    return(null);
                }

                AddressableAssetTree tree = new AddressableAssetTree();
                foreach (string path in paths)
                {
                    AddressableAssetTree.TreeNode node = tree.FindNode(path, true);
                    node.IsAddressable = true;
                }
                return(tree);
            }
        }
        void IRunCachedCallbacks <Item> .ProcessUncached(WorkItem <Item> item)
        {
            IWriteOperation op = m_WriteData.WriteOperations[item.Index];

            string targetDir = m_UseCache != null?m_UseCache.GetCachedArtifactsDirectory(item.entry) : m_Parameters.TempOutputFolder;

            Directory.CreateDirectory(targetDir);

            using (m_Log.ScopedStep(LogLevel.Info, $"Writing {op.GetType().Name}", op.Command.fileName))
                item.Context.Result = op.Write(targetDir, m_BuildSettings, m_GlobalUsage);

            item.Context.MetaData = CalculateFileMetadata(ref item.Context.Result);

            if (ScriptableBuildPipeline.slimWriteResults)
            {
                SlimifySerializedObjects(ref item.Context.Result);
            }
        }
        static private void ArchiveSingleItem(ArchiveWorkItem item, string tempOutputFolder, IBuildLogger log)
        {
            using (log.ScopedStep(LogLevel.Info, "ArchiveSingleItem", item.BundleName))
            {
                item.ResultDetails = new BundleDetails();
                string writePath = string.Format("{0}/{1}", tempOutputFolder, item.BundleName);
                if (!string.IsNullOrEmpty(item.CachedArtifactPath))
                {
                    writePath = item.CachedArtifactPath;
                }

                Directory.CreateDirectory(Path.GetDirectoryName(writePath));
                item.ResultDetails.FileName = item.OutputFilePath;
                item.ResultDetails.Crc      = ContentBuildInterface.ArchiveAndCompress(item.ResourceFiles.ToArray(), writePath, item.Compression);

                CopyFileWithTimestampIfDifferent(writePath, item.ResultDetails.FileName, log);
            }
        }
示例#19
0
        static private void ArchiveSingleItem(ArchiveWorkItem item, Dictionary <string, ulong> fileOffsets, string tempOutputFolder, IBuildLogger log)
        {
            using (log.ScopedStep(LogLevel.Info, $"Archive {item.BundleName}"))
            {
                item.ResultDetails = new BundleDetails();
                string writePath = string.Format("{0}/{1}", tempOutputFolder, item.BundleName);
                if (!string.IsNullOrEmpty(item.CachedArtifactPath))
                {
                    writePath = item.CachedArtifactPath;
                }

                Directory.CreateDirectory(Path.GetDirectoryName(writePath));
                item.ResultDetails.FileName = item.OutputFilePath;
                item.ResultDetails.Crc      = ContentBuildInterface.ArchiveAndCompress(item.ResourceFiles, writePath, item.Compression);
                item.ResultHash             = CalculateHashVersion(fileOffsets, item.ResourceFiles, item.ResultDetails.Dependencies);
                CopyToOutputLocation(writePath, item.ResultDetails.FileName, log);
            }
        }
示例#20
0
        static private bool ArchiveItems(List <ArchiveWorkItem> items, Dictionary <string, ulong> fileOffsets, string tempOutputFolder, IProgressTracker tracker, bool threaded, IBuildLogger log)
        {
            using (log.ScopedStep(LogLevel.Info, "ArchiveItems", threaded))
            {
                log?.AddEntry(LogLevel.Info, $"Archiving {items.Count} Bundles");
                if (threaded)
                {
                    return(ArchiveItemsThreaded(items, fileOffsets, tempOutputFolder, tracker, log));
                }

                foreach (ArchiveWorkItem item in items)
                {
                    if (tracker != null && !tracker.UpdateInfoUnchecked(item.BundleName))
                    {
                        return(false);
                    }

                    ArchiveSingleItem(item, fileOffsets, tempOutputFolder, log);
                }
                return(true);
            }
        }
#pragma warning restore 649

        /// <inheritdoc />
        public ReturnCode Run()
        {
            Dictionary <string, WriteCommand> fileToCommand;
            Dictionary <string, HashSet <ObjectIdentifier> > forwardObjectDependencies;
            Dictionary <string, HashSet <string> >           forwardFileDependencies;
            Dictionary <string, HashSet <GUID> >             reverseAssetDependencies;

            // BuildReferenceMap details what objects exist in other bundles that objects in a source bundle depend upon (forward dependencies)
            // BuildUsageTagSet details the conditional data needed to be written by objects in a source bundle that is in used by objects in other bundles (reverse dependencies)
            using (m_Log.ScopedStep(LogLevel.Info, $"Temporary Map Creations"))
            {
                fileToCommand             = m_WriteData.WriteOperations.ToDictionary(x => x.Command.internalName, x => x.Command);
                forwardObjectDependencies = new Dictionary <string, HashSet <ObjectIdentifier> >();
                forwardFileDependencies   = new Dictionary <string, HashSet <string> >();
                reverseAssetDependencies  = new Dictionary <string, HashSet <GUID> >();
                foreach (var pair in m_WriteData.AssetToFiles)
                {
                    GUID          asset = pair.Key;
                    List <string> files = pair.Value;

                    // The includes for an asset live in the first file, references could live in any file
                    forwardObjectDependencies.GetOrAdd(files[0], out HashSet <ObjectIdentifier> objectDependencies);
                    forwardFileDependencies.GetOrAdd(files[0], out HashSet <string> fileDependencies);

                    // Grab the list of object references for the asset or scene and add them to the forward dependencies hash set for this file (write command)
                    if (m_DependencyData.AssetInfo.TryGetValue(asset, out AssetLoadInfo assetInfo))
                    {
                        objectDependencies.UnionWith(assetInfo.referencedObjects);
                    }
                    if (m_DependencyData.SceneInfo.TryGetValue(asset, out SceneDependencyInfo sceneInfo))
                    {
                        objectDependencies.UnionWith(sceneInfo.referencedObjects);
                    }

                    // Grab the list of file references for the asset or scene and add them to the forward dependencies hash set for this file (write command)
                    // While doing so, also add the asset to the reverse dependencies hash set for all the other files it depends upon.
                    // We already ensure BuildReferenceMap & BuildUsageTagSet contain the objects in this write command in GenerateBundleCommands. So skip over the first file (self)
                    for (int i = 1; i < files.Count; i++)
                    {
                        fileDependencies.Add(files[i]);
                        reverseAssetDependencies.GetOrAdd(files[i], out HashSet <GUID> reverseDependencies);
                        reverseDependencies.Add(asset);
                    }
                }
            }

            // Using the previously generated forward dependency maps, update the BuildReferenceMap per WriteCommand to contain just the references that we care about
            using (m_Log.ScopedStep(LogLevel.Info, $"Populate BuildReferenceMaps"))
            {
                foreach (var operation in m_WriteData.WriteOperations)
                {
                    var internalName = operation.Command.internalName;

                    BuildReferenceMap referenceMap = m_WriteData.FileToReferenceMap[internalName];
                    if (!forwardObjectDependencies.TryGetValue(internalName, out var objectDependencies))
                    {
                        continue; // this bundle has no external dependencies
                    }
                    if (!forwardFileDependencies.TryGetValue(internalName, out var fileDependencies))
                    {
                        continue; // this bundle has no external dependencies
                    }
                    foreach (string file in fileDependencies)
                    {
                        WriteCommand dependentCommand = fileToCommand[file];
                        foreach (var serializedObject in dependentCommand.serializeObjects)
                        {
                            // Only add objects we are referencing. This ensures that new/removed objects to files we depend upon will not cause a rebuild
                            // of this file, unless are referencing the new/removed objects.
                            if (!objectDependencies.Contains(serializedObject.serializationObject))
                            {
                                continue;
                            }

                            referenceMap.AddMapping(file, serializedObject.serializationIndex, serializedObject.serializationObject);
                        }
                    }
                }
            }

            // Using the previously generate reverse dependency map, create the BuildUsageTagSet per WriteCommand to contain just the data that we care about
            using (m_Log.ScopedStep(LogLevel.Info, $"Populate BuildUsageTagSet"))
            {
                foreach (var operation in m_WriteData.WriteOperations)
                {
                    var internalName           = operation.Command.internalName;
                    BuildUsageTagSet fileUsage = m_WriteData.FileToUsageSet[internalName];
                    if (reverseAssetDependencies.TryGetValue(internalName, out var assetDependencies))
                    {
                        foreach (GUID asset in assetDependencies)
                        {
                            if (m_DependencyData.AssetUsage.TryGetValue(asset, out var assetUsage))
                            {
                                fileUsage.UnionWith(assetUsage);
                            }
                            if (m_DependencyData.SceneUsage.TryGetValue(asset, out var sceneUsage))
                            {
                                fileUsage.UnionWith(sceneUsage);
                            }
                        }
                    }
                    if (ReflectionExtensions.SupportsFilterToSubset)
                    {
                        fileUsage.FilterToSubset(m_WriteData.FileToObjects[internalName].ToArray());
                    }
                }
            }
            return(ReturnCode.Success);
        }
示例#22
0
        public static ReturnCode RunCachedOperation <T>(IBuildCache cache, IBuildLogger log, IProgressTracker tracker, List <WorkItem <T> > workItems,
                                                        IRunCachedCallbacks <T> cbs
                                                        )
        {
            using (log.ScopedStep(LogLevel.Info, "RunCachedOperation"))
            {
                List <CacheEntry>    cacheEntries   = null;
                List <WorkItem <T> > nonCachedItems = workItems;
                var cachedItems = new List <WorkItem <T> >();

                for (int i = 0; i < workItems.Count; i++)
                {
                    workItems[i].Index = i;
                }

                IList <CachedInfo> cachedInfo = null;

                if (cache != null)
                {
                    using (log.ScopedStep(LogLevel.Info, "Creating Cache Entries"))
                        for (int i = 0; i < workItems.Count; i++)
                        {
                            workItems[i].entry = cbs.CreateCacheEntry(workItems[i]);
                        }

                    cacheEntries = workItems.Select(i => i.entry).ToList();

                    using (log.ScopedStep(LogLevel.Info, "Load Cached Data"))
                        cache.LoadCachedData(cacheEntries, out cachedInfo);

                    cachedItems    = workItems.Where(x => cachedInfo[x.Index] != null).ToList();
                    nonCachedItems = workItems.Where(x => cachedInfo[x.Index] == null).ToList();
                }

                using (log.ScopedStep(LogLevel.Info, "Process Entries"))
                    foreach (WorkItem <T> item in nonCachedItems)
                    {
                        if (!tracker.UpdateInfoUnchecked(item.StatusText))
                        {
                            return(ReturnCode.Canceled);
                        }
                        cbs.ProcessUncached(item);
                    }

                using (log.ScopedStep(LogLevel.Info, "Process Cached Entries"))
                    foreach (WorkItem <T> item in cachedItems)
                    {
                        cbs.ProcessCached(item, cachedInfo[item.Index]);
                    }

                foreach (WorkItem <T> item in workItems)
                {
                    cbs.PostProcess(item);
                }

                if (cache != null)
                {
                    List <CachedInfo> uncachedInfo;
                    using (log.ScopedStep(LogLevel.Info, "Saving to Cache"))
                    {
                        using (log.ScopedStep(LogLevel.Info, "Creating Cached Infos"))
                            uncachedInfo = nonCachedItems.Select((item) => cbs.CreateCachedInfo(item)).ToList();
                        cache.SaveCachedData(uncachedInfo);
                    }
                }

                log.AddEntrySafe(LogLevel.Info, $"Total Entries: {workItems.Count}, Processed: {nonCachedItems.Count}, Cached: {cachedItems.Count}");
                return(ReturnCode.Success);
            }
        }