WuhuIslandTesting/Library/PackageCache/com.unity.scriptablebuildpipeline@1.21.5/Editor/Tasks/UpdateBundleObjectLayout.cs
2025-01-07 02:06:59 +01:00

143 lines
6.1 KiB
C#

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using UnityEditor.Build.Content;
using UnityEditor.Build.Pipeline.Injector;
using UnityEditor.Build.Pipeline.Interfaces;
using UnityEditor.Build.Pipeline.Utilities;
using UnityEditor.Build.Utilities;
namespace UnityEditor.Build.Pipeline.Tasks
{
/// <summary>
/// Updates the layout for bundle objects.
/// </summary>
public class UpdateBundleObjectLayout : IBuildTask
{
/// <inheritdoc />
public int Version { get { return 1; } }
#pragma warning disable 649
[InjectContext(ContextUsage.In, true)]
IBundleExplictObjectLayout m_Layout;
[InjectContext]
IBundleBuildContent m_Content;
[InjectContext(ContextUsage.In)]
IDependencyData m_DependencyData;
[InjectContext]
IBundleWriteData m_WriteData;
[InjectContext(ContextUsage.In)]
IDeterministicIdentifiers m_PackingMethod;
[InjectContext(ContextUsage.In, true)]
IBuildLogger m_Log;
#pragma warning restore 649
/// <inheritdoc />
public ReturnCode Run()
{
if (m_Layout == null || m_Layout.ExplicitObjectLocation.IsNullOrEmpty())
return ReturnCode.SuccessNotRun;
var ObjectToAssetReferences = new Dictionary<ObjectIdentifier, List<GUID>>();
var ObjectToFiles = new Dictionary<ObjectIdentifier, List<string>>();
using (m_Log.ScopedStep(LogLevel.Info, "PopulateReferencesMaps", true))
{
var task = Task.Run(() =>
{
using (m_Log.ScopedStep(LogLevel.Info, "Populate Assets Map", $"Count={m_DependencyData.AssetInfo.Count}"))
{
foreach (KeyValuePair<GUID, AssetLoadInfo> dependencyPair in m_DependencyData.AssetInfo)
{
PopulateReferencesMap(dependencyPair.Key, dependencyPair.Value.includedObjects, ObjectToAssetReferences);
PopulateReferencesMap(dependencyPair.Key, dependencyPair.Value.referencedObjects, ObjectToAssetReferences);
}
}
using (m_Log.ScopedStep(LogLevel.Info, "Populate Scenes Map", $"Count={m_DependencyData.SceneInfo.Count}"))
{
foreach (KeyValuePair<GUID, SceneDependencyInfo> dependencyPair in m_DependencyData.SceneInfo)
PopulateReferencesMap(dependencyPair.Key, dependencyPair.Value.referencedObjects, ObjectToAssetReferences);
}
});
using (m_Log.ScopedStep(LogLevel.Info, "Populate Files Map", $"Count={m_WriteData.FileToObjects.Count}"))
{
foreach (KeyValuePair<string, List<ObjectIdentifier>> filePair in m_WriteData.FileToObjects)
PopulateReferencesMap(filePair.Key, filePair.Value, ObjectToFiles);
}
task.Wait();
}
using (m_Log.ScopedStep(LogLevel.Info, "UpdateWriteData"))
{
foreach (var group in m_Layout.ExplicitObjectLocation.GroupBy(s => s.Value))
{
IEnumerable<ObjectIdentifier> objectIDs = group.Select(s => s.Key);
string bundleName = group.Key;
string internalName = string.Format(CommonStrings.AssetBundleNameFormat, m_PackingMethod.GenerateInternalFileName(bundleName));
foreach (var objectID in objectIDs)
{
UpdateAssetToFilesMap(internalName, ObjectToAssetReferences[objectID], m_WriteData.AssetToFiles);
RemoveObjectIDFromFiles(objectID, ObjectToFiles[objectID], m_WriteData.FileToObjects);
}
// Add new mapping for File to Bundle
UpdateFileToBundleMap(bundleName, internalName, m_WriteData.FileToBundle, m_Content.BundleLayout);
// Update File to Object map
UpdateFileToObjectMap(internalName, objectIDs, m_WriteData.FileToObjects);
}
}
return ReturnCode.Success;
}
internal static void PopulateReferencesMap<T>(T key, IList<ObjectIdentifier> objects, Dictionary<ObjectIdentifier, List<T>> map)
{
foreach (var obj in objects)
{
map.GetOrAdd(obj, out var set);
set.Add(key);
}
}
internal static void UpdateAssetToFilesMap(string file, List<GUID> assetsToUpdate, Dictionary<GUID, List<string>> AssetToFiles)
{
foreach (var asset in assetsToUpdate)
{
var assetFiles = AssetToFiles[asset];
if (!assetFiles.Contains(file))
assetFiles.Add(file);
}
}
internal static void RemoveObjectIDFromFiles(ObjectIdentifier objectID, List<string> files, Dictionary<string, List<ObjectIdentifier>> FileToObjects)
{
foreach (var file in files)
FileToObjects[file].Remove(objectID);
}
internal static void UpdateFileToBundleMap(string bundleName, string file, Dictionary<string, string> FileToBundle, Dictionary<string, List<GUID>> BundleLayout)
{
if (!FileToBundle.ContainsKey(file))
{
FileToBundle.Add(file, bundleName);
// NOTE: We want the output result to know about the new bundle, but since we are only
// assigning individual objects to this bundle and not full assets, the asset list will be empty
BundleLayout.Add(bundleName, new List<GUID>());
}
}
internal static void UpdateFileToObjectMap(string file, IEnumerable<ObjectIdentifier> newObjectIDs, Dictionary<string, List<ObjectIdentifier>> FileToObjects)
{
// This is called after remove, thus we can just AddRange as we already know these objects are not in any file
FileToObjects.GetOrAdd(file, out var objectIDs);
objectIDs.AddRange(newObjectIDs);
}
}
}