diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e67052..fd2635d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,16 @@ All notable changes to this package will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [0.0.8-preview] - 2018-03-27 +- Test rename & meta file cleanup +- Added documentation for shared classes / structs +- Updated inconsistent interface / class names +- Added missing parameter to IBuildParameters +- Ran spell check +- Moved IWriteOperation to Interfaces +- Update IWriteOperation properties to PascalCase +- Added IWriteOperation documentation + ## [0.0.6-preview] - 2018-03-20 - doc updates diff --git a/Editor/ContentPipeline.cs b/Editor/ContentPipeline.cs index 2b3d017..193983b 100644 --- a/Editor/ContentPipeline.cs +++ b/Editor/ContentPipeline.cs @@ -1,8 +1,8 @@ using System.Diagnostics; -using UnityEditor.Build.Interfaces; -using UnityEditor.Build.Utilities; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.Utilities; -namespace UnityEditor.Build.AssetBundle +namespace UnityEditor.Build.Pipeline.Content { public static class ContentPipeline { @@ -10,47 +10,8 @@ public static class ContentPipeline public static BuildCallbacks BuildCallbacks = new BuildCallbacks(); - public static ReturnCodes BuildContentPacks(IBuildParameters buildParameters, IBuildContent buildContent, out IBuildResults result) + public static ReturnCodes BuildAssetBundles(IBuildParameters buildParameters, IBundleBuildContent buildContent, out IBundleBuildResults result) { - var buildTimer = new Stopwatch(); - buildTimer.Start(); - - ReturnCodes exitCode; - result = new BuildBuildResults(); - - using (var progressTracker = new ProgressTracker()) - { - using (var buildCleanup = new BuildStateCleanup(buildParameters.TempOutputFolder)) - { - var buildContext = new BuildContext(buildParameters, buildContent, result, progressTracker); - buildContext.SetContextObject(new PrefabPackedIdentifiers()); - buildContext.SetContextObject(new BuildDependencyData()); - buildContext.SetContextObject(new BuildWriteData()); - buildContext.SetContextObject(BuildCallbacks); - - var pipeline = DefaultBuildTasks.Create(DefaultBuildTasks.Presets.AutopackReleaseContent, buildParameters.ScriptInfo == null); - exitCode = BuildTasksRunner.Validate(pipeline, buildContext); - if (exitCode >= ReturnCodes.Success) - exitCode = BuildTasksRunner.Run(pipeline, buildContext); - } - } - - buildTimer.Stop(); - if (exitCode >= ReturnCodes.Success) - BuildLogger.Log("Build Content successful in: {0:c}", buildTimer.Elapsed); - else if (exitCode == ReturnCodes.Canceled) - BuildLogger.LogWarning("Build Content canceled in: {0:c}", buildTimer.Elapsed); - else - BuildLogger.LogError("Build Content failed in: {0:c}. Error: {1}.", buildTimer.Elapsed, exitCode); - - return exitCode; - } - - public static ReturnCodes BuildAssetBundles(IBuildParameters buildParameters, IBundleContent bundleContent, out IBundleBuildResults result) - { - var buildTimer = new Stopwatch(); - buildTimer.Start(); - ReturnCodes exitCode; result = new BundleBuildResults(); @@ -58,7 +19,8 @@ public static ReturnCodes BuildAssetBundles(IBuildParameters buildParameters, IB { using (var buildCleanup = new BuildStateCleanup(buildParameters.TempOutputFolder)) { - var buildContext = new BuildContext(buildParameters, bundleContent, result, progressTracker); + var buildContext = new BuildContext(buildParameters, buildContent, result, progressTracker); + buildContext.SetContextObject(new BuildCache()); buildContext.SetContextObject(new Unity5PackedIdentifiers()); buildContext.SetContextObject(new BuildDependencyData()); buildContext.SetContextObject(new BundleWriteData()); @@ -70,16 +32,7 @@ public static ReturnCodes BuildAssetBundles(IBuildParameters buildParameters, IB exitCode = BuildTasksRunner.Run(pipeline, buildContext); } } - - buildTimer.Stop(); - if (exitCode >= ReturnCodes.Success) - BuildLogger.Log("Build Asset Bundles successful in: {0:c}", buildTimer.Elapsed); - else if (exitCode == ReturnCodes.Canceled) - BuildLogger.LogWarning("Build Asset Bundles canceled in: {0:c}", buildTimer.Elapsed); - else - BuildLogger.LogError("Build Asset Bundles failed in: {0:c}. Error: {1}.", buildTimer.Elapsed, exitCode); - return exitCode; } } -} \ No newline at end of file +} diff --git a/Editor/Interfaces/IBuildCache.cs b/Editor/Interfaces/IBuildCache.cs new file mode 100644 index 0000000..6080b5d --- /dev/null +++ b/Editor/Interfaces/IBuildCache.cs @@ -0,0 +1,115 @@ +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.Utilities; + +namespace UnityEditor.Build.Pipeline.Interfaces +{ + /// + /// Base interface for the Build Caching + /// + public interface IBuildCache : IContextObject + { + /// + /// Returns the relative directory path where dependency data can be cached for a specified cacheEntry. + /// + /// Valid CacheEntry to get directory path. + /// Relative directory path. + string GetDependencyCacheDirectory(CacheEntry cacheEntry); + + /// + /// Returns the relative directory path where artifact data can be cached for a specified cacheEntry. + /// + /// Valid CacheEntry to get directory path. + /// Relative directory path. + string GetArtifactCacheDirectory(CacheEntry cacheEntry); + + /// + /// Gets a CacheEntry for an asset identified by its GUID. + /// + /// GUID identifier for an asset from the Asset Database + /// CacheEntry representing current asset. + CacheEntry GetCacheEntry(GUID asset); + + /// + /// Validates a cacheEntry and its dependencies. + /// + /// The entry in the cache to validate. + /// true if the cacheEntry is valid; otherwise, false. + bool IsCacheEntryValid(CacheEntry cacheEntry); + + /// + /// Tries to load from the cache generated dependency and usage data for a specified Assets's cacheEntry. + /// + /// The entry to load dependency data. + /// The Asset's generated dependency data to load. Parameter will not be chanced if data was unable to be loaded. + /// The Asset's generated usage data to load. Parameter will not be chanced if data was unable to be loaded. + /// true if the cache was able to load the specified data; otherwise, false. + bool TryLoadFromCache(CacheEntry cacheEntry, ref AssetLoadInfo info, ref BuildUsageTagSet usage); + + /// + /// Tries to load from the cache generated dependency and usage data for a specified Scene's cacheEntry. + /// + /// The entry to load dependency data. + /// The Scene's generated dependency data to load. + /// The Scene's generated usage data to load. + /// true if the cache was able to load the specified data; otherwise, false. + bool TryLoadFromCache(CacheEntry cacheEntry, ref SceneDependencyInfo info, ref BuildUsageTagSet usage); + + /// + /// Tries to load from the cache generated data for a specified cacheEntry. + /// + /// The type of results data to load. + /// The entry to load data. + /// The generated data to load. + /// true if the cache was able to load the specified data; otherwise, false. + bool TryLoadFromCache(CacheEntry cacheEntry, ref T results); + + /// + /// Tries to load from the cache generated data for a specified cacheEntry. + /// + /// The first type of results data to load. + /// The second type of results data to cache. + /// The entry to load data. + /// The first generated data to load. + /// The second generated data to load. + /// true if the cache was able to load the specified data; otherwise, false. + bool TryLoadFromCache(CacheEntry cacheEntry, ref T1 results1, ref T2 results2); + + /// + /// Tries to cache an Asset's cacheEntry and its generated dependency and usage data. + /// + /// The entry for caching dependency data. + /// The Asset's generated dependency data to cache. + /// The Asset's generated usage data to cache. + /// true if the cache was able to save the specified data; otherwise, false. + bool TrySaveToCache(CacheEntry cacheEntry, AssetLoadInfo info, BuildUsageTagSet usage); + + /// + /// Tries to cache a Scene's cacheEntry and its generated dependency and usage data. + /// + /// The entry for caching dependency data. + /// The Scene's generated dependency data to cache. + /// The Scene's generated usage data to cache. + /// true if the cache was able to save the specified data; otherwise, false. + bool TrySaveToCache(CacheEntry cacheEntry, SceneDependencyInfo info, BuildUsageTagSet usage); + + /// + /// Tries to cache generated data for the specified cacheEntry. + /// + /// The type of results data to cache. + /// The entry for caching data. + /// The generated data to cache. + /// true if the cache was able to save the specified data; otherwise, false. + bool TrySaveToCache(CacheEntry cacheEntry, T results); + + /// + /// Tries to cache generated data for the specified cacheEntry. + /// + /// The first type of results data to cache. + /// The second type of results data to cache. + /// The entry for caching data. + /// The first generated data to cache. + /// The second generated data to cache. + /// true if the cache was able to save the specified data; otherwise, false. + bool TrySaveToCache(CacheEntry cacheEntry, T1 results1, T2 results2); + } +} diff --git a/Editor/Tasks/GenerateReleaseAutoPacking.cs.meta b/Editor/Interfaces/IBuildCache.cs.meta similarity index 83% rename from Editor/Tasks/GenerateReleaseAutoPacking.cs.meta rename to Editor/Interfaces/IBuildCache.cs.meta index 37bd470..195bcde 100644 --- a/Editor/Tasks/GenerateReleaseAutoPacking.cs.meta +++ b/Editor/Interfaces/IBuildCache.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 920e048daf0d9024987234399aeb167e +guid: 717b55fbf36106b449169defda0705c7 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Editor/Interfaces/IBuildContent.cs b/Editor/Interfaces/IBuildContent.cs index 343fcc7..7602211 100644 --- a/Editor/Interfaces/IBuildContent.cs +++ b/Editor/Interfaces/IBuildContent.cs @@ -1,16 +1,36 @@ using System.Collections.Generic; -namespace UnityEditor.Build.Interfaces +namespace UnityEditor.Build.Pipeline.Interfaces { + /// + /// Base interface for feeding Assets to the Scriptable Build Pipeline. + /// public interface IBuildContent : IContextObject { + /// + /// List of Assets to include. + /// List Assets { get; } + + /// + /// List of Scenes to include. + /// List Scenes { get; } } - - public interface IBundleContent : IBuildContent + + /// + /// Base interface for feeding Assets with explicit Asset Bundle layout to the Scriptable Build Pipeline. + /// + public interface IBundleBuildContent : IBuildContent { + /// + /// Specific layout of asset bundles to assets or scenes. + /// Dictionary> BundleLayout { get; } + + /// + /// Custom loading identifiers to use for Assets or Scenes. + /// Dictionary Addresses { get; } } } \ No newline at end of file diff --git a/Editor/Interfaces/IBuildContext.cs b/Editor/Interfaces/IBuildContext.cs index 0f18e10..437ab99 100644 --- a/Editor/Interfaces/IBuildContext.cs +++ b/Editor/Interfaces/IBuildContext.cs @@ -1,40 +1,123 @@ using System; -namespace UnityEditor.Build.Interfaces +namespace UnityEditor.Build.Pipeline.Interfaces { + /// + /// Base interface for all objects that can be stored in . + /// public interface IContextObject { } + /// + /// Base interface that handles processing the callbacks after script building step. + /// public interface IScriptsCallback : IContextObject { + /// + /// Processes all the callbacks after script building step. + /// + /// Parameters passed into the build pipeline. + /// Results from the script building step. + /// Return code from processing the callbacks. ReturnCodes PostScripts(IBuildParameters buildParameters, IBuildResults buildResults); } - + + /// + /// Base interface for handling running the callbacks after dependency calculation step. + /// public interface IDependencyCallback : IContextObject { + /// + /// Processes all the callbacks after dependency calculation step. + /// + /// Parameters passed into the build pipeline. + /// Results from the dependency calculation step. + /// Return code from processing the callbacks. ReturnCodes PostDependency(IBuildParameters buildParameters, IDependencyData dependencyData); } - + + /// + /// Base interface for handling running the callbacks after packing step. + /// public interface IPackingCallback : IContextObject { + /// + /// Processes all the callbacks after packing step. + /// + /// Parameters passed into the build pipeline. + /// Results from the dependency calculation step. + /// Results from the packing step. + /// Return code from processing the callbacks. ReturnCodes PostPacking(IBuildParameters buildParameters, IDependencyData dependencyData, IWriteData writeData); } - + + /// + /// Base interface for handling running the callbacks after writing step. + /// public interface IWritingCallback : IContextObject { + /// + /// Processes all the callbacks after writing step. + /// + /// Parameters passed into the build pipeline. + /// Results from the dependency calculation step. + /// Results from the packing step. + /// Results from the writing step. + /// Return code from processing the callbacks. ReturnCodes PostWriting(IBuildParameters buildParameters, IDependencyData dependencyData, IWriteData writeData, IBuildResults buildResults); } + /// + /// Base interface for build data container system + /// public interface IBuildContext { + /// + /// Checks the build context for existence of a data that is of the specified type. + /// + /// Type of data to check for existence. + /// true if the context contains specified type of data; otherwise, false. bool ContainsContextObject() where T : IContextObject; + + /// + /// Checks the build context for existence of a data that is of the specified type. + /// + /// Type of data to check for existence. + /// true if the context contains specified type of data; otherwise, false. bool ContainsContextObject(Type type); + /// + /// Gets the data of the specified type contained in the build context. + /// + /// Type of data to return. + /// The type of data specified. T GetContextObject() where T : IContextObject; + + /// + /// Gets the data of the specified type contained in the build context. + /// + /// Type of data to return. + /// The type of data specified. IContextObject GetContextObject(Type type); + /// + /// Adds the data of the specified type to the build context. + /// + /// Type of data to add. + /// Object holding the data to add. void SetContextObject(IContextObject contextObject) where T : IContextObject; + + /// + /// Adds the data to the build context. Type will be inferred using Reflection. + /// + /// Object holding the data to add. void SetContextObject(IContextObject contextObject); + /// + /// Tries to get the data of the specified type contained in the build context. + /// + /// Type of data to return. + /// The object holding the data to be returned if found. + /// true if the context was able to returned the specified data; otherwise, false. bool TryGetContextObject(out T contextObject) where T : IContextObject; } } diff --git a/Editor/Interfaces/IBuildParameters.cs b/Editor/Interfaces/IBuildParameters.cs index 627989d..649d1c1 100644 --- a/Editor/Interfaces/IBuildParameters.cs +++ b/Editor/Interfaces/IBuildParameters.cs @@ -1,49 +1,71 @@ -using UnityEditor.Experimental.Build.AssetBundle; -using UnityEditor.Experimental.Build.Player; -using UnityEngine; +using UnityEditor.Build.Content; +using UnityEditor.Build.Player; -namespace UnityEditor.Build.Interfaces +namespace UnityEditor.Build.Pipeline.Interfaces { - //public interface IScriptParameters : IContextObject - //{ - // BuildTarget Target { get; set; } - // BuildTargetGroup Group { get; set; } - // ScriptCompilationOptions ScriptOptions { get; set; } - - // ScriptCompilationSettings GetScriptCompilationSettings(); - //} - - //public interface IContentParameters : IContextObject - //{ - // BuildTarget Target { get; set; } - // BuildTargetGroup Group { get; set; } - // TypeDB ScriptInfo { get; set; } - - // BuildSettings GetContentBuildSettings(); - - // BuildCompression GetCompressionForIdentifier(string identifier); - //} - - - public interface IBuildParameters : IContextObject//IScriptParameters, IContentParameters + /// + /// Base interface for the parameters container + /// + public interface IBuildParameters : IContextObject { + /// + /// Target build platform. + /// BuildTarget Target { get; set; } + + /// + /// Target build platform group. + /// BuildTargetGroup Group { get; set; } + + /// + /// The set of build flags to use for building content. + /// + ContentBuildFlags ContentBuildFlags { get; set; } + /// + /// Scripting type information to use when building content. + /// Setting this to a previously cached value will prevent the default script compiling step. + /// TypeDB ScriptInfo { get; set; } + /// + /// Script compilation options to use for the script compiling step. + /// ScriptCompilationOptions ScriptOptions { get; set; } + /// + /// Final output location where built content will be written. + /// string OutputFolder { get; set; } - string TempOutputFolder { get; } - bool UseCache { get; set; } - string GetTempOrCacheBuildPath(Hash128 hash); + /// + /// Temporary location to be used for artifacts generated during the build but are not part of the final output. + /// + string TempOutputFolder { get; set; } + /// + /// Enables the use of the build cache if set to true. + /// + bool UseCache { get; set; } + + /// + /// Constructs and returns the BuildSettings struct to use for content building. + /// + /// Returns the BuildSettings struct to use for content building. BuildSettings GetContentBuildSettings(); + /// + /// Constructs and returns the BuildCompression struct to use for the specified identifier. + /// + /// Identifier used to construct the BuildCompression struct. + /// Returns the BuildCompression struct to use for a specific identifier. BuildCompression GetCompressionForIdentifier(string identifier); - + + /// + /// Constructs and returns the ScriptCompilationSettings struct to use for script compiling. + /// + /// Returns the ScriptCompilationSettings struct to use for script compiling. ScriptCompilationSettings GetScriptCompilationSettings(); } } diff --git a/Editor/Interfaces/IBuildResults.cs b/Editor/Interfaces/IBuildResults.cs index 833483e..e257c22 100644 --- a/Editor/Interfaces/IBuildResults.cs +++ b/Editor/Interfaces/IBuildResults.cs @@ -1,17 +1,34 @@ using System.Collections.Generic; -using UnityEditor.Experimental.Build.AssetBundle; -using UnityEditor.Experimental.Build.Player; +using UnityEditor.Build.Content; +using UnityEditor.Build.Player; -namespace UnityEditor.Build.Interfaces +namespace UnityEditor.Build.Pipeline.Interfaces { + /// + /// Base interface for the build results container + /// public interface IBuildResults : IContextObject { + /// + /// Results from the script compiling step. + /// ScriptCompilationResult ScriptResults { get; set; } + + /// + /// Map of serialized file name to results for built content. + /// Dictionary WriteResults { get; } } + /// + /// Extended interface for Asset Bundle build results container. + /// + /// public interface IBundleBuildResults : IBuildResults { + /// + /// Map of Asset Bundle name to details about the built bundle. + /// Dictionary BundleInfos { get; } } } \ No newline at end of file diff --git a/Editor/Interfaces/IBuildTasks.cs b/Editor/Interfaces/IBuildTasks.cs index 7ca0f5c..afac574 100644 --- a/Editor/Interfaces/IBuildTasks.cs +++ b/Editor/Interfaces/IBuildTasks.cs @@ -1,13 +1,29 @@ using System; -namespace UnityEditor.Build.Interfaces +namespace UnityEditor.Build.Pipeline.Interfaces { + /// + /// Base interface of all build tasks. + /// public interface IBuildTask { + /// + /// Version identifier for the build task. + /// Primarily for caching. + /// int Version { get; } + /// + /// List of required data types in for this task to run correctly. + /// Primarily used to early out due to not having all the required data. + /// Type[] RequiredContextTypes { get; } + /// + /// Generic run method for build tasks + /// + /// that contains the required data types to run. + /// Return code with status information about success or failure causes. ReturnCodes Run(IBuildContext context); } } diff --git a/Editor/Interfaces/IDependencyData.cs b/Editor/Interfaces/IDependencyData.cs index 911c88d..463daf9 100644 --- a/Editor/Interfaces/IDependencyData.cs +++ b/Editor/Interfaces/IDependencyData.cs @@ -1,14 +1,31 @@ using System.Collections.Generic; -using UnityEditor.Experimental.Build.AssetBundle; +using UnityEditor.Build.Content; -namespace UnityEditor.Build.Interfaces +namespace UnityEditor.Build.Pipeline.Interfaces { + /// + /// Base interface for the dependency data container + /// public interface IDependencyData : IContextObject { + /// + /// Map of Asset to dependency data. + /// Dictionary AssetInfo { get; } + + /// + /// Map of Asset to usage data. + /// Dictionary AssetUsage { get; } + /// + /// Map of Scene to dependency data. + /// Dictionary SceneInfo { get; } + + /// + /// Map of Scene to usage data. + /// Dictionary SceneUsage { get; } } } \ No newline at end of file diff --git a/Editor/Interfaces/IDeterministicIdentifiers.cs b/Editor/Interfaces/IDeterministicIdentifiers.cs index f6c7e4b..e68caba 100644 --- a/Editor/Interfaces/IDeterministicIdentifiers.cs +++ b/Editor/Interfaces/IDeterministicIdentifiers.cs @@ -1,10 +1,24 @@ -using UnityEditor.Experimental.Build.AssetBundle; +using UnityEditor.Build.Content; -namespace UnityEditor.Build.Interfaces +namespace UnityEditor.Build.Pipeline.Interfaces { + /// + /// Base interface for the generating deterministic identifiers for different parts of the build pipeline. + /// public interface IDeterministicIdentifiers : IContextObject { + /// + /// Generates a deterministic internal file name from the passed in name. + /// + /// Name identifier for internal file name generation + /// Deterministic file name. string GenerateInternalFileName(string name); + + /// + /// Generates a deterministic id for a given object in the build. + /// + /// Object identifier to for id generation. + /// long representing the id of the objectID. long SerializationIndexFromObjectIdentifier(ObjectIdentifier objectID); } } \ No newline at end of file diff --git a/Editor/Interfaces/IProgressTracker.cs b/Editor/Interfaces/IProgressTracker.cs index 6c7edf8..2792d66 100644 --- a/Editor/Interfaces/IProgressTracker.cs +++ b/Editor/Interfaces/IProgressTracker.cs @@ -1,33 +1,32 @@ -using System.Text.RegularExpressions; - -namespace UnityEditor.Build.Interfaces +namespace UnityEditor.Build.Pipeline.Interfaces { + /// + /// Base interface for the build progress tracker + /// public interface IProgressTracker : IContextObject { + /// + /// Number of build tasks to run + /// int TaskCount { get; set; } + /// + /// Current 0.0f to 1.0f progress though the TaskCount + /// float Progress { get; } + /// + /// Increments and updated the title of the progress bar. + /// + /// The title to display on the progress bar. + /// false if the build should not continue due to user interaction with the progress bar; otherwise, true. bool UpdateTask(string taskTitle); + /// + /// Updates the secondary information display of the progress bar. + /// + /// The secondary information to display on the progress bar. + /// false if the build should not continue due to user interaction with the progress bar; otherwise, true. bool UpdateInfo(string taskInfo); } - - public static class TrackerExtensions - { - public static string HumanReadable(this string camelCased) - { - return Regex.Replace(camelCased, @"(\B[A-Z]+?(?=[A-Z][^A-Z])|\B[A-Z]+?(?=[^A-Z]))", " $1"); - } - - public static bool UpdateTaskUnchecked(this IProgressTracker tracker, string taskTitle) - { - return tracker == null || tracker.UpdateTask(taskTitle); - } - - public static bool UpdateInfoUnchecked(this IProgressTracker tracker, string taskInfo) - { - return tracker == null || tracker.UpdateInfo(taskInfo); - } - } } diff --git a/Editor/Interfaces/IWriteData.cs b/Editor/Interfaces/IWriteData.cs index bbbcf4a..99f943e 100644 --- a/Editor/Interfaces/IWriteData.cs +++ b/Editor/Interfaces/IWriteData.cs @@ -1,21 +1,49 @@ using System.Collections.Generic; -using UnityEditor.Build.WriteTypes; -using UnityEditor.Experimental.Build.AssetBundle; +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.WriteTypes; -namespace UnityEditor.Build.Interfaces +namespace UnityEditor.Build.Pipeline.Interfaces { + /// + /// Base interface for the write data container. + /// public interface IWriteData : IContextObject { + /// + /// Map of asset to file dependencies. + /// First dependency in the list is the main file for an asset. + /// Dictionary> AssetToFiles { get; } + + /// + /// Map of file to list of objects in that file + /// Dictionary> FileToObjects { get; } + /// + /// List of all write operations to serialize data to disk + /// List WriteOperations { get; } } + /// + /// Extended interface for Asset Bundle write data container. + /// public interface IBundleWriteData : IWriteData { + /// + /// Map of file name to bundle name + /// Dictionary FileToBundle { get; } + + /// + /// Map of file name to calculated usage set + /// Dictionary FileToUsageSet { get; } + + /// + /// Map of file name to calculated object references + /// Dictionary FileToReferenceMap { get; } } } \ No newline at end of file diff --git a/Editor/Interfaces/IWriteOperation.cs b/Editor/Interfaces/IWriteOperation.cs new file mode 100644 index 0000000..b59fd16 --- /dev/null +++ b/Editor/Interfaces/IWriteOperation.cs @@ -0,0 +1,45 @@ +using UnityEditor.Build.Content; +using UnityEngine; + +namespace UnityEditor.Build.Pipeline.Interfaces +{ + /// + /// Base interface for wrapping the different low level WriteSerializeFile API around a common high level Write function + /// + public interface IWriteOperation + { + /// + /// The specific write command containing the details about what to write to disk. + /// + /// + WriteCommand Command { get; set; } + + /// + /// The specific usage data for objects in the write command. + /// + /// + BuildUsageTagSet UsageSet { get; set; } + + /// + /// The specific reference data for objects in the write command. + /// + /// + + BuildReferenceMap ReferenceMap { get; set; } + + /// + /// Write function that wraps the low level WriteSerializeFile APIs that takes the common minimum set of parameters. + /// + /// The location to write data to disk. + /// The build settings to use for writing data. + /// The global usage to use for writing data. + /// The write results struct containing details about what was written to disk + WriteResult Write(string outputFolder, BuildSettings settings, BuildUsageTagGlobal globalUsage); + + /// + /// Optimized hash function for use with the Build Cache system. + /// + /// Unique hash for the contents of this write operation. + Hash128 GetHash128(); + } +} diff --git a/Editor/WriteTypes/IWriteOperation.cs.meta b/Editor/Interfaces/IWriteOperation.cs.meta similarity index 100% rename from Editor/WriteTypes/IWriteOperation.cs.meta rename to Editor/Interfaces/IWriteOperation.cs.meta diff --git a/Editor/LegacyBuildPipeline.cs b/Editor/LegacyBuildPipeline.cs index 735f9fc..702b0bc 100644 --- a/Editor/LegacyBuildPipeline.cs +++ b/Editor/LegacyBuildPipeline.cs @@ -1,28 +1,28 @@ -using UnityEditor.Build.AssetBundle; -using UnityEditor.Build.Interfaces; -using UnityEditor.Experimental.Build.AssetBundle; +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.Content; +using UnityEditor.Build.Pipeline.Interfaces; using UnityEngine; -namespace UnityEditor.Build +namespace UnityEditor.Build.Pipeline { public static class LegacyBuildPipeline { public static AssetBundleManifest BuildAssetBundles(string outputPath, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform) { - var buildInput = BundleBuildInterface.GenerateBuildInput(); - return BuildAssetBundles_Internal(outputPath, new BundleContent(buildInput), assetBundleOptions, targetPlatform); + var buildInput = ContentBuildInterface.GenerateAssetBundleBuilds(); + return BuildAssetBundles_Internal(outputPath, new BundleBuildContent(buildInput), assetBundleOptions, targetPlatform); } public static AssetBundleManifest BuildAssetBundles(string outputPath, AssetBundleBuild[] builds, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform) { - return BuildAssetBundles_Internal(outputPath, new BundleContent(builds), assetBundleOptions, targetPlatform); + return BuildAssetBundles_Internal(outputPath, new BundleBuildContent(builds), assetBundleOptions, targetPlatform); } - internal static AssetBundleManifest BuildAssetBundles_Internal(string outputPath, IBundleContent buildContent, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform) + internal static AssetBundleManifest BuildAssetBundles_Internal(string outputPath, IBundleBuildContent buildContent, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform) { var group = UnityEditor.BuildPipeline.GetBuildTargetGroup(targetPlatform); - var buildParams = new BuildParameters(targetPlatform, group, outputPath, ContentPipeline.kTempBuildPath); - + var buildParams = new BuildParameters(targetPlatform, group, outputPath); + if ((assetBundleOptions & BuildAssetBundleOptions.ChunkBasedCompression) != 0) buildParams.BundleCompression = BuildCompression.DefaultLZ4; else if ((assetBundleOptions & BuildAssetBundleOptions.UncompressedAssetBundle) != 0) @@ -34,7 +34,7 @@ internal static AssetBundleManifest BuildAssetBundles_Internal(string outputPath ReturnCodes exitCode = ContentPipeline.BuildAssetBundles(buildParams, buildContent, out results); if (exitCode < ReturnCodes.Success) return null; - + // TODO: Return Unity 5 Manifest return null; } diff --git a/Editor/ReturnCodes.cs b/Editor/ReturnCodes.cs index 00b2f23..55c3bcb 100644 --- a/Editor/ReturnCodes.cs +++ b/Editor/ReturnCodes.cs @@ -1,4 +1,4 @@ -namespace UnityEditor.Build +namespace UnityEditor.Build.Pipeline { public enum ReturnCodes { diff --git a/Editor/Shared/BuildBuildResults.cs b/Editor/Shared/BuildBuildResults.cs deleted file mode 100644 index dc06491..0000000 --- a/Editor/Shared/BuildBuildResults.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Collections.Generic; -using UnityEditor.Build.Interfaces; -using UnityEditor.Experimental.Build.AssetBundle; -using UnityEditor.Experimental.Build.Player; - -namespace UnityEditor.Build -{ - [Serializable] - public class BuildBuildResults : IBuildResults - { - public ScriptCompilationResult ScriptResults { get; set; } - public Dictionary WriteResults { get; private set; } - - public BuildBuildResults() - { - WriteResults = new Dictionary(); - } - } - - [Serializable] - public class BundleBuildResults : IBundleBuildResults - { - public ScriptCompilationResult ScriptResults { get; set; } - public Dictionary BundleInfos { get; private set; } - public Dictionary WriteResults { get; private set; } - - public BundleBuildResults() - { - BundleInfos = new Dictionary(); - WriteResults = new Dictionary(); - } - } -} diff --git a/Editor/Shared/BuildCallbacks.cs b/Editor/Shared/BuildCallbacks.cs index ae4863b..b04a56c 100644 --- a/Editor/Shared/BuildCallbacks.cs +++ b/Editor/Shared/BuildCallbacks.cs @@ -1,36 +1,60 @@ using System; -using UnityEditor.Build.Interfaces; +using UnityEditor.Build.Pipeline.Interfaces; -namespace UnityEditor.Build +namespace UnityEditor.Build.Pipeline { + /// + /// Basic implementation of IDependencyCallback, IPackingCallback, IWritingCallback, & IScriptsCallback. + /// Uses Func implementation for callbacks. , + /// , and + /// public class BuildCallbacks : IDependencyCallback, IPackingCallback, IWritingCallback, IScriptsCallback { + /// + /// Func delegate for the callback after scripts have been compiled. + /// public Func PostScriptsCallbacks { get; set; } + + /// + /// Func delegate for the callback after dependency calculation has occurred. + /// public Func PostDependencyCallback { get; set; } + + /// + /// Func delegate for the callback after packing has occurred. + /// public Func PostPackingCallback { get; set; } + + /// + /// Func delegate for the callback after writing content has occurred. + /// public Func PostWritingCallback { get; set; } - + + /// public ReturnCodes PostScripts(IBuildParameters buildParameters, IBuildResults buildResults) { if (PostScriptsCallbacks != null) return PostScriptsCallbacks(buildParameters, buildResults); return ReturnCodes.Success; } - + + /// public ReturnCodes PostDependency(IBuildParameters buildParameters, IDependencyData dependencyData) { if (PostDependencyCallback != null) return PostDependencyCallback(buildParameters, dependencyData); return ReturnCodes.Success; } - + + /// public ReturnCodes PostPacking(IBuildParameters buildParameters, IDependencyData dependencyData, IWriteData writeData) { if (PostPackingCallback != null) return PostPackingCallback(buildParameters, dependencyData, writeData); return ReturnCodes.Success; } - + + /// public ReturnCodes PostWriting(IBuildParameters buildParameters, IDependencyData dependencyData, IWriteData writeData, IBuildResults buildResults) { if (PostWritingCallback != null) diff --git a/Editor/Shared/BuildContent.cs b/Editor/Shared/BuildContent.cs index fa3b5fe..89648bb 100644 --- a/Editor/Shared/BuildContent.cs +++ b/Editor/Shared/BuildContent.cs @@ -1,19 +1,27 @@ using System; using System.Collections.Generic; -using System.Linq; -using UnityEditor.Build.Interfaces; -using UnityEditor.Build.Utilities; -using UnityEditor.Experimental.Build.AssetBundle; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.Utilities; -namespace UnityEditor.Build +namespace UnityEditor.Build.Pipeline { + /// + /// Basic implementation of IBuildContent. Stores the list of Assets to feed the Scriptable Build Pipeline. + /// + /// [Serializable] public class BuildContent : IBuildContent { + /// public List Assets { get; private set; } - + + /// public List Scenes { get; private set; } + /// + /// Default constructor, takes a set of Assets and converts them to the appropriate properties. + /// + /// The set of Assets identified by GUID to ensure are packaged with the build public BuildContent(IEnumerable assets) { Assets = new List(); @@ -30,44 +38,31 @@ public BuildContent(IEnumerable assets) } } } - + + /// + /// Basic implementation of IBundleBuildContent. Stores the list of Assets with explicit Asset Bundle layout to feed the Scriptable Build Pipeline. + /// + /// [Serializable] - public class BundleContent : IBundleContent + public class BundleBuildContent : IBundleBuildContent { + /// public List Assets { get; private set; } - + + /// public List Scenes { get; private set; } - + + /// public Dictionary Addresses { get; private set; } - + + /// public Dictionary> BundleLayout { get; private set; } - public BundleContent(BuildInput bundleInput) - { - Assets = new List(); - Scenes = new List(); - Addresses = new Dictionary(); - BundleLayout = new Dictionary>(); - - foreach (BuildInput.Definition bundle in bundleInput.definitions) - { - List guids; - BundleLayout.GetOrAdd(bundle.assetBundleName, out guids); - foreach (var assetInfo in bundle.explicitAssets) - { - guids.Add(assetInfo.asset); - Addresses.Add(assetInfo.asset, string.IsNullOrEmpty(assetInfo.address) ? AssetDatabase.GUIDToAssetPath(assetInfo.asset.ToString()) : assetInfo.address); - if (ValidationMethods.ValidAsset(assetInfo.asset)) - Assets.Add(assetInfo.asset); - else if (ValidationMethods.ValidScene(assetInfo.asset)) - Scenes.Add(assetInfo.asset); - else - throw new ArgumentException(string.Format("Asset '{0}' is not a valid Asset or Scene.", assetInfo.asset)); - } - } - } - - public BundleContent(IEnumerable bundleBuilds) + /// + /// Default constructor, takes a set of AssetBundleBuild and converts them to the appropriate properties. + /// + /// The set of AssetbundleBuild to be built. + public BundleBuildContent(IEnumerable bundleBuilds) { Assets = new List(); Scenes = new List(); diff --git a/Editor/Shared/BuildContext.cs b/Editor/Shared/BuildContext.cs index 8c05076..7105372 100644 --- a/Editor/Shared/BuildContext.cs +++ b/Editor/Shared/BuildContext.cs @@ -1,25 +1,37 @@ using System; using System.Collections.Generic; -using UnityEditor.Build.Interfaces; +using UnityEditor.Build.Pipeline.Interfaces; -namespace UnityEditor.Build +namespace UnityEditor.Build.Pipeline { + /// + /// Basic implementation of IBuildContext. Stores data generated during a build. + /// + /// public class BuildContext : IBuildContext { Dictionary m_ContextObjects; + /// + /// Default constructor + /// public BuildContext() { m_ContextObjects = new Dictionary(); } + /// + /// Default constructor, adds the passed in parameters to the context. + /// + /// The set of initial parameters to add to the context. public BuildContext(params IContextObject[] buildParams) { m_ContextObjects = new Dictionary(); foreach (var buildParam in buildParams) SetContextObject(buildParam); } - + + /// public void SetContextObject(IContextObject contextObject) where T : IContextObject { var type = typeof(T); @@ -29,7 +41,8 @@ public void SetContextObject(IContextObject contextObject) where T : IContext throw new InvalidOperationException(string.Format("'{0}' is not of passed in type '{1}'.", contextObject.GetType(), type)); m_ContextObjects[typeof(T)] = contextObject; } - + + /// public void SetContextObject(IContextObject contextObject) { var iCType = typeof(IContextObject); @@ -41,27 +54,32 @@ public void SetContextObject(IContextObject contextObject) m_ContextObjects[iType] = contextObject; } } - + + /// public bool ContainsContextObject() where T : IContextObject { return ContainsContextObject(typeof(T)); } - + + /// public bool ContainsContextObject(Type type) { return m_ContextObjects.ContainsKey(type); } - + + /// public T GetContextObject() where T : IContextObject { return (T)m_ContextObjects[typeof(T)]; } - + + /// public IContextObject GetContextObject(Type type) { return m_ContextObjects[type]; } - + + /// public bool TryGetContextObject(out T contextObject) where T : IContextObject { IContextObject cachedContextObject; diff --git a/Editor/Shared/BuildDependencyData.cs b/Editor/Shared/BuildDependencyData.cs index d9e431a..a70a5db 100644 --- a/Editor/Shared/BuildDependencyData.cs +++ b/Editor/Shared/BuildDependencyData.cs @@ -1,19 +1,30 @@ using System; using System.Collections.Generic; -using UnityEditor.Build.Interfaces; -using UnityEditor.Experimental.Build.AssetBundle; +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.Interfaces; -namespace UnityEditor.Build +namespace UnityEditor.Build.Pipeline { + /// + /// Basic implementation of IDependencyData. Stores the dependency and usage data calculated during a build. + /// + /// [Serializable] public class BuildDependencyData : IDependencyData { + /// public Dictionary AssetInfo { get; private set; } + /// public Dictionary AssetUsage { get; private set; } - + + /// public Dictionary SceneInfo { get; private set; } + /// public Dictionary SceneUsage { get; private set; } + /// + /// Default constructor, initializes properties to defaults + /// public BuildDependencyData() { AssetInfo = new Dictionary(); diff --git a/Editor/Shared/BuildParameters.cs b/Editor/Shared/BuildParameters.cs index e179d02..6f1de45 100644 --- a/Editor/Shared/BuildParameters.cs +++ b/Editor/Shared/BuildParameters.cs @@ -1,68 +1,92 @@ using System; -using System.IO; -using UnityEditor.Build.Interfaces; -using UnityEditor.Build.Utilities; -using UnityEditor.Experimental.Build.AssetBundle; -using UnityEditor.Experimental.Build.Player; -using UnityEngine; +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.Content; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Player; -namespace UnityEditor.Build +namespace UnityEditor.Build.Pipeline { + /// + /// Basic implementation of IBuildParameters. Stores the set of parameters passed into the Scriptable Build Pipeline. + /// + /// [Serializable] public class BuildParameters : IBuildParameters { + /// public BuildTarget Target { get; set; } + /// public BuildTargetGroup Group { get; set; } + /// + public ContentBuildFlags ContentBuildFlags { get; set; } + + /// public TypeDB ScriptInfo { get; set; } + /// public ScriptCompilationOptions ScriptOptions { get; set; } + /// + /// Default compression option to use for all built content files + /// public BuildCompression BundleCompression { get; set; } - + + /// public string OutputFolder { get; set; } - public string TempOutputFolder { get; protected set; } + + string m_TempOutputFolder; + /// + public string TempOutputFolder + { + get { return m_TempOutputFolder; } + set + { + if (string.IsNullOrEmpty(value)) + throw new ArgumentException("Argument cannot be null or empty.", "TempOutputFolder"); + m_TempOutputFolder = value; + } + } + /// public bool UseCache { get; set; } - public BuildParameters(BuildTarget target, BuildTargetGroup group, string outputFolder, string tempOutputFolder) + /// + /// Default constructor, requires the target, group and output parameters at minimum for a successful build. + /// + /// The target for building content. + /// The group for building content. + /// The final output location for built content. + public BuildParameters(BuildTarget target, BuildTargetGroup group, string outputFolder) { if (string.IsNullOrEmpty(outputFolder)) throw new ArgumentException("Argument cannot be null or empty.", "outputFolder"); - if (string.IsNullOrEmpty(tempOutputFolder)) - throw new ArgumentException("Argument cannot be null or empty.", "tempOutputFolder"); Target = target; Group = group; // TODO: Validate target & group - + ScriptInfo = null; ScriptOptions = ScriptCompilationOptions.None; BundleCompression = BuildCompression.DefaultLZMA; OutputFolder = outputFolder; - TempOutputFolder = tempOutputFolder; + TempOutputFolder = ContentPipeline.kTempBuildPath; UseCache = true; } - - public string GetTempOrCacheBuildPath(Hash128 hash) - { - var path = TempOutputFolder; - if (UseCache) - path = BuildCache.GetPathForCachedArtifacts(hash); - Directory.CreateDirectory(path); - return path; - } - + + /// public BuildSettings GetContentBuildSettings() { return new BuildSettings { group = Group, target = Target, - typeDB = ScriptInfo + typeDB = ScriptInfo, + buildFlags = ContentBuildFlags }; } - + + /// public ScriptCompilationSettings GetScriptCompilationSettings() { return new ScriptCompilationSettings @@ -72,7 +96,8 @@ public ScriptCompilationSettings GetScriptCompilationSettings() options = ScriptOptions }; } - + + /// public BuildCompression GetCompressionForIdentifier(string identifier) { return BundleCompression; diff --git a/Editor/Shared/BuildResults.cs b/Editor/Shared/BuildResults.cs new file mode 100644 index 0000000..85b1d28 --- /dev/null +++ b/Editor/Shared/BuildResults.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Player; + +namespace UnityEditor.Build.Pipeline +{ + /// + /// Basic implementation of IBuildResults. Stores the results for script compilation and content building. + /// + /// + [Serializable] + public class BuildResults : IBuildResults + { + /// + public ScriptCompilationResult ScriptResults { get; set; } + /// + public Dictionary WriteResults { get; private set; } + + /// + /// Default constructor, initializes properties to defaults + /// + public BuildResults() + { + WriteResults = new Dictionary(); + } + } + + /// + /// Basic implementation of IBundleBuildResults. Stores the results for script compilation and asset bundle building. + /// + /// + [Serializable] + public class BundleBuildResults : IBundleBuildResults + { + /// + public ScriptCompilationResult ScriptResults { get; set; } + /// + public Dictionary BundleInfos { get; private set; } + /// + public Dictionary WriteResults { get; private set; } + + /// + /// Default constructor, initializes properties to defaults + /// + public BundleBuildResults() + { + BundleInfos = new Dictionary(); + WriteResults = new Dictionary(); + } + } +} diff --git a/Editor/Shared/BuildBuildResults.cs.meta b/Editor/Shared/BuildResults.cs.meta similarity index 100% rename from Editor/Shared/BuildBuildResults.cs.meta rename to Editor/Shared/BuildResults.cs.meta diff --git a/Editor/Shared/BuildTasksRunner.cs b/Editor/Shared/BuildTasksRunner.cs index 39a3a1a..1b922b9 100644 --- a/Editor/Shared/BuildTasksRunner.cs +++ b/Editor/Shared/BuildTasksRunner.cs @@ -1,12 +1,22 @@ using System; using System.Collections.Generic; -using UnityEditor.Build.Interfaces; -using UnityEditor.Build.Utilities; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.Utilities; -namespace UnityEditor.Build +namespace UnityEditor.Build.Pipeline { + /// + /// Basic static class containing default implementations for BuildTask validation and running. + /// public static class BuildTasksRunner { + /// + /// Basic run implementation that takes a set of tasks, a context, and runs returning the build results. + /// , , and + /// + /// The set of build tasks to run. + /// The build context to use for this run. + /// Return code with status information about success or failure causes. public static ReturnCodes Run(IList pipeline, IBuildContext context) { IProgressTracker tracker; @@ -33,6 +43,13 @@ public static ReturnCodes Run(IList pipeline, IBuildContext context) return ReturnCodes.Success; } + /// + /// Basic validate implementation that takes a set of tasks, a context, and does checks to ensure the task requirements are all satisfied. + /// , , and + /// + /// The set of build tasks to run. + /// The build context to use for this run. + /// Return code with status information about success or failure causes. public static ReturnCodes Validate(IList pipeline, IBuildContext context) { var requiredTypes = new HashSet(); diff --git a/Editor/Shared/BuildWriteData.cs b/Editor/Shared/BuildWriteData.cs index 3d1cdd7..3784cb2 100644 --- a/Editor/Shared/BuildWriteData.cs +++ b/Editor/Shared/BuildWriteData.cs @@ -1,18 +1,28 @@ using System; using System.Collections.Generic; -using UnityEditor.Build.WriteTypes; -using UnityEditor.Build.Interfaces; -using UnityEditor.Experimental.Build.AssetBundle; +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.WriteTypes; -namespace UnityEditor.Build +namespace UnityEditor.Build.Pipeline { + /// + /// Basic implementation of IWriteData. Stores the write information calculated during a build. + /// + /// [Serializable] public class BuildWriteData : IWriteData { + /// public Dictionary> AssetToFiles { get; private set; } + /// public Dictionary> FileToObjects { get; private set; } + /// public List WriteOperations { get; private set; } - + + /// + /// Default constructor, initializes properties to defaults + /// public BuildWriteData() { AssetToFiles = new Dictionary>(); @@ -21,16 +31,28 @@ public BuildWriteData() } } + /// + /// Basic implementation of IBundleWriteData. Stores the asset bundle write information calculated during a build. + /// + /// [Serializable] public class BundleWriteData : IBundleWriteData { public Dictionary> AssetToFiles { get; private set; } + /// public Dictionary> FileToObjects { get; private set; } + /// public Dictionary FileToBundle { get; private set; } + /// public Dictionary FileToUsageSet { get; private set; } + /// public Dictionary FileToReferenceMap { get; private set; } + /// public List WriteOperations { get; private set; } - + + /// + /// Default constructor, initializes properties to defaults + /// public BundleWriteData() { AssetToFiles = new Dictionary>(); diff --git a/Editor/Shared/BundleDetails.cs b/Editor/Shared/BundleDetails.cs index f67e9fa..01f3a2e 100644 --- a/Editor/Shared/BundleDetails.cs +++ b/Editor/Shared/BundleDetails.cs @@ -1,13 +1,29 @@ using System; using UnityEngine; -namespace UnityEditor.Build +namespace UnityEditor.Build.Pipeline { + /// + /// Struct containing detailed information about a built asset bundle + /// [Serializable] public struct BundleDetails { + /// + /// Specific file name on disk of the asset bundle. + /// public string fileName; + + /// + /// Cyclic redundancy check of the content contained inside of the asset bundle. + /// This value will not change between identical asset bundles with different compression options. + /// public uint crc; + + /// + /// The hash version of the content contained inside of the asset bundle. + /// This value will not change between identical asset bundles with different compression options. + /// public Hash128 hash; } } \ No newline at end of file diff --git a/Editor/Shared/DefaultBuildTasks.cs b/Editor/Shared/DefaultBuildTasks.cs index abb482c..1cb86bc 100644 --- a/Editor/Shared/DefaultBuildTasks.cs +++ b/Editor/Shared/DefaultBuildTasks.cs @@ -1,20 +1,30 @@ using System; using System.Collections.Generic; -using UnityEditor.Build.Interfaces; -using UnityEditor.Build.Tasks; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.Tasks; -namespace UnityEditor.Build +namespace UnityEditor.Build.Pipeline { + /// + /// Basic static class containing preset build pipeline task collections. + /// public static class DefaultBuildTasks { + /// + /// Enum of the different preset build pipelines + /// public enum Presets { PlayerScriptsOnly, - AssetBundleCompatible, - AutopackReleaseContent, - //AutopackFastDeployContent, + AssetBundleCompatible } + /// + /// Constructs and returns an IList containing the build tasks in the correct order for the preset build pipeline. + /// + /// The preset build pipeline to construct and return. + /// The boolean to allow bypassing script compilation of a preset build pipeline if supported. + /// IList containing the build tasks in the correct order for the preset build pipeline. public static IList Create(Presets preset, bool compileScripts = true) { switch (preset) @@ -23,8 +33,6 @@ public static IList Create(Presets preset, bool compileScripts = tru return PlayerScriptsOnly(); case Presets.AssetBundleCompatible: return AssetBundleCompatible(compileScripts); - case Presets.AutopackReleaseContent: - return AutopackReleaseContent(compileScripts); default: throw new NotImplementedException(string.Format("Presets for '{0}' not yet implemented.", preset)); } @@ -55,42 +63,6 @@ static IList PlayerScriptsOnly() return buildTasks; } - static IList AutopackReleaseContent(bool compileScripts) - { - var buildTasks = new List(); - - // Setup - buildTasks.Add(new ProjectInCleanState()); - buildTasks.Add(new SwitchToBuildPlatform()); - buildTasks.Add(new RebuildAtlasCache()); - - // Player Scripts - if (compileScripts) - { - buildTasks.Add(new BuildPlayerScripts()); - buildTasks.Add(new SetBundleSettingsTypeDB()); - buildTasks.Add(new PostScriptsCallback()); - } - - // Dependency - buildTasks.Add(new CalculateSceneDependencyData()); - buildTasks.Add(new CalculateAssetDependencyData()); - buildTasks.Add(new StripUnusedSpriteSources()); - buildTasks.Add(new PostDependencyCallback()); - - // Packing - buildTasks.Add(new GenerateReleaseAutoPacking()); - buildTasks.Add(new GenerateCommands()); - buildTasks.Add(new PostPackingCallback()); - - // Writing - buildTasks.Add(new WriteSerializedFiles()); - buildTasks.Add(new CopySerializedFiles()); - buildTasks.Add(new PostWritingCallback()); - - return buildTasks; - } - static IList AssetBundleCompatible(bool compileScripts) { var buildTasks = new List(); diff --git a/Editor/Shared/LinearPackedIdentifiers.cs b/Editor/Shared/LinearPackedIdentifiers.cs index 3d7ff5f..caad702 100644 --- a/Editor/Shared/LinearPackedIdentifiers.cs +++ b/Editor/Shared/LinearPackedIdentifiers.cs @@ -1,25 +1,37 @@ -using UnityEditor.Build.Interfaces; -using UnityEditor.Build.Utilities; -using UnityEditor.Experimental.Build.AssetBundle; +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.Utilities; using UnityEngine; -namespace UnityEditor.Build +namespace UnityEditor.Build.Pipeline { + /// + /// Generates identifiers linearly for built content. Only deterministic if object order and initial Index is deterministic. + /// public struct LinearPackedIdentifiers : IDeterministicIdentifiers { + /// + /// The index at which to start linear id assignment. + /// public long Index { get; set; } + /// + /// Default constructor, takes an initial index at which to start linear id assignment. + /// + /// Initial index at which to start linear id assignment. public LinearPackedIdentifiers(long index) : this() { Index = index; } - + + /// public string GenerateInternalFileName(string name) { Hash128 hash = HashingMethods.CalculateMD5Hash(name); return string.Format("CAB-{0}", hash); } - + + /// public long SerializationIndexFromObjectIdentifier(ObjectIdentifier objectID) { return Index++; diff --git a/Editor/Shared/PrefabPackedIdentifiers.cs b/Editor/Shared/PrefabPackedIdentifiers.cs index 08bce7a..3e444aa 100644 --- a/Editor/Shared/PrefabPackedIdentifiers.cs +++ b/Editor/Shared/PrefabPackedIdentifiers.cs @@ -1,19 +1,25 @@ using System; -using UnityEditor.Build.Interfaces; -using UnityEditor.Build.Utilities; -using UnityEditor.Experimental.Build.AssetBundle; +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.Utilities; using UnityEngine; -namespace UnityEditor.Build +namespace UnityEditor.Build.Pipeline { + /// + /// Generates a deterministic identifier using a MD5 hash algorithm and does not require object ordering to be deterministic. + /// This algorithm ensures objects coming from the same asset are packed closer together and can improve loading performance under certain situations. + /// public struct PrefabPackedIdentifiers : IDeterministicIdentifiers { + /// public string GenerateInternalFileName(string name) { Hash128 hash = HashingMethods.CalculateMD5Hash(name); return string.Format("CAB-{0}", hash); } - + + /// public long SerializationIndexFromObjectIdentifier(ObjectIdentifier objectID) { byte[] assetHash = HashingMethods.CalculateMD5(objectID.guid, objectID.filePath); diff --git a/Editor/Shared/Unity5PackedIdentifiers.cs b/Editor/Shared/Unity5PackedIdentifiers.cs index cb9fb74..8e3b79d 100644 --- a/Editor/Shared/Unity5PackedIdentifiers.cs +++ b/Editor/Shared/Unity5PackedIdentifiers.cs @@ -1,13 +1,20 @@ using System; using System.Text; -using UnityEditor.Build.Interfaces; -using UnityEditor.Build.Utilities; -using UnityEditor.Experimental.Build.AssetBundle; +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.Utilities; -namespace UnityEditor.Build +namespace UnityEditor.Build.Pipeline { + /// + /// Generates a deterministic identifier using a MD4 hash algorithm and does not require object ordering to be deterministic. +#pragma warning disable 1574 + /// This algorithm generates identical results to what is used internally in . +#pragma warning restore 1574 + /// public struct Unity5PackedIdentifiers : IDeterministicIdentifiers { + /// public string GenerateInternalFileName(string name) { var md4 = MD4.Create(); @@ -15,7 +22,8 @@ public string GenerateInternalFileName(string name) md4.TransformFinalBlock(bytes, 0, bytes.Length); return "CAB-" + BitConverter.ToString(md4.Hash, 0).ToLower().Replace("-", ""); } - + + /// public long SerializationIndexFromObjectIdentifier(ObjectIdentifier objectID) { byte[] bytes; @@ -23,7 +31,7 @@ public long SerializationIndexFromObjectIdentifier(ObjectIdentifier objectID) if (objectID.fileType == FileType.MetaAssetType || objectID.fileType == FileType.SerializedAssetType) { // TODO: Variant info - // NOTE: ToString() required as unity5 used the guid as a string to hash + // NOTE: ToString() required as unity5 uses the GUID as a string to hash bytes = Encoding.ASCII.GetBytes(objectID.guid.ToString()); md4.TransformBlock(bytes, 0, bytes.Length, bytes, 0); bytes = BitConverter.GetBytes((int)objectID.fileType); diff --git a/Editor/Tasks/ArchiveAndCompressBundles.cs b/Editor/Tasks/ArchiveAndCompressBundles.cs index a683bf4..08fa759 100644 --- a/Editor/Tasks/ArchiveAndCompressBundles.cs +++ b/Editor/Tasks/ArchiveAndCompressBundles.cs @@ -2,12 +2,11 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using UnityEditor.Build.Interfaces; -using UnityEditor.Build.Utilities; -using UnityEditor.Experimental.Build.AssetBundle; -using UnityEngine; +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.Utilities; -namespace UnityEditor.Build.Tasks +namespace UnityEditor.Build.Pipeline.Tasks { public struct ArchiveAndCompressBundles : IBuildTask { @@ -21,21 +20,22 @@ public ReturnCodes Run(IBuildContext context) { IProgressTracker tracker; context.TryGetContextObject(out tracker); - return Run(context.GetContextObject(), context.GetContextObject(), context.GetContextObject(), tracker); + IBuildCache cache; + context.TryGetContextObject(out cache); + return Run(context.GetContextObject(), context.GetContextObject(), context.GetContextObject(), tracker, cache); } - static Hash128 CalculateInputHash(bool useCache, ResourceFile[] resources, BuildCompression compression) + static void CalcualteCacheEntry(ResourceFile[] resources, BuildCompression compression, string bundleName, ref CacheEntry cacheEntry) { - if (!useCache) - return new Hash128(); - var fileHashes = new List(); foreach (ResourceFile resource in resources) - fileHashes.Add(HashingMethods.CalculateFileMD5Hash(resource.fileName).ToString()); - return HashingMethods.CalculateMD5Hash(k_Version, fileHashes, compression); + fileHashes.Add(HashingMethods.CalculateFileMD5(resource.fileName).ToString()); + + cacheEntry.guid = HashingMethods.CalculateMD5Guid("ArchiveAndCompressBundles", bundleName); + cacheEntry.hash = HashingMethods.CalculateMD5Hash(k_Version, fileHashes, compression); } - public static ReturnCodes Run(IBuildParameters parameters, IBundleWriteData writeData, IBundleBuildResults results, IProgressTracker tracker = null) + public static ReturnCodes Run(IBuildParameters parameters, IBundleWriteData writeData, IBundleBuildResults results, IProgressTracker tracker = null, IBuildCache cache = null) { Dictionary> bundleToResults = new Dictionary>(); foreach (var result in results.WriteResults) @@ -50,54 +50,42 @@ public static ReturnCodes Run(IBuildParameters parameters, IBundleWriteData writ { ResourceFile[] resourceFiles = bundle.Value.SelectMany(x => x.resourceFiles).ToArray(); BuildCompression compression = parameters.GetCompressionForIdentifier(bundle.Key); - Hash128 hash = CalculateInputHash(parameters.UseCache, resourceFiles, compression); - - var finalPath = string.Format("{0}/{1}", parameters.OutputFolder, bundle.Key); - var writePath = string.Format("{0}/{1}", parameters.GetTempOrCacheBuildPath(hash), bundle.Key); var details = new BundleDetails(); - if (TryLoadFromCache(parameters.UseCache, hash, ref details)) - { - if (!tracker.UpdateInfoUnchecked(string.Format("{0} (Cached)", bundle.Key))) - return ReturnCodes.Canceled; + // TODO: Not fond of how caching is handled for archiving, rewrite it + var writePath = string.Format("{0}/{1}", parameters.TempOutputFolder, bundle.Key); - SetOutputInformation(writePath, finalPath, bundle.Key, details, results); - continue; + var cacheEntry = new CacheEntry(); + if (parameters.UseCache && cache != null) + { + CalcualteCacheEntry(resourceFiles, compression, bundle.Key, ref cacheEntry); + writePath = string.Format("{0}/{1}", cache.GetArtifactCacheDirectory(cacheEntry), bundle.Key); + if (cache.TryLoadFromCache(cacheEntry, ref details)) + { + if (!tracker.UpdateInfoUnchecked(string.Format("{0} (Cached)", bundle.Key))) + return ReturnCodes.Canceled; + + details.fileName = string.Format("{0}/{1}", parameters.OutputFolder, bundle.Key); + SetOutputInformation(writePath, details.fileName, bundle.Key, details, results); + continue; + } } if (!tracker.UpdateInfoUnchecked(bundle.Key)) return ReturnCodes.Canceled; - details.fileName = finalPath; - details.crc = BundleBuildInterface.ArchiveAndCompress(resourceFiles, writePath, compression); + details.fileName = string.Format("{0}/{1}", parameters.OutputFolder, bundle.Key); + details.crc = ContentBuildInterface.ArchiveAndCompress(resourceFiles, writePath, compression); details.hash = HashingMethods.CalculateFileMD5Hash(writePath); - SetOutputInformation(writePath, finalPath, bundle.Key, details, results); + SetOutputInformation(writePath, details.fileName, bundle.Key, details, results); - if (!TrySaveToCache(parameters.UseCache, hash, details)) + if (parameters.UseCache && cache != null && !cache.TrySaveToCache(cacheEntry, details)) BuildLogger.LogWarning("Unable to cache ArchiveAndCompressBundles result for bundle {0}.", bundle.Key); } return ReturnCodes.Success; } - static bool TryLoadFromCache(bool useCache, Hash128 hash, ref BundleDetails details) - { - BundleDetails cachedDetails; - if (useCache && BuildCache.TryLoadCachedResults(hash, out cachedDetails)) - { - details = cachedDetails; - return true; - } - return false; - } - - static bool TrySaveToCache(bool useCache, Hash128 hash, BundleDetails details) - { - if (useCache && !BuildCache.SaveCachedResults(hash, details)) - return false; - return true; - } - static void SetOutputInformation(string writePath, string finalPath, string bundleName, BundleDetails details, IBundleBuildResults results) { if (finalPath != writePath) diff --git a/Editor/Tasks/BuildPlayerScripts.cs b/Editor/Tasks/BuildPlayerScripts.cs index b35a253..f1ed993 100644 --- a/Editor/Tasks/BuildPlayerScripts.cs +++ b/Editor/Tasks/BuildPlayerScripts.cs @@ -1,9 +1,9 @@ using System; -using UnityEditor.Build.Interfaces; -using UnityEditor.Build.Utilities; -using UnityEditor.Experimental.Build.Player; +using UnityEditor.Build.Pipeline.Utilities; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Player; -namespace UnityEditor.Build.Tasks +namespace UnityEditor.Build.Pipeline.Tasks { public struct BuildPlayerScripts : IBuildTask { diff --git a/Editor/Tasks/CalculateAssetDependencyData.cs b/Editor/Tasks/CalculateAssetDependencyData.cs index f1a8cb2..f0d6072 100644 --- a/Editor/Tasks/CalculateAssetDependencyData.cs +++ b/Editor/Tasks/CalculateAssetDependencyData.cs @@ -1,12 +1,10 @@ using System; using System.Collections.Generic; -using UnityEditor.Build.Interfaces; -using UnityEditor.Build.Utilities; -using UnityEditor.Experimental.Build; -using UnityEditor.Experimental.Build.AssetBundle; -using UnityEngine; +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.Utilities; -namespace UnityEditor.Build.Tasks +namespace UnityEditor.Build.Pipeline.Tasks { public struct CalculateAssetDependencyData : IBuildTask { @@ -20,24 +18,12 @@ public ReturnCodes Run(IBuildContext context) { IProgressTracker tracker; context.TryGetContextObject(out tracker); - return Run(context.GetContextObject(), context.GetContextObject(), context.GetContextObject(), tracker); + IBuildCache cache; + context.TryGetContextObject(out cache); + return Run(context.GetContextObject(), context.GetContextObject(), context.GetContextObject(), tracker, cache); } - static Hash128 CalculateInputHash(bool useCache, GUID asset, BuildUsageTagGlobal globalUsage, BuildSettings settings) - { - if (!useCache) - return new Hash128(); - - string path = AssetDatabase.GUIDToAssetPath(asset.ToString()); - string assetHash = AssetDatabase.GetAssetDependencyHash(path).ToString(); - string[] dependencies = AssetDatabase.GetDependencies(path); - var dependencyHashes = new string[dependencies.Length]; - for (int i = 0; i < dependencies.Length; ++i) - dependencyHashes[i] = AssetDatabase.GetAssetDependencyHash(dependencies[i]).ToString(); - return HashingMethods.CalculateMD5Hash(k_Version, assetHash, dependencyHashes, globalUsage, settings); - } - - public static ReturnCodes Run(IBuildParameters parameters, IBuildContent content, IDependencyData dependencyData, IProgressTracker tracker = null) + public static ReturnCodes Run(IBuildParameters parameters, IBuildContent content, IDependencyData dependencyData, IProgressTracker tracker = null, IBuildCache cache = null) { var globalUsage = new BuildUsageTagGlobal(); foreach (SceneDependencyInfo sceneInfo in dependencyData.SceneInfo.Values) @@ -49,30 +35,33 @@ public static ReturnCodes Run(IBuildParameters parameters, IBuildContent content var usageTags = new BuildUsageTagSet(); string assetPath = AssetDatabase.GUIDToAssetPath(asset.ToString()); - Hash128 hash = CalculateInputHash(parameters.UseCache, asset, globalUsage, parameters.GetContentBuildSettings()); - if (TryLoadFromCache(parameters.UseCache, hash, ref assetInfo, ref usageTags)) + var cacheEntry = new CacheEntry { guid = asset }; + if (parameters.UseCache && cache != null) { - if (!tracker.UpdateInfoUnchecked(string.Format("{0} (Cached)", assetPath))) - return ReturnCodes.Canceled; - - SetOutputInformation(asset, assetInfo, usageTags, dependencyData); - continue; + cacheEntry = cache.GetCacheEntry(asset); + var result = cache.IsCacheEntryValid(cacheEntry); + if (result && cache.TryLoadFromCache(cacheEntry, ref assetInfo, ref usageTags)) + { + if (!tracker.UpdateInfoUnchecked(string.Format("{0} (Cached)", assetPath))) + return ReturnCodes.Canceled; + + SetOutputInformation(asset, assetInfo, usageTags, dependencyData); + continue; + } } if (!tracker.UpdateInfoUnchecked(assetPath)) return ReturnCodes.Canceled; assetInfo.asset = asset; - assetInfo.includedObjects = new List(BundleBuildInterface.GetPlayerObjectIdentifiersInAsset(asset, parameters.Target)); - + assetInfo.includedObjects = new List(ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(asset, parameters.Target)); var includedObjects = assetInfo.includedObjects.ToArray(); - assetInfo.referencedObjects = new List(BundleBuildInterface.GetPlayerDependenciesForObjects(includedObjects, parameters.Target, parameters.ScriptInfo)); - BundleBuildInterface.CalculateBuildUsageTags(assetInfo.referencedObjects.ToArray(), includedObjects, globalUsage, usageTags); + assetInfo.referencedObjects = new List(ContentBuildInterface.GetPlayerDependenciesForObjects(includedObjects, parameters.Target, parameters.ScriptInfo)); + ContentBuildInterface.CalculateBuildUsageTags(assetInfo.referencedObjects.ToArray(), includedObjects, globalUsage, usageTags); SetOutputInformation(asset, assetInfo, usageTags, dependencyData); - - if (!TrySaveToCache(parameters.UseCache, hash, assetInfo, usageTags)) - BuildLogger.LogWarning("Unable to cache AssetDependency results for asset '{0}'.", AssetDatabase.GUIDToAssetPath(asset.ToString())); + if (parameters.UseCache && cache != null && !cache.TrySaveToCache(cacheEntry, assetInfo, usageTags)) + BuildLogger.LogWarning("Unable to cache AssetCachedDependency results for asset '{0}'.", AssetDatabase.GUIDToAssetPath(asset.ToString())); } return ReturnCodes.Success; @@ -84,26 +73,5 @@ static void SetOutputInformation(GUID asset, AssetLoadInfo assetInfo, BuildUsage dependencyData.AssetInfo.Add(asset, assetInfo); dependencyData.AssetUsage.Add(asset, usageTags); } - - static bool TryLoadFromCache(bool useCache, Hash128 hash, ref AssetLoadInfo assetInfo, ref BuildUsageTagSet usageTags) - { - AssetLoadInfo cachedAssetInfo; - BuildUsageTagSet cachedAssetUsage; - if (useCache && BuildCache.TryLoadCachedResults(hash, out cachedAssetInfo) && BuildCache.TryLoadCachedResults(hash, out cachedAssetUsage)) - { - assetInfo = cachedAssetInfo; - usageTags = cachedAssetUsage; - return true; - } - - return false; - } - - static bool TrySaveToCache(bool useCache, Hash128 hash, AssetLoadInfo assetInfo, BuildUsageTagSet usageTags) - { - if (useCache && !(BuildCache.SaveCachedResults(hash, assetInfo) && BuildCache.SaveCachedResults(hash, usageTags))) - return false; - return true; - } } } diff --git a/Editor/Tasks/CalculateSceneDependencyData.cs b/Editor/Tasks/CalculateSceneDependencyData.cs index bc1f85e..95aaf8b 100644 --- a/Editor/Tasks/CalculateSceneDependencyData.cs +++ b/Editor/Tasks/CalculateSceneDependencyData.cs @@ -1,10 +1,10 @@ using System; -using UnityEditor.Build.Interfaces; +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.Utilities; using UnityEditor.Build.Utilities; -using UnityEditor.Experimental.Build.AssetBundle; -using UnityEngine; -namespace UnityEditor.Build.Tasks +namespace UnityEditor.Build.Pipeline.Tasks { public struct CalculateSceneDependencyData : IBuildTask { @@ -18,27 +18,16 @@ public ReturnCodes Run(IBuildContext context) { IProgressTracker tracker; context.TryGetContextObject(out tracker); - return Run(context.GetContextObject(), context.GetContextObject(), context.GetContextObject(), tracker); + IBuildCache cache; + context.TryGetContextObject(out cache); + return Run(context.GetContextObject(), context.GetContextObject(), context.GetContextObject(), tracker, cache); } - static Hash128 CalculateInputHash(bool useCache, GUID asset, BuildSettings settings) - { - if (!useCache) - return new Hash128(); - - string path = AssetDatabase.GUIDToAssetPath(asset.ToString()); - string assetHash = AssetDatabase.GetAssetDependencyHash(path).ToString(); - string[] dependencies = AssetDatabase.GetDependencies(path); - var dependencyHashes = new string[dependencies.Length]; - for (int i = 0; i < dependencies.Length; ++i) - dependencyHashes[i] = AssetDatabase.GetAssetDependencyHash(dependencies[i]).ToString(); - return HashingMethods.CalculateMD5Hash(k_Version, assetHash, dependencyHashes, settings); - } - - public static ReturnCodes Run(IBuildParameters parameters, IBuildContent content, IDependencyData dependencyData, IProgressTracker tracker = null) + public static ReturnCodes Run(IBuildParameters parameters, IBuildContent content, IDependencyData dependencyData, IProgressTracker tracker = null, IBuildCache cache = null) { using (new SceneStateCleanup()) { + foreach (GUID asset in content.Scenes) { string scenePath = AssetDatabase.GUIDToAssetPath(asset.ToString()); @@ -46,26 +35,33 @@ public static ReturnCodes Run(IBuildParameters parameters, IBuildContent content var usageTags = new BuildUsageTagSet(); var sceneInfo = new SceneDependencyInfo(); - Hash128 hash = CalculateInputHash(parameters.UseCache, asset, parameters.GetContentBuildSettings()); - if (TryLoadFromCache(parameters.UseCache, hash, ref sceneInfo, ref usageTags)) + var cacheEntry = new CacheEntry { guid = asset }; + if (parameters.UseCache && cache != null) { - if (!tracker.UpdateInfoUnchecked(string.Format("{0} (Cached)", scenePath))) - return ReturnCodes.Canceled; - - SetOutputInformation(asset, sceneInfo, usageTags, dependencyData); - continue; + cacheEntry = cache.GetCacheEntry(asset); + var result = cache.IsCacheEntryValid(cacheEntry); + if (result && cache.TryLoadFromCache(cacheEntry, ref sceneInfo, ref usageTags)) + { + if (!tracker.UpdateInfoUnchecked(string.Format("{0} (Cached)", scenePath))) + return ReturnCodes.Canceled; + + SetOutputInformation(asset, sceneInfo, usageTags, dependencyData); + continue; + } } if (!tracker.UpdateInfoUnchecked(scenePath)) return ReturnCodes.Canceled; - sceneInfo = BundleBuildInterface.PrepareScene(scenePath, parameters.GetContentBuildSettings(), usageTags, parameters.GetTempOrCacheBuildPath(hash)); + var outputFolder = parameters.UseCache && cache != null ? cache.GetArtifactCacheDirectory(cacheEntry) : parameters.TempOutputFolder; + sceneInfo = ContentBuildInterface.PrepareScene(scenePath, parameters.GetContentBuildSettings(), usageTags, outputFolder); SetOutputInformation(asset, sceneInfo, usageTags, dependencyData); - if (!TrySaveToCache(parameters.UseCache, hash, sceneInfo, usageTags)) - BuildLogger.LogWarning("Unable to cache SceneDependency results for asset '{0}'.", AssetDatabase.GUIDToAssetPath(asset.ToString())); + if (parameters.UseCache && cache != null && !cache.TrySaveToCache(cacheEntry, sceneInfo, usageTags)) + BuildLogger.LogWarning("Unable to cache CalculateSceneDependencyData results for asset '{0}'.", AssetDatabase.GUIDToAssetPath(asset.ToString())); } } + return ReturnCodes.Success; } @@ -75,26 +71,5 @@ static void SetOutputInformation(GUID asset, SceneDependencyInfo sceneInfo, Buil dependencyData.SceneInfo.Add(asset, sceneInfo); dependencyData.SceneUsage.Add(asset, usageTags); } - - static bool TryLoadFromCache(bool useCache, Hash128 hash, ref SceneDependencyInfo sceneInfo, ref BuildUsageTagSet usageTags) - { - SceneDependencyInfo cachedSceneInfo; - BuildUsageTagSet cachedUsageTags; - if (useCache && BuildCache.TryLoadCachedResults(hash, out cachedSceneInfo) && BuildCache.TryLoadCachedResults(hash, out cachedUsageTags)) - { - sceneInfo = cachedSceneInfo; - usageTags = cachedUsageTags; - return true; - } - - return false; - } - - static bool TrySaveToCache(bool useCache, Hash128 hash, SceneDependencyInfo sceneInfo, BuildUsageTagSet usageTags) - { - if (useCache && !(BuildCache.SaveCachedResults(hash, sceneInfo) && BuildCache.SaveCachedResults(hash, usageTags))) - return false; - return true; - } } } diff --git a/Editor/Tasks/CopySerializedFiles.cs b/Editor/Tasks/CopySerializedFiles.cs deleted file mode 100644 index 905a06f..0000000 --- a/Editor/Tasks/CopySerializedFiles.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEditor.Build.Interfaces; -using UnityEditor.Build.WriteTypes; -using UnityEditor.Experimental.Build.AssetBundle; - -namespace UnityEditor.Build.Tasks -{ - public struct CopySerializedFiles : IBuildTask - { - const int k_Version = 1; - public int Version { get { return k_Version; } } - - static readonly Type[] k_RequiredTypes = { typeof(IBuildParameters), typeof(IBuildResults) }; - public Type[] RequiredContextTypes { get { return k_RequiredTypes; } } - - public ReturnCodes Run(IBuildContext context) - { - return Run(context.GetContextObject(), context.GetContextObject()); - } - - public static ReturnCodes Run(IBuildParameters parameters, IBuildResults results) - { - foreach (var writeResult in results.WriteResults.Values) - { - foreach (var resourceFile in writeResult.resourceFiles) - { - var filePath = string.Format("{0}/{1}", parameters.OutputFolder, resourceFile.fileAlias); - Directory.CreateDirectory(Path.GetDirectoryName(filePath)); - File.Copy(resourceFile.fileName, filePath); - } - } - - return ReturnCodes.Success; - } - } -} diff --git a/Editor/Tasks/GenerateBundleCommands.cs b/Editor/Tasks/GenerateBundleCommands.cs index 66d565c..56c9a36 100644 --- a/Editor/Tasks/GenerateBundleCommands.cs +++ b/Editor/Tasks/GenerateBundleCommands.cs @@ -2,38 +2,38 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using UnityEditor.Build.Interfaces; -using UnityEditor.Build.Utilities; -using UnityEditor.Build.WriteTypes; -using UnityEditor.Experimental.Build.AssetBundle; +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.Utilities; +using UnityEditor.Build.Pipeline.WriteTypes; -namespace UnityEditor.Build.Tasks +namespace UnityEditor.Build.Pipeline.Tasks { public struct GenerateBundleCommands : IBuildTask { const int k_Version = 1; public int Version { get { return k_Version; } } - static readonly Type[] k_RequiredTypes = { typeof(IBundleContent), typeof(IDependencyData), typeof(IBundleWriteData), typeof(IDeterministicIdentifiers) }; + static readonly Type[] k_RequiredTypes = { typeof(IBundleBuildContent), typeof(IDependencyData), typeof(IBundleWriteData), typeof(IDeterministicIdentifiers) }; public Type[] RequiredContextTypes { get { return k_RequiredTypes; } } public ReturnCodes Run(IBuildContext context) { - return Run(context.GetContextObject(), context.GetContextObject(), context.GetContextObject(), + return Run(context.GetContextObject(), context.GetContextObject(), context.GetContextObject(), context.GetContextObject()); } - public static ReturnCodes Run(IBundleContent content, IDependencyData dependencyData, IBundleWriteData writeData, IDeterministicIdentifiers packingMethod) + public static ReturnCodes Run(IBundleBuildContent buildContent, IDependencyData dependencyData, IBundleWriteData writeData, IDeterministicIdentifiers packingMethod) { - foreach (var bundlePair in content.BundleLayout) + foreach (var bundlePair in buildContent.BundleLayout) { if (ValidationMethods.ValidAssetBundle(bundlePair.Value)) { - CreateAssetBundleCommand(bundlePair.Key, writeData.AssetToFiles[bundlePair.Value[0]][0], bundlePair.Value, content, dependencyData, writeData, packingMethod); + CreateAssetBundleCommand(bundlePair.Key, writeData.AssetToFiles[bundlePair.Value[0]][0], bundlePair.Value, buildContent, dependencyData, writeData, packingMethod); } else if (ValidationMethods.ValidSceneBundle(bundlePair.Value)) { - CreateSceneBundleCommand(bundlePair.Key, writeData.AssetToFiles[bundlePair.Value[0]][0], bundlePair.Value[0], bundlePair.Value, content, dependencyData, writeData); + CreateSceneBundleCommand(bundlePair.Key, writeData.AssetToFiles[bundlePair.Value[0]][0], bundlePair.Value[0], bundlePair.Value, buildContent, dependencyData, writeData); for (int i = 1; i < bundlePair.Value.Count; ++i) CreateSceneDataCommand(writeData.AssetToFiles[bundlePair.Value[i]][0], bundlePair.Value[i], dependencyData, writeData); } @@ -46,7 +46,6 @@ static WriteCommand CreateWriteCommand(string internalName, List new SerializationInfo { @@ -56,71 +55,73 @@ static WriteCommand CreateWriteCommand(string internalName, List assets, IBundleContent content, IDependencyData dependencyData, IBundleWriteData writeData, IDeterministicIdentifiers packingMethod) + static void CreateAssetBundleCommand(string bundleName, string internalName, List assets, IBundleBuildContent buildContent, IDependencyData dependencyData, IBundleWriteData writeData, IDeterministicIdentifiers packingMethod) { var abOp = new AssetBundleWriteOperation(); - abOp.usageSet = new BuildUsageTagSet(); - writeData.FileToUsageSet.Add(internalName, abOp.usageSet); + abOp.UsageSet = new BuildUsageTagSet(); + writeData.FileToUsageSet.Add(internalName, abOp.UsageSet); - abOp.referenceMap = new BuildReferenceMap(); - writeData.FileToReferenceMap.Add(internalName, abOp.referenceMap); + abOp.ReferenceMap = new BuildReferenceMap(); + writeData.FileToReferenceMap.Add(internalName, abOp.ReferenceMap); var fileObjects = writeData.FileToObjects[internalName]; - abOp.command = CreateWriteCommand(internalName, fileObjects, packingMethod); + abOp.Command = CreateWriteCommand(internalName, fileObjects, packingMethod); { - abOp.info = new AssetBundleInfo(); - abOp.info.bundleName = bundleName; - - var dependencies = new HashSet(); - var bundles = assets.SelectMany(x => writeData.AssetToFiles[x].Select(y => writeData.FileToBundle[y])); - dependencies.UnionWith(bundles); - dependencies.Remove(bundleName); - - abOp.info.bundleDependencies = dependencies.OrderBy(x => x).ToList(); - abOp.info.bundleAssets = assets.Select(x => dependencyData.AssetInfo[x]).ToList(); - foreach (var loadInfo in abOp.info.bundleAssets) - loadInfo.address = content.Addresses[loadInfo.asset]; + abOp.Info = new AssetBundleInfo(); + abOp.Info.bundleName = bundleName; + + // TODO: Convert this to AssetBundleManifest data + //var dependencies = new HashSet(); + //var bundles = assets.SelectMany(x => writeData.AssetToFiles[x].Select(y => writeData.FileToBundle[y])); + //dependencies.UnionWith(bundles); + //dependencies.Remove(bundleName); + //abOp.Info.bundleDependencies = dependencies.OrderBy(x => x).ToList(); + + abOp.Info.bundleAssets = assets.Select(x => dependencyData.AssetInfo[x]).ToList(); + foreach (var loadInfo in abOp.Info.bundleAssets) + loadInfo.address = buildContent.Addresses[loadInfo.asset]; } writeData.WriteOperations.Add(abOp); } - static void CreateSceneBundleCommand(string bundleName, string internalName, GUID asset, List assets, IBundleContent content, IDependencyData dependencyData, IBundleWriteData writeData) + static void CreateSceneBundleCommand(string bundleName, string internalName, GUID asset, List assets, IBundleBuildContent buildContent, IDependencyData dependencyData, IBundleWriteData writeData) { var sbOp = new SceneBundleWriteOperation(); - sbOp.usageSet = new BuildUsageTagSet(); - writeData.FileToUsageSet.Add(internalName, sbOp.usageSet); + sbOp.UsageSet = new BuildUsageTagSet(); + writeData.FileToUsageSet.Add(internalName, sbOp.UsageSet); - sbOp.referenceMap = new BuildReferenceMap(); - writeData.FileToReferenceMap.Add(internalName, sbOp.referenceMap); + sbOp.ReferenceMap = new BuildReferenceMap(); + writeData.FileToReferenceMap.Add(internalName, sbOp.ReferenceMap); var fileObjects = writeData.FileToObjects[internalName]; - sbOp.command = CreateWriteCommand(internalName, fileObjects, new LinearPackedIdentifiers(3)); // Start at 3: PreloadData = 1, AssetBundle = 2 + sbOp.Command = CreateWriteCommand(internalName, fileObjects, new LinearPackedIdentifiers(3)); // Start at 3: PreloadData = 1, AssetBundle = 2 var sceneInfo = dependencyData.SceneInfo[asset]; - sbOp.scene = sceneInfo.scene; - sbOp.processedScene = sceneInfo.processedScene; + sbOp.Scene = sceneInfo.scene; + sbOp.ProcessedScene = sceneInfo.processedScene; { - sbOp.preloadInfo = new PreloadInfo { preloadObjects = sceneInfo.referencedObjects.Where(x => !fileObjects.Contains(x)).ToList() }; + sbOp.PreloadInfo = new PreloadInfo { preloadObjects = sceneInfo.referencedObjects.Where(x => !fileObjects.Contains(x)).ToList() }; } { - sbOp.info = new SceneBundleInfo(); - sbOp.info.bundleName = bundleName; + sbOp.Info = new SceneBundleInfo(); + sbOp.Info.bundleName = bundleName; - var dependencies = new HashSet(); - var bundles = assets.SelectMany(x => writeData.AssetToFiles[x].Select(y => writeData.FileToBundle[y])); - dependencies.UnionWith(bundles); - dependencies.Remove(bundleName); + // TODO: Convert this to AssetBundleManifest data + //var dependencies = new HashSet(); + //var bundles = assets.SelectMany(x => writeData.AssetToFiles[x].Select(y => writeData.FileToBundle[y])); + //dependencies.UnionWith(bundles); + //dependencies.Remove(bundleName); + //sbOp.Info.bundleDependencies = dependencies.OrderBy(x => x).ToList(); - sbOp.info.bundleDependencies = dependencies.OrderBy(x => x).ToList(); - sbOp.info.bundleScenes = assets.Select(x => new SceneLoadInfo + sbOp.Info.bundleScenes = assets.Select(x => new SceneLoadInfo { asset = x, internalName = Path.GetFileNameWithoutExtension(writeData.AssetToFiles[x][0]), - address = content.Addresses[x] + address = buildContent.Addresses[x] }).ToList(); } @@ -130,22 +131,22 @@ static void CreateSceneBundleCommand(string bundleName, string internalName, GUI static void CreateSceneDataCommand(string internalName, GUID asset, IDependencyData dependencyData, IBundleWriteData writeData) { var sdOp = new SceneDataWriteOperation(); - sdOp.usageSet = new BuildUsageTagSet(); - writeData.FileToUsageSet.Add(internalName, sdOp.usageSet); + sdOp.UsageSet = new BuildUsageTagSet(); + writeData.FileToUsageSet.Add(internalName, sdOp.UsageSet); - sdOp.referenceMap = new BuildReferenceMap(); - writeData.FileToReferenceMap.Add(internalName, sdOp.referenceMap); + sdOp.ReferenceMap = new BuildReferenceMap(); + writeData.FileToReferenceMap.Add(internalName, sdOp.ReferenceMap); var fileObjects = writeData.FileToObjects[internalName]; - sdOp.command = CreateWriteCommand(internalName, fileObjects, new LinearPackedIdentifiers(2)); // Start at 2: PreloadData = 1 + sdOp.Command = CreateWriteCommand(internalName, fileObjects, new LinearPackedIdentifiers(2)); // Start at 2: PreloadData = 1 var sceneInfo = dependencyData.SceneInfo[asset]; - sdOp.scene = sceneInfo.scene; - sdOp.processedScene = sceneInfo.processedScene; + sdOp.Scene = sceneInfo.scene; + sdOp.ProcessedScene = sceneInfo.processedScene; { - sdOp.preloadInfo = new PreloadInfo(); - sdOp.preloadInfo.preloadObjects = sceneInfo.referencedObjects.Where(x => !fileObjects.Contains(x)).ToList(); + sdOp.PreloadInfo = new PreloadInfo(); + sdOp.PreloadInfo.preloadObjects = sceneInfo.referencedObjects.Where(x => !fileObjects.Contains(x)).ToList(); } writeData.WriteOperations.Add(sdOp); diff --git a/Editor/Tasks/GenerateBundleMaps.cs b/Editor/Tasks/GenerateBundleMaps.cs index 3306f29..d579dc8 100644 --- a/Editor/Tasks/GenerateBundleMaps.cs +++ b/Editor/Tasks/GenerateBundleMaps.cs @@ -1,10 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; -using UnityEditor.Build.Interfaces; -using UnityEditor.Experimental.Build.AssetBundle; +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.Utilities; -namespace UnityEditor.Build.Tasks +namespace UnityEditor.Build.Pipeline.Tasks { public struct GenerateBundleMaps : IBuildTask { @@ -21,11 +22,12 @@ public ReturnCodes Run(IBuildContext context) public static ReturnCodes Run(IDependencyData dependencyData, IBundleWriteData writeData) { + Dictionary> filesMapped = new Dictionary>(); foreach (var assetFilesPair in writeData.AssetToFiles) { // Generate BuildReferenceMap map - AddReferencesForFiles(assetFilesPair.Value, writeData); - + AddReferencesForFiles(assetFilesPair.Value, writeData, filesMapped); + // Generate BuildUsageTagSet map AddUsageSetForFiles(assetFilesPair.Key, assetFilesPair.Value, dependencyData, writeData); } @@ -33,18 +35,24 @@ public static ReturnCodes Run(IDependencyData dependencyData, IBundleWriteData w return ReturnCodes.Success; } - static void AddReferencesForFiles(IList files, IBundleWriteData writeData) + static void AddReferencesForFiles(IList files, IBundleWriteData writeData, Dictionary> filesMapped) { + HashSet visited; + filesMapped.GetOrAdd(files[0], out visited); + BuildReferenceMap referenceMap; if (!writeData.FileToReferenceMap.TryGetValue(files[0], out referenceMap)) { referenceMap = new BuildReferenceMap(); writeData.FileToReferenceMap.Add(files[0], referenceMap); } - - var fileToCommand = writeData.WriteOperations.ToDictionary(x => x.command.internalName, x => x.command); + + var fileToCommand = writeData.WriteOperations.ToDictionary(x => x.Command.internalName, x => x.Command); foreach (var file in files) { + if (!visited.Add(file)) + continue; + var command = fileToCommand[file]; referenceMap.AddMappings(file, command.serializeObjects.ToArray()); } diff --git a/Editor/Tasks/GenerateBundlePacking.cs b/Editor/Tasks/GenerateBundlePacking.cs index e1c0bec..4eced07 100644 --- a/Editor/Tasks/GenerateBundlePacking.cs +++ b/Editor/Tasks/GenerateBundlePacking.cs @@ -1,11 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; -using UnityEditor.Build.Interfaces; -using UnityEditor.Build.Utilities; -using UnityEditor.Experimental.Build.AssetBundle; +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.Utilities; -namespace UnityEditor.Build.Tasks +namespace UnityEditor.Build.Pipeline.Tasks { public class GenerateBundlePacking : IBuildTask { @@ -21,7 +21,7 @@ public int Version get { return k_Version; } } - static readonly Type[] k_RequiredTypes = { typeof(IBundleContent), typeof(IDependencyData), typeof(IBundleWriteData), typeof(IDeterministicIdentifiers) }; + static readonly Type[] k_RequiredTypes = { typeof(IBundleBuildContent), typeof(IDependencyData), typeof(IBundleWriteData), typeof(IDeterministicIdentifiers) }; public Type[] RequiredContextTypes { @@ -30,16 +30,16 @@ public Type[] RequiredContextTypes public ReturnCodes Run(IBuildContext context) { - return Run(context.GetContextObject(), context.GetContextObject(), context.GetContextObject(), + return Run(context.GetContextObject(), context.GetContextObject(), context.GetContextObject(), context.GetContextObject()); } - public static ReturnCodes Run(IBundleContent content, IDependencyData dependencyData, IBundleWriteData writeData, IDeterministicIdentifiers packingMethod) + public static ReturnCodes Run(IBundleBuildContent buildContent, IDependencyData dependencyData, IBundleWriteData writeData, IDeterministicIdentifiers packingMethod) { Dictionary> AssetToReferences = new Dictionary>(); // Pack each asset bundle - foreach (var bundle in content.BundleLayout) + foreach (var bundle in buildContent.BundleLayout) { if (ValidationMethods.ValidAssetBundle(bundle.Value)) PackAssetBundle(bundle.Key, bundle.Value, dependencyData, writeData, packingMethod, AssetToReferences); @@ -48,7 +48,7 @@ public static ReturnCodes Run(IBundleContent content, IDependencyData dependency } // Calculate Asset file load dependency list - foreach (var bundle in content.BundleLayout) + foreach (var bundle in buildContent.BundleLayout) { foreach (var asset in bundle.Value) { diff --git a/Editor/Tasks/GenerateCommands.cs b/Editor/Tasks/GenerateCommands.cs deleted file mode 100644 index aca8e77..0000000 --- a/Editor/Tasks/GenerateCommands.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEditor.Build.Interfaces; -using UnityEditor.Build.WriteTypes; -using UnityEditor.Experimental.Build.AssetBundle; - -namespace UnityEditor.Build.Tasks -{ - public struct GenerateCommands : IBuildTask - { - const int k_Version = 1; - public int Version { get { return k_Version; } } - - static readonly Type[] k_RequiredTypes = { typeof(IDependencyData), typeof(IWriteData), typeof(IDeterministicIdentifiers) }; - public Type[] RequiredContextTypes { get { return k_RequiredTypes; } } - - public ReturnCodes Run(IBuildContext context) - { - return Run(context.GetContextObject(), context.GetContextObject(), context.GetContextObject()); - } - - public static ReturnCodes Run(IDependencyData dependencyData, IWriteData writeData, IDeterministicIdentifiers packingMethod) - { - var usageSet = new BuildUsageTagSet(); - foreach (var assetUsage in dependencyData.AssetUsage.Values) - usageSet.UnionWith(assetUsage); - foreach (var sceneUsage in dependencyData.SceneUsage.Values) - usageSet.UnionWith(sceneUsage); - - var referenceMap = new BuildReferenceMap(); - - foreach (var filePair in writeData.FileToObjects) - CreateRawCommand(filePair.Key, filePair.Value, referenceMap, usageSet, writeData, packingMethod); - - foreach (var sceneInfo in dependencyData.SceneInfo.Values) - CreateSceneRawCommand(sceneInfo, referenceMap, usageSet, writeData, packingMethod); - - foreach (var op in writeData.WriteOperations) - referenceMap.AddMappings(op.command.internalName, op.command.serializeObjects.ToArray()); // TODO: Add Overload that takes List<> - - return ReturnCodes.Success; - } - - static void CreateRawCommand(string internalName, List objects, BuildReferenceMap referenceMap, BuildUsageTagSet usageSet, IWriteData writeData, IDeterministicIdentifiers packingMethod) - { - var rOp = new RawWriteOperation(); - rOp.command = new WriteCommand(); - rOp.command.internalName = internalName; - rOp.command.fileName = Path.GetFileName(internalName); // TODO: Maybe remove this from C++? - // rOp.command.dependencies // TODO: Definitely remove this from C++ - - rOp.command.serializeObjects = objects.Select(x => new SerializationInfo - { - serializationObject = x, - serializationIndex = packingMethod.SerializationIndexFromObjectIdentifier(x) - }).ToList(); - - rOp.referenceMap = referenceMap; - rOp.usageSet = usageSet; - - writeData.WriteOperations.Add(rOp); - } - - static void CreateSceneRawCommand(SceneDependencyInfo sceneInfo, BuildReferenceMap referenceMap, BuildUsageTagSet usageSet, IWriteData writeData, IDeterministicIdentifiers packingMethod) - { - var srOp = new SceneRawWriteOperation(); - srOp.command = new WriteCommand(); - srOp.command.internalName = packingMethod.GenerateInternalFileName(sceneInfo.scene) + ".sharedAssets"; // TODO: This is a bit awkward that we require this extension - srOp.command.fileName = Path.GetFileName(srOp.command.internalName); // TODO: Maybe remove this from C++? - // srOp.command.dependencies // TODO: Definitely remove this from C++ - srOp.command.serializeObjects = new List(); // TODO: Currently unused in this case, possible use in the future - - srOp.referenceMap = referenceMap; - srOp.usageSet = usageSet; - srOp.scene = sceneInfo.scene; - srOp.processedScene = sceneInfo.processedScene; - - writeData.WriteOperations.Add(srOp); - } - } -} diff --git a/Editor/Tasks/GenerateCommands.cs.meta b/Editor/Tasks/GenerateCommands.cs.meta deleted file mode 100644 index d5a5360..0000000 --- a/Editor/Tasks/GenerateCommands.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 52fe25e0ed64414e89be52a838280d3a -timeCreated: 1517943636 \ No newline at end of file diff --git a/Editor/Tasks/GenerateReleaseAutoPacking.cs b/Editor/Tasks/GenerateReleaseAutoPacking.cs deleted file mode 100644 index c5bdbb2..0000000 --- a/Editor/Tasks/GenerateReleaseAutoPacking.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEditor.Build.Interfaces; -using UnityEditor.Build.Utilities; -using UnityEditor.Experimental.Build.AssetBundle; -using UnityEngine; - -namespace UnityEditor.Build.Tasks -{ - public struct GenerateReleaseAutoPacking : IBuildTask - { - // TODO: Move to utility file - public const string k_UnityDefaultResourcePath = "library/unity default resources"; - - const int k_Version = 1; - public int Version { get { return k_Version; } } - - static readonly Type[] k_RequiredTypes = { typeof(IDependencyData), typeof(IWriteData) }; - public Type[] RequiredContextTypes { get { return k_RequiredTypes; } } - - public ReturnCodes Run(IBuildContext context) - { - return Run(context.GetContextObject(), context.GetContextObject()); - } - - public static ReturnCodes Run(IDependencyData dependencyData, IWriteData writeData) - { - // Object usage (ObjectID to Set of Asset GUIDs) - var objectUsage = new Dictionary>(); - - // Calculate the set of what is using every object - foreach (var assetPair in dependencyData.AssetInfo) - { - AddObjectUsage(assetPair.Key.ToString(), assetPair.Value.includedObjects, objectUsage); - AddObjectUsage(assetPair.Key.ToString(), assetPair.Value.referencedObjects, objectUsage); - } - - foreach (var scenePair in dependencyData.SceneInfo) - { - AddObjectUsage(scenePair.Key.ToString(), scenePair.Value.referencedObjects, objectUsage); - } - - // Calculate the optimal layout based on object usage - foreach (var usagePair in objectUsage) - { - var usageList = usagePair.Value.ToList(); - Hash128 usageHash = HashingMethods.CalculateMD5Hash(usageList); - - List objects; - writeData.FileToObjects.GetOrAdd("CAB-" + usageHash, out objects); - objects.Add(usagePair.Key); - } - - ///LogContextToFile.Run(writeData.FileToObjects, @"D:\Projects\BuildHLAPI\Builds\ObjectLayout.json"); - - foreach (var assetPair in dependencyData.AssetInfo) - { - List hashes; - writeData.AssetToFiles.GetOrAdd(assetPair.Key, out hashes); - - AddObjectDependencies(objectUsage, assetPair.Value.includedObjects, hashes); - AddObjectDependencies(objectUsage, assetPair.Value.referencedObjects, hashes); - } - - foreach (var scenePair in dependencyData.SceneInfo) - { - List hashes; - writeData.AssetToFiles.GetOrAdd(scenePair.Key, out hashes); - hashes.Add(scenePair.Key.ToString()); - - AddObjectDependencies(objectUsage, scenePair.Value.referencedObjects, hashes); - } - - ///LogContextToFile.Run(writeData.AssetToFiles, @"D:\Projects\BuildHLAPI\Builds\AssetDependencies.json"); - - return ReturnCodes.Success; - } - - static void AddObjectUsage(string source, IEnumerable objectIDs, Dictionary> outObjectUsage) - { - foreach (ObjectIdentifier objectID in objectIDs) - { - if (objectID.filePath == k_UnityDefaultResourcePath) // TODO: Fix this so we can pull in these objects - continue; - - HashSet usage; - outObjectUsage.GetOrAdd(objectID, out usage); - usage.Add(source); - } - } - - static void AddObjectDependencies(Dictionary> objectUsage, IEnumerable objectIDs, List outDependencies) - { - foreach (var objectID in objectIDs) - { - if (objectID.filePath == k_UnityDefaultResourcePath) // TODO: Fix this so we can pull in these objects - continue; - - var usageList = objectUsage[objectID].ToList(); - Hash128 usageHash = HashingMethods.CalculateMD5Hash(usageList); - if (!outDependencies.Contains(usageHash.ToString())) - outDependencies.Add(usageHash.ToString()); - } - } - } -} diff --git a/Editor/Tasks/PostDependencyCallback.cs b/Editor/Tasks/PostDependencyCallback.cs index 2676338..e4c9551 100644 --- a/Editor/Tasks/PostDependencyCallback.cs +++ b/Editor/Tasks/PostDependencyCallback.cs @@ -1,7 +1,7 @@ using System; -using UnityEditor.Build.Interfaces; +using UnityEditor.Build.Pipeline.Interfaces; -namespace UnityEditor.Build.Tasks +namespace UnityEditor.Build.Pipeline.Tasks { public struct PostDependencyCallback : IBuildTask { diff --git a/Editor/Tasks/PostPackingCallback.cs b/Editor/Tasks/PostPackingCallback.cs index 45abf8b..89c2bde 100644 --- a/Editor/Tasks/PostPackingCallback.cs +++ b/Editor/Tasks/PostPackingCallback.cs @@ -1,7 +1,7 @@ using System; -using UnityEditor.Build.Interfaces; +using UnityEditor.Build.Pipeline.Interfaces; -namespace UnityEditor.Build.Tasks +namespace UnityEditor.Build.Pipeline.Tasks { public struct PostPackingCallback : IBuildTask { diff --git a/Editor/Tasks/PostScriptsCallback.cs b/Editor/Tasks/PostScriptsCallback.cs index dcfb33d..b103c81 100644 --- a/Editor/Tasks/PostScriptsCallback.cs +++ b/Editor/Tasks/PostScriptsCallback.cs @@ -1,7 +1,7 @@ using System; -using UnityEditor.Build.Interfaces; +using UnityEditor.Build.Pipeline.Interfaces; -namespace UnityEditor.Build.Tasks +namespace UnityEditor.Build.Pipeline.Tasks { public struct PostScriptsCallback : IBuildTask { diff --git a/Editor/Tasks/PostWritingCallback.cs b/Editor/Tasks/PostWritingCallback.cs index 60b67f6..f9215cb 100644 --- a/Editor/Tasks/PostWritingCallback.cs +++ b/Editor/Tasks/PostWritingCallback.cs @@ -1,7 +1,7 @@ using System; -using UnityEditor.Build.Interfaces; +using UnityEditor.Build.Pipeline.Interfaces; -namespace UnityEditor.Build.Tasks +namespace UnityEditor.Build.Pipeline.Tasks { public struct PostWritingCallback : IBuildTask { diff --git a/Editor/Tasks/PreviewSceneDependencyData.cs b/Editor/Tasks/PreviewSceneDependencyData.cs index 36fcf14..d93a8a9 100644 --- a/Editor/Tasks/PreviewSceneDependencyData.cs +++ b/Editor/Tasks/PreviewSceneDependencyData.cs @@ -2,12 +2,11 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; -using UnityEditor.Build.Interfaces; -using UnityEditor.Build.Utilities; -using UnityEditor.Experimental.Build.AssetBundle; -using UnityEngine; +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.Utilities; -namespace UnityEditor.Build.Tasks +namespace UnityEditor.Build.Pipeline.Tasks { public struct PreviewSceneDependencyData : IBuildTask { @@ -21,24 +20,12 @@ public ReturnCodes Run(IBuildContext context) { IProgressTracker tracker; context.TryGetContextObject(out tracker); - return Run(context.GetContextObject(), context.GetContextObject(), context.GetContextObject(), tracker); + IBuildCache cache; + context.TryGetContextObject(out cache); + return Run(context.GetContextObject(), context.GetContextObject(), context.GetContextObject(), tracker, cache); } - static Hash128 CalculateInputHash(bool useCache, GUID asset, BuildSettings settings) - { - if (!useCache) - return new Hash128(); - - string path = AssetDatabase.GUIDToAssetPath(asset.ToString()); - string assetHash = AssetDatabase.GetAssetDependencyHash(path).ToString(); - string[] dependencies = AssetDatabase.GetDependencies(path); - var dependencyHashes = new string[dependencies.Length]; - for (int i = 0; i < dependencies.Length; ++i) - dependencyHashes[i] = AssetDatabase.GetAssetDependencyHash(dependencies[i]).ToString(); - return HashingMethods.CalculateMD5Hash(k_Version, assetHash, dependencyHashes, settings); - } - - public static ReturnCodes Run(IBuildParameters parameters, IBuildContent content, IDependencyData dependencyData, IProgressTracker tracker = null) + public static ReturnCodes Run(IBuildParameters parameters, IBuildContent content, IDependencyData dependencyData, IProgressTracker tracker = null, IBuildCache cache = null) { foreach (GUID asset in content.Scenes) { @@ -47,14 +34,19 @@ public static ReturnCodes Run(IBuildParameters parameters, IBuildContent content var usageTags = new BuildUsageTagSet(); var sceneInfo = new SceneDependencyInfo(); - Hash128 hash = CalculateInputHash(parameters.UseCache, asset, parameters.GetContentBuildSettings()); - if (TryLoadFromCache(parameters.UseCache, hash, ref sceneInfo, ref usageTags)) + var cacheEntry = new CacheEntry { guid = asset }; + if (parameters.UseCache && cache != null) { - if (!tracker.UpdateInfoUnchecked(string.Format("{0} (Cached)", scenePath))) - return ReturnCodes.Canceled; - - SetOutputInformation(asset, sceneInfo, usageTags, dependencyData); - continue; + cacheEntry = cache.GetCacheEntry(asset); + var result = cache.IsCacheEntryValid(cacheEntry); + if (result && cache.TryLoadFromCache(cacheEntry, ref sceneInfo, ref usageTags)) + { + if (!tracker.UpdateInfoUnchecked(string.Format("{0} (Cached)", scenePath))) + return ReturnCodes.Canceled; + + SetOutputInformation(asset, sceneInfo, usageTags, dependencyData); + continue; + } } if (!tracker.UpdateInfoUnchecked(scenePath)) @@ -67,8 +59,9 @@ public static ReturnCodes Run(IBuildParameters parameters, IBuildContent content var assetGuid = new GUID(AssetDatabase.AssetPathToGUID(assetPath)); if (!ValidationMethods.ValidAsset(assetGuid)) continue; - var assetIncludes = BundleBuildInterface.GetPlayerObjectIdentifiersInAsset(assetGuid, parameters.Target); - var assetReferences = BundleBuildInterface.GetPlayerDependenciesForObjects(assetIncludes, parameters.Target, parameters.ScriptInfo); + // TODO: Use Cache to speed this up? + var assetIncludes = ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(assetGuid, parameters.Target); + var assetReferences = ContentBuildInterface.GetPlayerDependenciesForObjects(assetIncludes, parameters.Target, parameters.ScriptInfo); references.UnionWith(assetIncludes); references.UnionWith(assetReferences); } @@ -81,8 +74,8 @@ public static ReturnCodes Run(IBuildParameters parameters, IBuildContent content SetOutputInformation(asset, sceneInfo, usageTags, dependencyData); - if (!TrySaveToCache(parameters.UseCache, hash, sceneInfo, usageTags)) - BuildLogger.LogWarning("Unable to cache SceneDependency results for asset '{0}'.", scenePath); + if (parameters.UseCache && cache != null && !cache.TrySaveToCache(cacheEntry, sceneInfo, usageTags)) + BuildLogger.LogWarning("Unable to cache PreviewSceneDependencyData results for asset '{0}'.", AssetDatabase.GUIDToAssetPath(asset.ToString())); } return ReturnCodes.Success; @@ -94,26 +87,5 @@ static void SetOutputInformation(GUID asset, SceneDependencyInfo sceneInfo, Buil dependencyData.SceneInfo.Add(asset, sceneInfo); dependencyData.SceneUsage.Add(asset, usageTags); } - - static bool TryLoadFromCache(bool useCache, Hash128 hash, ref SceneDependencyInfo sceneInfo, ref BuildUsageTagSet usageTags) - { - SceneDependencyInfo cachedSceneInfo; - BuildUsageTagSet cachedUsageTags; - if (useCache && BuildCache.TryLoadCachedResults(hash, out cachedSceneInfo) && BuildCache.TryLoadCachedResults(hash, out cachedUsageTags)) - { - sceneInfo = cachedSceneInfo; - usageTags = cachedUsageTags; - return true; - } - - return false; - } - - static bool TrySaveToCache(bool useCache, Hash128 hash, SceneDependencyInfo sceneInfo, BuildUsageTagSet usageTags) - { - if (useCache && !(BuildCache.SaveCachedResults(hash, sceneInfo) && BuildCache.SaveCachedResults(hash, usageTags))) - return false; - return true; - } } } diff --git a/Editor/Tasks/ProjectInCleanState.cs b/Editor/Tasks/ProjectInCleanState.cs index 326a079..3d74ac2 100644 --- a/Editor/Tasks/ProjectInCleanState.cs +++ b/Editor/Tasks/ProjectInCleanState.cs @@ -1,8 +1,8 @@ using System; -using UnityEditor.Build.Interfaces; -using UnityEditor.Build.Utilities; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.Utilities; -namespace UnityEditor.Build.Tasks +namespace UnityEditor.Build.Pipeline.Tasks { public struct ProjectInCleanState : IBuildTask { diff --git a/Editor/Tasks/RebuildAtlasCache.cs b/Editor/Tasks/RebuildAtlasCache.cs index e081780..019cba0 100644 --- a/Editor/Tasks/RebuildAtlasCache.cs +++ b/Editor/Tasks/RebuildAtlasCache.cs @@ -1,8 +1,8 @@ using System; -using UnityEditor.Build.Interfaces; +using UnityEditor.Build.Pipeline.Interfaces; using UnityEditor.Sprites; -namespace UnityEditor.Build.Tasks +namespace UnityEditor.Build.Pipeline.Tasks { public struct RebuildAtlasCache : IBuildTask { diff --git a/Editor/Tasks/SetBundleSettingsTypeDB.cs b/Editor/Tasks/SetBundleSettingsTypeDB.cs index 6af64f1..c0b4172 100644 --- a/Editor/Tasks/SetBundleSettingsTypeDB.cs +++ b/Editor/Tasks/SetBundleSettingsTypeDB.cs @@ -1,7 +1,7 @@ using System; -using UnityEditor.Build.Interfaces; +using UnityEditor.Build.Pipeline.Interfaces; -namespace UnityEditor.Build.Tasks +namespace UnityEditor.Build.Pipeline.Tasks { public struct SetBundleSettingsTypeDB : IBuildTask { diff --git a/Editor/Tasks/StripUnusedSpriteSources.cs b/Editor/Tasks/StripUnusedSpriteSources.cs index fa871ea..e82086f 100644 --- a/Editor/Tasks/StripUnusedSpriteSources.cs +++ b/Editor/Tasks/StripUnusedSpriteSources.cs @@ -1,12 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; -using UnityEditor.Build.Interfaces; -using UnityEditor.Build.Utilities; -using UnityEditor.Experimental.Build.AssetBundle; -using UnityEngine; +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.Utilities; -namespace UnityEditor.Build.Tasks +namespace UnityEditor.Build.Pipeline.Tasks { public struct StripUnusedSpriteSources : IBuildTask { @@ -18,26 +17,30 @@ public struct StripUnusedSpriteSources : IBuildTask public ReturnCodes Run(IBuildContext context) { - return Run(context.GetContextObject(), context.GetContextObject()); + IBuildCache cache; + context.TryGetContextObject(out cache); + return Run(context.GetContextObject(), context.GetContextObject(), cache); } - static Hash128 CalculateInputHash(bool useCache, IDependencyData dependencyData) + static void CalcualteCacheEntry(IDependencyData dependencyData, ref CacheEntry cacheEntry) { - if (!useCache) - return new Hash128(); - - return HashingMethods.CalculateMD5Hash(k_Version, dependencyData.AssetInfo, dependencyData.SceneInfo); + cacheEntry.hash = HashingMethods.CalculateMD5Hash(k_Version, dependencyData.AssetInfo, dependencyData.SceneInfo); + cacheEntry.guid = HashingMethods.CalculateMD5Guid("StripUnusedSpriteSources"); } - public static ReturnCodes Run(IBuildParameters parameters, IDependencyData dependencyData) + public static ReturnCodes Run(IBuildParameters parameters, IDependencyData dependencyData, IBuildCache cache = null) { var spriteSourceRef = new Dictionary(); - Hash128 hash = CalculateInputHash(parameters.UseCache, dependencyData); - if (TryLoadFromCache(parameters.UseCache, hash, ref spriteSourceRef)) + var cacheEntry = new CacheEntry(); + if (parameters.UseCache && cache != null) { - SetOutputInformation(spriteSourceRef, dependencyData); - return ReturnCodes.SuccessCached; + CalcualteCacheEntry(dependencyData, ref cacheEntry); + if (cache.TryLoadFromCache(cacheEntry, ref spriteSourceRef)) + { + SetOutputInformation(spriteSourceRef, dependencyData); + return ReturnCodes.SuccessCached; + } } // CreateBundle sprite source ref count map @@ -75,7 +78,7 @@ public static ReturnCodes Run(IBuildParameters parameters, IDependencyData depen SetOutputInformation(spriteSourceRef, dependencyData); - if (!TrySaveToCache(parameters.UseCache, hash, spriteSourceRef)) + if (parameters.UseCache && cache != null && !cache.TrySaveToCache(cacheEntry, spriteSourceRef)) BuildLogger.LogWarning("Unable to cache StripUnusedSpriteSources results."); return ReturnCodes.Success; @@ -92,24 +95,5 @@ static void SetOutputInformation(Dictionary spriteSourceR assetInfo.includedObjects.RemoveAt(0); } } - - static bool TryLoadFromCache(bool useCache, Hash128 hash, ref Dictionary spriteSourceRef) - { - Dictionary cachedSpriteSourceRef; - if (useCache && BuildCache.TryLoadCachedResults(hash, out cachedSpriteSourceRef)) - { - spriteSourceRef = cachedSpriteSourceRef; - return true; - } - - return false; - } - - static bool TrySaveToCache(bool useCache, Hash128 hash, Dictionary spriteSourceRef) - { - if (useCache && !BuildCache.SaveCachedResults(hash, spriteSourceRef)) - return false; - return true; - } } } diff --git a/Editor/Tasks/SwitchToBuildPlatform.cs b/Editor/Tasks/SwitchToBuildPlatform.cs index 37ba930..f450790 100644 --- a/Editor/Tasks/SwitchToBuildPlatform.cs +++ b/Editor/Tasks/SwitchToBuildPlatform.cs @@ -1,7 +1,7 @@ using System; -using UnityEditor.Build.Interfaces; +using UnityEditor.Build.Pipeline.Interfaces; -namespace UnityEditor.Build.Tasks +namespace UnityEditor.Build.Pipeline.Tasks { public struct SwitchToBuildPlatform : IBuildTask { diff --git a/Editor/Tasks/ValidateBundleAssignments.cs b/Editor/Tasks/ValidateBundleAssignments.cs index 1854f6e..17be43b 100644 --- a/Editor/Tasks/ValidateBundleAssignments.cs +++ b/Editor/Tasks/ValidateBundleAssignments.cs @@ -1,29 +1,29 @@ using System; using System.Collections.Generic; -using UnityEditor.Build.Interfaces; -using UnityEditor.Build.Utilities; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.Utilities; -namespace UnityEditor.Build.Tasks +namespace UnityEditor.Build.Pipeline.Tasks { public struct ValidateBundleAssignments : IBuildTask { const int k_Version = 1; public int Version { get { return k_Version; } } - static readonly Type[] k_RequiredTypes = { typeof(IBundleContent) }; + static readonly Type[] k_RequiredTypes = { typeof(IBundleBuildContent) }; public Type[] RequiredContextTypes { get { return k_RequiredTypes; } } public ReturnCodes Run(IBuildContext context) { - return Run(context.GetContextObject()); + return Run(context.GetContextObject()); } - public static ReturnCodes Run(IBundleContent content) + public static ReturnCodes Run(IBundleBuildContent buildContent) { - if (content.BundleLayout.IsNullOrEmpty()) + if (buildContent.BundleLayout.IsNullOrEmpty()) return ReturnCodes.Success; - foreach (KeyValuePair> bundle in content.BundleLayout) + foreach (KeyValuePair> bundle in buildContent.BundleLayout) { if (ValidationMethods.ValidAssetBundle(bundle.Value)) continue; diff --git a/Editor/Tasks/WriteSerializedFiles.cs b/Editor/Tasks/WriteSerializedFiles.cs index 114196d..f5e1d66 100644 --- a/Editor/Tasks/WriteSerializedFiles.cs +++ b/Editor/Tasks/WriteSerializedFiles.cs @@ -1,12 +1,10 @@ using System; -using UnityEditor.Build.WriteTypes; -using UnityEditor.Build.Interfaces; -using UnityEditor.Build.Utilities; -using UnityEditor.Experimental.Build; -using UnityEditor.Experimental.Build.AssetBundle; -using UnityEngine; +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.Utilities; +using UnityEditor.Build.Pipeline.WriteTypes; -namespace UnityEditor.Build.Tasks +namespace UnityEditor.Build.Pipeline.Tasks { public class WriteSerializedFiles : IBuildTask { @@ -20,21 +18,22 @@ public ReturnCodes Run(IBuildContext context) { IProgressTracker tracker; context.TryGetContextObject(out tracker); - return Run(context.GetContextObject(), context.GetContextObject(), context.GetContextObject(), context.GetContextObject(), tracker); + IBuildCache cache; + context.TryGetContextObject(out cache); + return Run(context.GetContextObject(), context.GetContextObject(), context.GetContextObject(), context.GetContextObject(), tracker, cache); } - protected static Hash128 CalculateInputHash(bool useCache, IWriteOperation operation, BuildSettings settings, BuildUsageTagGlobal globalUsage) + static void CalcualteCacheEntry(IWriteOperation operation, BuildSettings settings, BuildUsageTagGlobal globalUsage, ref CacheEntry cacheEntry) { - if (!useCache) - return new Hash128(); + string[] assetHashes = new string[operation.Command.serializeObjects.Count]; + for (var index = 0; index < operation.Command.serializeObjects.Count; index++) + assetHashes[index] = AssetDatabase.GetAssetDependencyHash(operation.Command.serializeObjects[index].serializationObject.guid.ToString()).ToString(); - string[] assetHashes = new string[operation.command.serializeObjects.Count]; - for (var index = 0; index < operation.command.serializeObjects.Count; index++) - assetHashes[index] = AssetDatabase.GetAssetDependencyHash(operation.command.serializeObjects[index].serializationObject.guid.ToString()).ToString(); - return HashingMethods.CalculateMD5Hash(k_Version, operation, assetHashes, settings, globalUsage); + cacheEntry.hash = HashingMethods.CalculateMD5Hash(k_Version, operation.GetHash128(), assetHashes, settings.GetHash128(), globalUsage); + cacheEntry.guid = HashingMethods.CalculateMD5Guid("WriteSerializedFiles", operation.Command.internalName); } - public static ReturnCodes Run(IBuildParameters parameters, IDependencyData dependencyData, IWriteData writeData, IBuildResults results, IProgressTracker tracker = null) + public static ReturnCodes Run(IBuildParameters parameters, IDependencyData dependencyData, IWriteData writeData, IBuildResults results, IProgressTracker tracker = null, IBuildCache cache = null) { BuildUsageTagGlobal globalUSage = new BuildUsageTagGlobal(); foreach (var sceneInfo in dependencyData.SceneInfo) @@ -42,25 +41,31 @@ public static ReturnCodes Run(IBuildParameters parameters, IDependencyData depen foreach (var op in writeData.WriteOperations) { - Hash128 hash = CalculateInputHash(parameters.UseCache, op, parameters.GetContentBuildSettings(), globalUSage); WriteResult result = new WriteResult(); - if (TryLoadFromCache(parameters.UseCache, hash, ref result)) + + var cacheEntry = new CacheEntry(); + if (parameters.UseCache && cache != null) { - if (!tracker.UpdateInfoUnchecked(string.Format("{0} (Cached)", op.command.internalName))) - return ReturnCodes.Canceled; + CalcualteCacheEntry(op, parameters.GetContentBuildSettings(), globalUSage, ref cacheEntry); + if (cache.TryLoadFromCache(cacheEntry, ref result)) + { + if (!tracker.UpdateInfoUnchecked(string.Format("{0} (Cached)", op.Command.internalName))) + return ReturnCodes.Canceled; - SetOutputInformation(op.command.internalName, result, results); - continue; + SetOutputInformation(op.Command.internalName, result, results); + continue; + } } - if (!tracker.UpdateInfoUnchecked(op.command.internalName)) + if (!tracker.UpdateInfoUnchecked(op.Command.internalName)) return ReturnCodes.Canceled; - result = op.Write(parameters.GetTempOrCacheBuildPath(hash), parameters.GetContentBuildSettings(), globalUSage); - SetOutputInformation(op.command.internalName, result, results); + var outputFolder = parameters.UseCache && cache != null ? cache.GetArtifactCacheDirectory(cacheEntry) : parameters.TempOutputFolder; + result = op.Write(outputFolder, parameters.GetContentBuildSettings(), globalUSage); + SetOutputInformation(op.Command.internalName, result, results); - if (!TrySaveToCache(parameters.UseCache, hash, result)) - BuildLogger.LogWarning("Unable to cache WriteSerializedFiles result for file {0}.", op.command.internalName); + if (parameters.UseCache && cache != null && !cache.TrySaveToCache(cacheEntry, result)) + BuildLogger.LogWarning("Unable to cache WriteSerializedFiles result for file {0}.", op.Command.internalName); } return ReturnCodes.Success; @@ -70,23 +75,5 @@ static void SetOutputInformation(string fileName, WriteResult result, IBuildResu { results.WriteResults.Add(fileName, result); } - - static bool TryLoadFromCache(bool useCache, Hash128 hash, ref WriteResult result) - { - WriteResult cachedResult; - if (useCache && BuildCache.TryLoadCachedResults(hash, out cachedResult)) - { - result = cachedResult; - return true; - } - return false; - } - - static bool TrySaveToCache(bool useCache, Hash128 hash, WriteResult result) - { - if (useCache && !BuildCache.SaveCachedResults(hash, result)) - return false; - return true; - } } } diff --git a/Editor/Utilities/BuildCache.cs b/Editor/Utilities/BuildCache.cs index 0cd13cb..f198688 100644 --- a/Editor/Utilities/BuildCache.cs +++ b/Editor/Utilities/BuildCache.cs @@ -1,172 +1,347 @@ -//#define BUILD_CACHE_DEBUG - using System; +using System.Collections.Generic; using System.IO; +using System.Linq; using System.Runtime.Serialization.Formatters.Binary; +#if !NET_4_6 +using System.Threading; +#endif +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.Interfaces; using UnityEngine; -namespace UnityEditor.Build.Utilities +namespace UnityEditor.Build.Pipeline.Utilities { - public static class BuildCache + public class BuildCache : IBuildCache { - private const string kCachePath = "Library/BuildCache"; + interface ICachedDependency + { + CacheEntry asset { get; set; } + CacheEntry[] dependencies { get; set; } + } - public static string GetPathForCachedResults(Hash128 hash) + [Serializable] + struct CachedDependency : ICachedDependency { - var file = hash.ToString(); - return string.Format("{0}/{1}/{2}/Results", kCachePath, file.Substring(0, 2), file); + public CacheEntry asset { get; set; } + public CacheEntry[] dependencies { get; set; } + + public T info; + public BuildUsageTagSet usage; + + public CachedDependency(T assetInfo, BuildUsageTagSet assetUsage) : this() + { + asset = new CacheEntry(); + dependencies = null; + info = assetInfo; + usage = assetUsage; + } } - public static string GetPathForCachedArtifacts(Hash128 hash) + internal const string kCachePath = "Library/BuildCache"; + internal const string kDependencyCachePath = "Library/BuildCache/Dependency"; + internal const string kArtifactCachePath = "Library/BuildCache/Artifact"; + + Dictionary m_HashCache = new Dictionary(); + + Dictionary m_DependencyCache = new Dictionary(); + + public static string GetDependencyCacheDirectory(CacheEntry cacheEntry) { - var file = hash.ToString(); - return string.Format("{0}/{1}/{2}/Artifacts", kCachePath, file.Substring(0, 2), file); + Directory.CreateDirectory(kDependencyCachePath); + return kDependencyCachePath; } - [MenuItem("Window/Build Pipeline/Purge Build Cache", priority = 10)] - public static void PurgeCache() + string IBuildCache.GetDependencyCacheDirectory(CacheEntry cacheEntry) { - if (!EditorUtility.DisplayDialog("Purge Build Cache", "Do you really want to purge your entire build cache?", "Yes", "No")) - return; + return GetDependencyCacheDirectory(cacheEntry); + } - if (Directory.Exists(kCachePath)) - Directory.Delete(kCachePath, true); + public static string GetArtifactCacheDirectory(CacheEntry cacheEntry) + { + var folder = string.Format("{0}/{1}/{2}", kArtifactCachePath, cacheEntry.guid, cacheEntry.hash); + Directory.CreateDirectory(folder); + return folder; + } + + string IBuildCache.GetArtifactCacheDirectory(CacheEntry cacheEntry) + { + return GetArtifactCacheDirectory(cacheEntry); } - public static bool TryLoadCachedResults(Hash128 hash, out T results) + public CacheEntry GetCacheEntry(GUID asset) { - var path = GetPathForCachedResults(hash); - var filePath = string.Format("{0}/{1}", path, typeof(T).Name); - if (!File.Exists(filePath)) + var entry = new CacheEntry { guid = asset }; + if (m_HashCache.TryGetValue(asset, out entry.hash)) + return entry; + + string path = AssetDatabase.GUIDToAssetPath(asset.ToString()); + string assetHash = AssetDatabase.GetAssetDependencyHash(path).ToString(); + + entry.hash = Hash128.Parse(assetHash); + m_HashCache[asset] = entry.hash; + return entry; + } + + static bool LoadFromCache(CacheEntry cacheEntry, out ICachedDependency cachedDependency) + { + // TODO: Cache server integration + try { - BuildLogger.LogCache("false TryLoadCachedResults<{0}>({1}, out ...)", typeof(T).Name, hash.ToString()); - results = default(T); + var file = string.Format("{0}/{1}_{2}.bytes", GetDependencyCacheDirectory(cacheEntry), cacheEntry.guid, cacheEntry.hash); + if (!File.Exists(file)) + { + cachedDependency = default(ICachedDependency); + return false; + } + + var formatter = new BinaryFormatter(); + using (var stream = new FileStream(file, FileMode.Open, FileAccess.Read)) + cachedDependency = (ICachedDependency)formatter.Deserialize(stream); + } + catch (Exception e) + { + BuildLogger.LogException(e); + cachedDependency = default(ICachedDependency); return false; } + return true; + } + static bool LoadFromCache(CacheEntry cacheEntry, out T results) + { + // TODO: Cache server integration try { + var file = string.Format("{0}/{1}.bytes", GetArtifactCacheDirectory(cacheEntry), typeof(T).Name); + if (!File.Exists(file)) + { + results = default(T); + return false; + } + var formatter = new BinaryFormatter(); - using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) + using (var stream = new FileStream(file, FileMode.Open, FileAccess.Read)) results = (T)formatter.Deserialize(stream); - BuildLogger.LogCache("true TryLoadCachedResults<{0}>({1}, out ...)", typeof(T).Name, hash.ToString()); - return true; } catch (Exception e) { - BuildLogger.LogCache("Exception TryLoadCachedResults<{0}>({1}, out ...)", typeof(T).Name, hash.ToString()); BuildLogger.LogException(e); results = default(T); return false; } + return true; } - public static bool TryLoadCachedArtifacts(Hash128 hash, out string[] artifactPaths, out string rootCachePath) + public bool IsCacheEntryValid(CacheEntry cacheEntry) { - rootCachePath = GetPathForCachedArtifacts(hash); - if (!Directory.Exists(rootCachePath)) + ICachedDependency cachedDependency; + if (!m_DependencyCache.TryGetValue(cacheEntry, out cachedDependency)) { - BuildLogger.LogCache("false TryLoadCachedArtifacts({0}, out ..., out ...)", hash.ToString()); - artifactPaths = null; + if (!LoadFromCache(cacheEntry, out cachedDependency)) + return false; + } + + foreach (CacheEntry dependency in cachedDependency.dependencies) + { + if (dependency == GetCacheEntry(dependency.guid)) + continue; return false; } - artifactPaths = Directory.GetFiles(rootCachePath, "*", SearchOption.AllDirectories); - BuildLogger.Log("true TryLoadCachedArtifacts({0}, out ..., out ...)", hash.ToString()); + m_DependencyCache[cacheEntry] = cachedDependency; return true; } - public static bool TryLoadCachedResultsAndArtifacts(Hash128 hash, out T results, out string[] artifactPaths, out string rootCachePath) + public bool TryLoadFromCache(CacheEntry cacheEntry, ref AssetLoadInfo info, ref BuildUsageTagSet usage) + { + ICachedDependency cachedDependency; + if (!m_DependencyCache.TryGetValue(cacheEntry, out cachedDependency)) + return false; + + if (cachedDependency is CachedDependency) + { + var dependency = (CachedDependency)cachedDependency; + info = dependency.info; + usage = dependency.usage; + return true; + } + + return false; + } + + public bool TryLoadFromCache(CacheEntry cacheEntry, ref SceneDependencyInfo info, ref BuildUsageTagSet usage) { - BuildLogger.LogCache("TryLoadCachedResultsAndArtifacts<{0}({1}, out ..., out ..., out ...)", typeof(T).Name, hash.ToString()); - artifactPaths = null; - rootCachePath = GetPathForCachedArtifacts(hash); - if (!TryLoadCachedResults(hash, out results)) + ICachedDependency cachedDependency; + if (!m_DependencyCache.TryGetValue(cacheEntry, out cachedDependency)) return false; - return TryLoadCachedArtifacts(hash, out artifactPaths, out rootCachePath); + if (cachedDependency is CachedDependency) + { + var dependency = (CachedDependency)cachedDependency; + info = dependency.info; + usage = dependency.usage; + return true; + } + + return false; + } + + public bool TryLoadFromCache(CacheEntry cacheEntry, ref T results) + { + T cachedResults; + var success = LoadFromCache(cacheEntry, out cachedResults); + if (success) + results = cachedResults; + return success; + } + + public bool TryLoadFromCache(CacheEntry cacheEntry, ref T1 results1, ref T2 results2) + { + //TODO: try and batch the load into one file + T1 cachedResults1; + T2 cachedResults2; + var success = LoadFromCache(cacheEntry, out cachedResults1); + success = LoadFromCache(cacheEntry, out cachedResults2) & success; + if (success) + { + results1 = cachedResults1; + results2 = cachedResults2; + } + return success; + } + +#if NET_4_6 + static async void WriteToFile(string file, byte[] data) + { + using (var fileStream = new FileStream(file, FileMode.OpenOrCreate, FileAccess.Write)) + await fileStream.WriteAsync(data, 0, data.Length); + } +#else + struct FileWrite + { + public string file; + public byte[] data; + } + + static void Write(object data) + { + var fileWrite = (FileWrite)data; + using (var fileStream = new FileStream(fileWrite.file, FileMode.OpenOrCreate, FileAccess.Write)) + fileStream.Write(fileWrite.data, 0, fileWrite.data.Length); } - public static bool SaveCachedResults(Hash128 hash, T results) + public static void WriteToFile(string file, byte[] data) { - var path = GetPathForCachedResults(hash); - var filePath = string.Format("{0}/{1}", path, typeof(T).Name); + var fileWrite = new FileWrite + { + file = file, + data = data + }; + ThreadPool.QueueUserWorkItem(Write, fileWrite); + } +#endif + + static bool SaveToCache(CacheEntry cacheEntry, ICachedDependency cachedDependency) + { + // TODO: Cache server integration try { - Directory.CreateDirectory(path); + var file = string.Format("{0}/{1}_{2}.bytes", GetDependencyCacheDirectory(cacheEntry), cacheEntry.guid, cacheEntry.hash); var formatter = new BinaryFormatter(); - using (var stream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write)) - formatter.Serialize(stream, results); + using (var stream = new MemoryStream()) + { + formatter.Serialize(stream, cachedDependency); + WriteToFile(file, stream.ToArray()); + } } catch (Exception e) { - BuildLogger.LogCache("Exception SaveCachedResults<{0}>({1}, T ...)", typeof(T).Name, hash.ToString()); BuildLogger.LogException(e); - if (Directory.Exists(path)) - Directory.Delete(path, true); return false; } - BuildLogger.LogCache("true SaveCachedResults<{0}>({1}, T ...)", typeof(T).Name, hash.ToString()); return true; } - public static bool SaveCachedArtifacts(Hash128 hash, string[] artifactPaths, string rootPath) + static bool SaveToCache(CacheEntry cacheEntry, T results) { - var path = GetPathForCachedArtifacts(hash); - - var result = true; + // TODO: Cache server integration try { - Directory.CreateDirectory(path); - foreach (var artifact in artifactPaths) + var file = string.Format("{0}/{1}.bytes", GetArtifactCacheDirectory(cacheEntry), typeof(T).Name); + var formatter = new BinaryFormatter(); + using (var stream = new MemoryStream()) { - var source = string.Format("{0}/{1}", rootPath, artifact); - if (!File.Exists(source)) - { - BuildLogger.LogWarning("Unable to find source file '{0}' to add to the build cache.", artifact); - result = false; - continue; - } - else if (result) - { - var copyToPath = string.Format("{0}/{1}", path, artifact); - var directory = Path.GetDirectoryName(copyToPath); - Directory.CreateDirectory(directory); - File.Copy(source, copyToPath, true); - } + formatter.Serialize(stream, results); + WriteToFile(file, stream.ToArray()); } } catch (Exception e) { BuildLogger.LogException(e); - if (Directory.Exists(path)) - Directory.Delete(path, true); return false; } + return true; + } - if (!result && Directory.Exists(path)) - Directory.Delete(path, true); + public bool TrySaveToCache(CacheEntry cacheEntry, AssetLoadInfo info, BuildUsageTagSet usage) + { + ICachedDependency dependency = new CachedDependency(info, usage); + dependency.asset = cacheEntry; - BuildLogger.LogCache("{0} SaveCachedArtifacts({1}, string[] ..., string ...)", result, hash.ToString()); - return result; + var dependencies = new HashSet(); + foreach (var reference in info.referencedObjects) + { + CacheEntry entry = GetCacheEntry(reference.guid); + dependencies.Add(entry); + } + dependency.dependencies = dependencies.ToArray(); + m_DependencyCache[cacheEntry] = dependency; + + var success = SaveToCache(cacheEntry, dependency); + return success; } - public static bool SaveCachedResultsAndArtifacts(Hash128 hash, T results, string[] artifactPaths, string rootPath) + public bool TrySaveToCache(CacheEntry cacheEntry, SceneDependencyInfo info, BuildUsageTagSet usage) { - BuildLogger.LogCache("SaveCachedResultsAndArtifacts<{0}({1}, T ..., string[] ..., string ...)", typeof(T).Name, hash.ToString()); - if (SaveCachedResults(hash, results) && SaveCachedArtifacts(hash, artifactPaths, rootPath)) - return true; + ICachedDependency dependency = new CachedDependency(info, usage); + dependency.asset = cacheEntry; - var path = GetPathForCachedResults(hash); - if (Directory.Exists(path)) - Directory.Delete(path, true); + var dependencies = new HashSet(); + foreach (var reference in info.referencedObjects) + { + CacheEntry entry = GetCacheEntry(reference.guid); + dependencies.Add(entry); + } + dependency.dependencies = dependencies.ToArray(); + m_DependencyCache[cacheEntry] = dependency; + + var success = SaveToCache(cacheEntry, dependency); + return success; + } - path = GetPathForCachedArtifacts(hash); - if (Directory.Exists(path)) - Directory.Delete(path, true); + public bool TrySaveToCache(CacheEntry cacheEntry, T results) + { + var success = SaveToCache(cacheEntry, results); + return success; + } - return false; + public bool TrySaveToCache(CacheEntry cacheEntry, T1 results1, T2 results2) + { + //TODO: try and batch the save into one file + var success = SaveToCache(cacheEntry, results1); + success &= SaveToCache(cacheEntry, results2); + return success; + } + + [MenuItem("Window/Build Pipeline/Purge Build Cache", priority = 10)] + public static void PurgeCache() + { + if (!EditorUtility.DisplayDialog("Purge Build Cache", "Do you really want to purge your entire build cache?", "Yes", "No")) + return; + if (Directory.Exists(kCachePath)) + Directory.Delete(kCachePath, true); } } -} +} \ No newline at end of file diff --git a/Editor/Utilities/BuildCache.cs.meta b/Editor/Utilities/BuildCache.cs.meta index cfbfd68..b0f47c2 100644 --- a/Editor/Utilities/BuildCache.cs.meta +++ b/Editor/Utilities/BuildCache.cs.meta @@ -1,7 +1,5 @@ fileFormatVersion: 2 -guid: 4664ae20418c56944a2f6c5ab30f82bf -timeCreated: 1504709533 -licenseType: Pro +guid: b2817048551db2447bb961c392abbfd0 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Editor/Utilities/BuildLogger.cs b/Editor/Utilities/BuildLogger.cs index 3b7ed17..a4f894c 100644 --- a/Editor/Utilities/BuildLogger.cs +++ b/Editor/Utilities/BuildLogger.cs @@ -1,7 +1,7 @@ using System.Diagnostics; using Debug = UnityEngine.Debug; -namespace UnityEditor.Build.Utilities +namespace UnityEditor.Build.Pipeline.Utilities { public static class BuildLogger { diff --git a/Editor/Utilities/BuildStateCleanup.cs b/Editor/Utilities/BuildStateCleanup.cs index 5a13b57..950958e 100644 --- a/Editor/Utilities/BuildStateCleanup.cs +++ b/Editor/Utilities/BuildStateCleanup.cs @@ -1,7 +1,7 @@ using System; using System.IO; -namespace UnityEditor.Build.Utilities +namespace UnityEditor.Build.Pipeline.Utilities { public class BuildStateCleanup : IDisposable { diff --git a/Editor/Utilities/CacheEntry.cs b/Editor/Utilities/CacheEntry.cs new file mode 100644 index 0000000..7574d60 --- /dev/null +++ b/Editor/Utilities/CacheEntry.cs @@ -0,0 +1,36 @@ +using System; +using UnityEngine; + +namespace UnityEditor.Build.Pipeline.Utilities +{ + [Serializable] + public struct CacheEntry + { + public Hash128 hash; + public GUID guid; + + public override bool Equals(object obj) + { + if (!(obj is CacheEntry)) + return false; + + var rhs = (CacheEntry)obj; + return rhs == this; + } + + public static bool operator ==(CacheEntry x, CacheEntry y) + { + return x.hash == y.hash && x.guid == y.guid; + } + + public static bool operator !=(CacheEntry x, CacheEntry y) + { + return !(x == y); + } + + public override int GetHashCode() + { + return hash.GetHashCode() ^ guid.GetHashCode(); + } + } +} diff --git a/Editor/Utilities/CacheEntry.cs.meta b/Editor/Utilities/CacheEntry.cs.meta new file mode 100644 index 0000000..cfbfd68 --- /dev/null +++ b/Editor/Utilities/CacheEntry.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 4664ae20418c56944a2f6c5ab30f82bf +timeCreated: 1504709533 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Utilities/ExtensionMethods.cs b/Editor/Utilities/ExtensionMethods.cs index cc47464..6a7aa9c 100644 --- a/Editor/Utilities/ExtensionMethods.cs +++ b/Editor/Utilities/ExtensionMethods.cs @@ -1,8 +1,10 @@ using System.Collections.Generic; +using UnityEditor.Build.Content; +using UnityEngine; -namespace UnityEditor.Build.Utilities +namespace UnityEditor.Build.Pipeline.Utilities { - internal static class ExtensionMethods + static class ExtensionMethods { public static bool IsNullOrEmpty(this ICollection collection) { @@ -40,5 +42,10 @@ public static void Swap(this T[] array, int index1, int index2) array[index2] = array[index1]; array[index1] = t; } + + public static Hash128 GetHash128(this BuildSettings settings) + { + return HashingMethods.CalculateMD5Hash(settings.target, settings.group, settings.buildFlags, settings.typeDB.GetHash128()); + } } } diff --git a/Editor/Utilities/HashingMethods.cs b/Editor/Utilities/HashingMethods.cs index 4dd9b34..a404cde 100644 --- a/Editor/Utilities/HashingMethods.cs +++ b/Editor/Utilities/HashingMethods.cs @@ -4,14 +4,21 @@ using System.Security.Cryptography; using UnityEngine; -namespace UnityEditor.Build.Utilities +namespace UnityEditor.Build.Pipeline.Utilities { public static class HashingMethods { static Hash128 ToHash128(byte[] hash) { - return new Hash128(BitConverter.ToUInt32(hash, 0), BitConverter.ToUInt32(hash, 4), + var result = new Hash128(BitConverter.ToUInt32(hash, 0), BitConverter.ToUInt32(hash, 4), BitConverter.ToUInt32(hash, 8), BitConverter.ToUInt32(hash, 12)); + return result; + } + static GUID ToGUID(byte[] hash) + { + var resultStr = BitConverter.ToString(hash).Replace("-", "").ToLower(); + var result = new GUID(resultStr); + return result; } public static byte[] CalculateStreamMD5(Stream stream) @@ -59,6 +66,7 @@ public static byte[] CalculateMD5(params object[] objects) if (obj != null) formatter.Serialize(stream, obj); } + hash = CalculateStreamMD5(stream); } return hash; @@ -70,6 +78,12 @@ public static Hash128 CalculateMD5Hash(params object[] objects) return ToHash128(hash); } + public static GUID CalculateMD5Guid(params object[] objects) + { + byte[] hash = CalculateMD5(objects); + return ToGUID(hash); + } + public static byte[] CalculateFileMD5(string filePath) { byte[] hash; diff --git a/Editor/Utilities/MD4.cs b/Editor/Utilities/MD4.cs index 79d7fce..bdb65e8 100644 --- a/Editor/Utilities/MD4.cs +++ b/Editor/Utilities/MD4.cs @@ -25,21 +25,21 @@ documentation and/or software. /* Converted to C# by Ryan Caltabiano for Unity Technologies */ -namespace UnityEditor.Build.Utilities +namespace UnityEditor.Build.Pipeline.Utilities { public sealed class MD4 : HashAlgorithm { - private uint[] m_Buffer; - private uint[] m_Block; - private uint m_Bytes; + uint[] m_Buffer; + uint[] m_Block; + uint m_Bytes; - private static readonly byte[] kPadding = { + static readonly byte[] kPadding = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - private MD4() + MD4() { Initialize(); } @@ -72,7 +72,7 @@ protected override void HashCore(byte[] array, int ibStart, int cbSize) var k = c >> 2; var s = (c & 3) << 3; m_Block[k] = (m_Block[k] & ~((uint)255 << (int)s)) | ((uint)b << (int)s); - + if (c == 63) ProcessBlock(); @@ -83,89 +83,89 @@ protected override void HashCore(byte[] array, int ibStart, int cbSize) protected override byte[] HashFinal() { var bytes = BitConverter.GetBytes(m_Bytes << 3); - + var length = ((m_Bytes + 8) & 0x7fffffc0) + 56 - m_Bytes; HashCore(kPadding, 0, (int)length); HashCore(bytes, 0, 4); HashCore(kPadding, kPadding.Length - 4, 4); - + var output = new byte[16]; - output[ 0] = (byte)( m_Buffer[0] & 0xff); - output[ 1] = (byte)((m_Buffer[0] >> 8) & 0xff); - output[ 2] = (byte)((m_Buffer[0] >> 16) & 0xff); - output[ 3] = (byte)((m_Buffer[0] >> 24) & 0xff); - output[ 4] = (byte)( m_Buffer[1] & 0xff); - output[ 5] = (byte)((m_Buffer[1] >> 8) & 0xff); - output[ 6] = (byte)((m_Buffer[1] >> 16) & 0xff); - output[ 7] = (byte)((m_Buffer[1] >> 24) & 0xff); - output[ 8] = (byte)( m_Buffer[2] & 0xff); - output[ 9] = (byte)((m_Buffer[2] >> 8) & 0xff); + output[0] = (byte)(m_Buffer[0] & 0xff); + output[1] = (byte)((m_Buffer[0] >> 8) & 0xff); + output[2] = (byte)((m_Buffer[0] >> 16) & 0xff); + output[3] = (byte)((m_Buffer[0] >> 24) & 0xff); + output[4] = (byte)(m_Buffer[1] & 0xff); + output[5] = (byte)((m_Buffer[1] >> 8) & 0xff); + output[6] = (byte)((m_Buffer[1] >> 16) & 0xff); + output[7] = (byte)((m_Buffer[1] >> 24) & 0xff); + output[8] = (byte)(m_Buffer[2] & 0xff); + output[9] = (byte)((m_Buffer[2] >> 8) & 0xff); output[10] = (byte)((m_Buffer[2] >> 16) & 0xff); output[11] = (byte)((m_Buffer[2] >> 24) & 0xff); - output[12] = (byte)( m_Buffer[3] & 0xff); - output[13] = (byte)((m_Buffer[3] >> 8) & 0xff); + output[12] = (byte)(m_Buffer[3] & 0xff); + output[13] = (byte)((m_Buffer[3] >> 8) & 0xff); output[14] = (byte)((m_Buffer[3] >> 16) & 0xff); output[15] = (byte)((m_Buffer[3] >> 24) & 0xff); return output; } - private void ProcessBlock() + void ProcessBlock() { var buffer = new uint[4]; Array.Copy(m_Buffer, buffer, 4); - + /* Round 1 */ - buffer[0] = RotateLeft(buffer[0] + F(buffer[1], buffer[2], buffer[3]) + m_Block[ 0], 3); - buffer[3] = RotateLeft(buffer[3] + F(buffer[0], buffer[1], buffer[2]) + m_Block[ 1], 7); - buffer[2] = RotateLeft(buffer[2] + F(buffer[3], buffer[0], buffer[1]) + m_Block[ 2], 11); - buffer[1] = RotateLeft(buffer[1] + F(buffer[2], buffer[3], buffer[0]) + m_Block[ 3], 19); - buffer[0] = RotateLeft(buffer[0] + F(buffer[1], buffer[2], buffer[3]) + m_Block[ 4], 3); - buffer[3] = RotateLeft(buffer[3] + F(buffer[0], buffer[1], buffer[2]) + m_Block[ 5], 7); - buffer[2] = RotateLeft(buffer[2] + F(buffer[3], buffer[0], buffer[1]) + m_Block[ 6], 11); - buffer[1] = RotateLeft(buffer[1] + F(buffer[2], buffer[3], buffer[0]) + m_Block[ 7], 19); - buffer[0] = RotateLeft(buffer[0] + F(buffer[1], buffer[2], buffer[3]) + m_Block[ 8], 3); - buffer[3] = RotateLeft(buffer[3] + F(buffer[0], buffer[1], buffer[2]) + m_Block[ 9], 7); + buffer[0] = RotateLeft(buffer[0] + F(buffer[1], buffer[2], buffer[3]) + m_Block[0], 3); + buffer[3] = RotateLeft(buffer[3] + F(buffer[0], buffer[1], buffer[2]) + m_Block[1], 7); + buffer[2] = RotateLeft(buffer[2] + F(buffer[3], buffer[0], buffer[1]) + m_Block[2], 11); + buffer[1] = RotateLeft(buffer[1] + F(buffer[2], buffer[3], buffer[0]) + m_Block[3], 19); + buffer[0] = RotateLeft(buffer[0] + F(buffer[1], buffer[2], buffer[3]) + m_Block[4], 3); + buffer[3] = RotateLeft(buffer[3] + F(buffer[0], buffer[1], buffer[2]) + m_Block[5], 7); + buffer[2] = RotateLeft(buffer[2] + F(buffer[3], buffer[0], buffer[1]) + m_Block[6], 11); + buffer[1] = RotateLeft(buffer[1] + F(buffer[2], buffer[3], buffer[0]) + m_Block[7], 19); + buffer[0] = RotateLeft(buffer[0] + F(buffer[1], buffer[2], buffer[3]) + m_Block[8], 3); + buffer[3] = RotateLeft(buffer[3] + F(buffer[0], buffer[1], buffer[2]) + m_Block[9], 7); buffer[2] = RotateLeft(buffer[2] + F(buffer[3], buffer[0], buffer[1]) + m_Block[10], 11); buffer[1] = RotateLeft(buffer[1] + F(buffer[2], buffer[3], buffer[0]) + m_Block[11], 19); - buffer[0] = RotateLeft(buffer[0] + F(buffer[1], buffer[2], buffer[3]) + m_Block[12], 3); - buffer[3] = RotateLeft(buffer[3] + F(buffer[0], buffer[1], buffer[2]) + m_Block[13], 7); + buffer[0] = RotateLeft(buffer[0] + F(buffer[1], buffer[2], buffer[3]) + m_Block[12], 3); + buffer[3] = RotateLeft(buffer[3] + F(buffer[0], buffer[1], buffer[2]) + m_Block[13], 7); buffer[2] = RotateLeft(buffer[2] + F(buffer[3], buffer[0], buffer[1]) + m_Block[14], 11); buffer[1] = RotateLeft(buffer[1] + F(buffer[2], buffer[3], buffer[0]) + m_Block[15], 19); /* Round 2 */ - buffer[0] = RotateLeft(buffer[0] + G(buffer[1], buffer[2], buffer[3]) + m_Block[ 0] + 0x5A827999, 3); - buffer[3] = RotateLeft(buffer[3] + G(buffer[0], buffer[1], buffer[2]) + m_Block[ 4] + 0x5A827999, 5); - buffer[2] = RotateLeft(buffer[2] + G(buffer[3], buffer[0], buffer[1]) + m_Block[ 8] + 0x5A827999, 9); + buffer[0] = RotateLeft(buffer[0] + G(buffer[1], buffer[2], buffer[3]) + m_Block[0] + 0x5A827999, 3); + buffer[3] = RotateLeft(buffer[3] + G(buffer[0], buffer[1], buffer[2]) + m_Block[4] + 0x5A827999, 5); + buffer[2] = RotateLeft(buffer[2] + G(buffer[3], buffer[0], buffer[1]) + m_Block[8] + 0x5A827999, 9); buffer[1] = RotateLeft(buffer[1] + G(buffer[2], buffer[3], buffer[0]) + m_Block[12] + 0x5A827999, 13); - buffer[0] = RotateLeft(buffer[0] + G(buffer[1], buffer[2], buffer[3]) + m_Block[ 1] + 0x5A827999, 3); - buffer[3] = RotateLeft(buffer[3] + G(buffer[0], buffer[1], buffer[2]) + m_Block[ 5] + 0x5A827999, 5); - buffer[2] = RotateLeft(buffer[2] + G(buffer[3], buffer[0], buffer[1]) + m_Block[ 9] + 0x5A827999, 9); + buffer[0] = RotateLeft(buffer[0] + G(buffer[1], buffer[2], buffer[3]) + m_Block[1] + 0x5A827999, 3); + buffer[3] = RotateLeft(buffer[3] + G(buffer[0], buffer[1], buffer[2]) + m_Block[5] + 0x5A827999, 5); + buffer[2] = RotateLeft(buffer[2] + G(buffer[3], buffer[0], buffer[1]) + m_Block[9] + 0x5A827999, 9); buffer[1] = RotateLeft(buffer[1] + G(buffer[2], buffer[3], buffer[0]) + m_Block[13] + 0x5A827999, 13); - buffer[0] = RotateLeft(buffer[0] + G(buffer[1], buffer[2], buffer[3]) + m_Block[ 2] + 0x5A827999, 3); - buffer[3] = RotateLeft(buffer[3] + G(buffer[0], buffer[1], buffer[2]) + m_Block[ 6] + 0x5A827999, 5); - buffer[2] = RotateLeft(buffer[2] + G(buffer[3], buffer[0], buffer[1]) + m_Block[10] + 0x5A827999, 9); + buffer[0] = RotateLeft(buffer[0] + G(buffer[1], buffer[2], buffer[3]) + m_Block[2] + 0x5A827999, 3); + buffer[3] = RotateLeft(buffer[3] + G(buffer[0], buffer[1], buffer[2]) + m_Block[6] + 0x5A827999, 5); + buffer[2] = RotateLeft(buffer[2] + G(buffer[3], buffer[0], buffer[1]) + m_Block[10] + 0x5A827999, 9); buffer[1] = RotateLeft(buffer[1] + G(buffer[2], buffer[3], buffer[0]) + m_Block[14] + 0x5A827999, 13); - buffer[0] = RotateLeft(buffer[0] + G(buffer[1], buffer[2], buffer[3]) + m_Block[ 3] + 0x5A827999, 3); - buffer[3] = RotateLeft(buffer[3] + G(buffer[0], buffer[1], buffer[2]) + m_Block[ 7] + 0x5A827999, 5); - buffer[2] = RotateLeft(buffer[2] + G(buffer[3], buffer[0], buffer[1]) + m_Block[11] + 0x5A827999, 9); + buffer[0] = RotateLeft(buffer[0] + G(buffer[1], buffer[2], buffer[3]) + m_Block[3] + 0x5A827999, 3); + buffer[3] = RotateLeft(buffer[3] + G(buffer[0], buffer[1], buffer[2]) + m_Block[7] + 0x5A827999, 5); + buffer[2] = RotateLeft(buffer[2] + G(buffer[3], buffer[0], buffer[1]) + m_Block[11] + 0x5A827999, 9); buffer[1] = RotateLeft(buffer[1] + G(buffer[2], buffer[3], buffer[0]) + m_Block[15] + 0x5A827999, 13); /* Round 3 */ - buffer[0] = RotateLeft(buffer[0] + H(buffer[1], buffer[2], buffer[3]) + m_Block[ 0] + 0x6ED9EBA1, 3); - buffer[3] = RotateLeft(buffer[3] + H(buffer[0], buffer[1], buffer[2]) + m_Block[ 8] + 0x6ED9EBA1, 9); - buffer[2] = RotateLeft(buffer[2] + H(buffer[3], buffer[0], buffer[1]) + m_Block[ 4] + 0x6ED9EBA1, 11); + buffer[0] = RotateLeft(buffer[0] + H(buffer[1], buffer[2], buffer[3]) + m_Block[0] + 0x6ED9EBA1, 3); + buffer[3] = RotateLeft(buffer[3] + H(buffer[0], buffer[1], buffer[2]) + m_Block[8] + 0x6ED9EBA1, 9); + buffer[2] = RotateLeft(buffer[2] + H(buffer[3], buffer[0], buffer[1]) + m_Block[4] + 0x6ED9EBA1, 11); buffer[1] = RotateLeft(buffer[1] + H(buffer[2], buffer[3], buffer[0]) + m_Block[12] + 0x6ED9EBA1, 15); - buffer[0] = RotateLeft(buffer[0] + H(buffer[1], buffer[2], buffer[3]) + m_Block[ 2] + 0x6ED9EBA1, 3); - buffer[3] = RotateLeft(buffer[3] + H(buffer[0], buffer[1], buffer[2]) + m_Block[10] + 0x6ED9EBA1, 9); - buffer[2] = RotateLeft(buffer[2] + H(buffer[3], buffer[0], buffer[1]) + m_Block[ 6] + 0x6ED9EBA1, 11); + buffer[0] = RotateLeft(buffer[0] + H(buffer[1], buffer[2], buffer[3]) + m_Block[2] + 0x6ED9EBA1, 3); + buffer[3] = RotateLeft(buffer[3] + H(buffer[0], buffer[1], buffer[2]) + m_Block[10] + 0x6ED9EBA1, 9); + buffer[2] = RotateLeft(buffer[2] + H(buffer[3], buffer[0], buffer[1]) + m_Block[6] + 0x6ED9EBA1, 11); buffer[1] = RotateLeft(buffer[1] + H(buffer[2], buffer[3], buffer[0]) + m_Block[14] + 0x6ED9EBA1, 15); - buffer[0] = RotateLeft(buffer[0] + H(buffer[1], buffer[2], buffer[3]) + m_Block[ 1] + 0x6ED9EBA1, 3); - buffer[3] = RotateLeft(buffer[3] + H(buffer[0], buffer[1], buffer[2]) + m_Block[ 9] + 0x6ED9EBA1, 9); - buffer[2] = RotateLeft(buffer[2] + H(buffer[3], buffer[0], buffer[1]) + m_Block[ 5] + 0x6ED9EBA1, 11); + buffer[0] = RotateLeft(buffer[0] + H(buffer[1], buffer[2], buffer[3]) + m_Block[1] + 0x6ED9EBA1, 3); + buffer[3] = RotateLeft(buffer[3] + H(buffer[0], buffer[1], buffer[2]) + m_Block[9] + 0x6ED9EBA1, 9); + buffer[2] = RotateLeft(buffer[2] + H(buffer[3], buffer[0], buffer[1]) + m_Block[5] + 0x6ED9EBA1, 11); buffer[1] = RotateLeft(buffer[1] + H(buffer[2], buffer[3], buffer[0]) + m_Block[13] + 0x6ED9EBA1, 15); - buffer[0] = RotateLeft(buffer[0] + H(buffer[1], buffer[2], buffer[3]) + m_Block[ 3] + 0x6ED9EBA1, 3); - buffer[3] = RotateLeft(buffer[3] + H(buffer[0], buffer[1], buffer[2]) + m_Block[11] + 0x6ED9EBA1, 9); - buffer[2] = RotateLeft(buffer[2] + H(buffer[3], buffer[0], buffer[1]) + m_Block[ 7] + 0x6ED9EBA1, 11); + buffer[0] = RotateLeft(buffer[0] + H(buffer[1], buffer[2], buffer[3]) + m_Block[3] + 0x6ED9EBA1, 3); + buffer[3] = RotateLeft(buffer[3] + H(buffer[0], buffer[1], buffer[2]) + m_Block[11] + 0x6ED9EBA1, 9); + buffer[2] = RotateLeft(buffer[2] + H(buffer[3], buffer[0], buffer[1]) + m_Block[7] + 0x6ED9EBA1, 11); buffer[1] = RotateLeft(buffer[1] + H(buffer[2], buffer[3], buffer[0]) + m_Block[15] + 0x6ED9EBA1, 15); unchecked @@ -177,25 +177,25 @@ private void ProcessBlock() } } - private static uint F(uint x, uint y, uint z) + static uint F(uint x, uint y, uint z) { // XY v not(X) Z return (x & y) | (~x & z); } - private static uint G(uint x, uint y, uint z) + static uint G(uint x, uint y, uint z) { // XY v XZ v YZ return (x & y) | (x & z) | (y & z); } - private static uint H(uint x, uint y, uint z) + static uint H(uint x, uint y, uint z) { - // X xor Y xor Z + // X XOR Y XOR Z return x ^ y ^ z; } - private static uint RotateLeft(uint x, uint n) + static uint RotateLeft(uint x, uint n) { return (x << (int)n) | (x >> (32 - (int)n)); } diff --git a/Editor/Utilities/ProgressLoggingTracker.cs b/Editor/Utilities/ProgressLoggingTracker.cs index 8e9c99d..2c7c59a 100644 --- a/Editor/Utilities/ProgressLoggingTracker.cs +++ b/Editor/Utilities/ProgressLoggingTracker.cs @@ -1,41 +1,30 @@ using System; -using UnityEditor.Build.Interfaces; -namespace UnityEditor.Build.Utilities +namespace UnityEditor.Build.Pipeline.Utilities { - public class ProgressLoggingTracker : IProgressTracker, IDisposable + public class ProgressLoggingTracker : ProgressTracker { - public int TaskCount { get; set; } - - public float Progress { get { return m_CurrentTask / (float)TaskCount; } } - - protected int m_CurrentTask = 0; - - protected string m_CurrentTaskTitle = ""; - public ProgressLoggingTracker() { BuildLogger.Log(string.Format("[{0}] Progress Tracker Started.", DateTime.Now)); } - public bool UpdateTask(string taskTitle) + public override bool UpdateTask(string taskTitle) { - m_CurrentTask++; - m_CurrentTaskTitle = taskTitle; BuildLogger.Log(string.Format("[{0}] {1:P2} Running Task: '{2}'", DateTime.Now, Progress, m_CurrentTaskTitle)); - return !EditorUtility.DisplayCancelableProgressBar(m_CurrentTaskTitle, "", Progress); + return base.UpdateInfo(taskTitle); } - public bool UpdateInfo(string taskInfo) + public override bool UpdateInfo(string taskInfo) { BuildLogger.Log(string.Format("[{0}] {1:P2} Running Task: '{2}' Information: '{3}'", DateTime.Now, Progress, m_CurrentTaskTitle, taskInfo)); - return !EditorUtility.DisplayCancelableProgressBar(m_CurrentTaskTitle, taskInfo, Progress); + return base.UpdateInfo(taskInfo); } - public void Dispose() + public override void Dispose() { BuildLogger.Log(string.Format("[{0}] Progress Tracker Completed.", DateTime.Now)); - EditorUtility.ClearProgressBar(); + base.Dispose(); } } } diff --git a/Editor/Utilities/ProgressTracker.cs b/Editor/Utilities/ProgressTracker.cs index 8557c74..d9184b0 100644 --- a/Editor/Utilities/ProgressTracker.cs +++ b/Editor/Utilities/ProgressTracker.cs @@ -1,7 +1,7 @@ using System; -using UnityEditor.Build.Interfaces; +using UnityEditor.Build.Pipeline.Interfaces; -namespace UnityEditor.Build.Utilities +namespace UnityEditor.Build.Pipeline.Utilities { public class ProgressTracker : IProgressTracker, IDisposable { @@ -9,23 +9,41 @@ public class ProgressTracker : IProgressTracker, IDisposable public float Progress { get { return m_CurrentTask / (float)TaskCount; } } + public uint UpdatesPerSecond + { + get { return (uint)(k_TicksPerSecond / m_UpdateFrequency); } + set { m_UpdateFrequency = k_TicksPerSecond / Math.Max(value, 1); } + } + protected int m_CurrentTask = 0; protected string m_CurrentTaskTitle = ""; - public bool UpdateTask(string taskTitle) + protected long m_TimeStamp = 0; + + protected long m_UpdateFrequency = k_TicksPerSecond / 100; + + const long k_TicksPerSecond = 10000000; + + public virtual bool UpdateTask(string taskTitle) { m_CurrentTask++; m_CurrentTaskTitle = taskTitle; + m_TimeStamp = 0; return !EditorUtility.DisplayCancelableProgressBar(m_CurrentTaskTitle, "", Progress); } - public bool UpdateInfo(string taskInfo) + public virtual bool UpdateInfo(string taskInfo) { + var currentTicks = DateTime.Now.Ticks; + if (currentTicks - m_TimeStamp < m_UpdateFrequency) + return true; + + m_TimeStamp = currentTicks; return !EditorUtility.DisplayCancelableProgressBar(m_CurrentTaskTitle, taskInfo, Progress); } - public void Dispose() + public virtual void Dispose() { EditorUtility.ClearProgressBar(); } diff --git a/Editor/Utilities/SceneStateCleanup.cs b/Editor/Utilities/SceneStateCleanup.cs index aa1d079..e0e81e8 100644 --- a/Editor/Utilities/SceneStateCleanup.cs +++ b/Editor/Utilities/SceneStateCleanup.cs @@ -1,4 +1,5 @@ using System; +using UnityEditor.Build.Pipeline.Utilities; using UnityEditor.SceneManagement; namespace UnityEditor.Build.Utilities diff --git a/Editor/Utilities/TimeThrottledProgressTracker.cs b/Editor/Utilities/TimeThrottledProgressTracker.cs index de8b63d..916de5e 100644 --- a/Editor/Utilities/TimeThrottledProgressTracker.cs +++ b/Editor/Utilities/TimeThrottledProgressTracker.cs @@ -1,5 +1,5 @@ using System; -using UnityEditor.Build.Interfaces; +using UnityEditor.Build.Pipeline.Interfaces; namespace UnityEditor.Build.Utilities { diff --git a/Editor/Utilities/TrackerExtensions.cs b/Editor/Utilities/TrackerExtensions.cs new file mode 100644 index 0000000..4596b9e --- /dev/null +++ b/Editor/Utilities/TrackerExtensions.cs @@ -0,0 +1,23 @@ +using System.Text.RegularExpressions; +using UnityEditor.Build.Pipeline.Interfaces; + +namespace UnityEditor.Build.Pipeline.Utilities +{ + public static class TrackerExtensions + { + public static string HumanReadable(this string camelCased) + { + return Regex.Replace(camelCased, @"(\B[A-Z]+?(?=[A-Z][^A-Z])|\B[A-Z]+?(?=[^A-Z]))", " $1"); + } + + public static bool UpdateTaskUnchecked(this IProgressTracker tracker, string taskTitle) + { + return tracker == null || tracker.UpdateTask(taskTitle); + } + + public static bool UpdateInfoUnchecked(this IProgressTracker tracker, string taskInfo) + { + return tracker == null || tracker.UpdateInfo(taskInfo); + } + } +} \ No newline at end of file diff --git a/Editor/Tasks/CopySerializedFiles.cs.meta b/Editor/Utilities/TrackerExtensions.cs.meta similarity index 83% rename from Editor/Tasks/CopySerializedFiles.cs.meta rename to Editor/Utilities/TrackerExtensions.cs.meta index 1ffe141..cd1052d 100644 --- a/Editor/Tasks/CopySerializedFiles.cs.meta +++ b/Editor/Utilities/TrackerExtensions.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 7d646fb15eef0094dac768d2206de888 +guid: cc721af777e8101459b9a2ea31544b01 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Editor/Utilities/ValidationMethods.cs b/Editor/Utilities/ValidationMethods.cs index 32abf68..47d16c0 100644 --- a/Editor/Utilities/ValidationMethods.cs +++ b/Editor/Utilities/ValidationMethods.cs @@ -3,9 +3,9 @@ using System.Linq; using UnityEditor.SceneManagement; -namespace UnityEditor.Build.Utilities +namespace UnityEditor.Build.Pipeline.Utilities { - internal static class ValidationMethods + static class ValidationMethods { public static bool ValidScene(GUID asset) { diff --git a/Editor/WriteTypes/AssetBundleWriteOperation.cs b/Editor/WriteTypes/AssetBundleWriteOperation.cs index 41a4ebe..f51950a 100644 --- a/Editor/WriteTypes/AssetBundleWriteOperation.cs +++ b/Editor/WriteTypes/AssetBundleWriteOperation.cs @@ -1,21 +1,28 @@ using System; -using UnityEditor.Experimental.Build; -using UnityEditor.Experimental.Build.AssetBundle; +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.Utilities; +using UnityEngine; -namespace UnityEditor.Build.WriteTypes +namespace UnityEditor.Build.Pipeline.WriteTypes { [Serializable] public struct AssetBundleWriteOperation : IWriteOperation { - public WriteCommand command { get; set; } - public BuildUsageTagSet usageSet { get; set; } - public BuildReferenceMap referenceMap { get; set; } + public WriteCommand Command { get; set; } + public BuildUsageTagSet UsageSet { get; set; } + public BuildReferenceMap ReferenceMap { get; set; } - public AssetBundleInfo info { get; set; } + public AssetBundleInfo Info { get; set; } public WriteResult Write(string outputFolder, BuildSettings settings, BuildUsageTagGlobal globalUsage) { - return BundleBuildInterface.WriteSerializedFile(outputFolder, command, settings, globalUsage, usageSet, referenceMap, info); + return ContentBuildInterface.WriteSerializedFile(outputFolder, Command, settings, globalUsage, UsageSet, ReferenceMap, Info); + } + + public Hash128 GetHash128() + { + return HashingMethods.CalculateMD5Hash(Command, UsageSet.GetHash128(), ReferenceMap.GetHash128(), Info); } } } diff --git a/Editor/WriteTypes/IWriteOperation.cs b/Editor/WriteTypes/IWriteOperation.cs deleted file mode 100644 index 2fa7b36..0000000 --- a/Editor/WriteTypes/IWriteOperation.cs +++ /dev/null @@ -1,16 +0,0 @@ -using UnityEditor.Experimental.Build; -using UnityEditor.Experimental.Build.AssetBundle; - -namespace UnityEditor.Build.WriteTypes -{ - public interface IWriteOperation - { - WriteCommand command { get; set; } - - BuildUsageTagSet usageSet { get; set; } - - BuildReferenceMap referenceMap { get; set; } - - WriteResult Write(string outputFolder, BuildSettings settings, BuildUsageTagGlobal globalUsage); - } -} diff --git a/Editor/WriteTypes/RawWriteOperation.cs b/Editor/WriteTypes/RawWriteOperation.cs index f368e41..23b5613 100644 --- a/Editor/WriteTypes/RawWriteOperation.cs +++ b/Editor/WriteTypes/RawWriteOperation.cs @@ -1,19 +1,26 @@ using System; -using UnityEditor.Experimental.Build; -using UnityEditor.Experimental.Build.AssetBundle; +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.Utilities; +using UnityEngine; -namespace UnityEditor.Build.WriteTypes +namespace UnityEditor.Build.Pipeline.WriteTypes { [Serializable] public struct RawWriteOperation : IWriteOperation { - public WriteCommand command { get; set; } - public BuildUsageTagSet usageSet { get; set; } - public BuildReferenceMap referenceMap { get; set; } + public WriteCommand Command { get; set; } + public BuildUsageTagSet UsageSet { get; set; } + public BuildReferenceMap ReferenceMap { get; set; } public WriteResult Write(string outputFolder, BuildSettings settings, BuildUsageTagGlobal globalUsage) { - return BundleBuildInterface.WriteSerializedFile(outputFolder, command, settings, globalUsage, usageSet, referenceMap); + return ContentBuildInterface.WriteSerializedFile(outputFolder, Command, settings, globalUsage, UsageSet, ReferenceMap); + } + + public Hash128 GetHash128() + { + return HashingMethods.CalculateMD5Hash(Command, UsageSet.GetHash128(), ReferenceMap.GetHash128()); } } } diff --git a/Editor/WriteTypes/SceneBundleWriteOperation.cs b/Editor/WriteTypes/SceneBundleWriteOperation.cs index 9dda9d4..8f8502e 100644 --- a/Editor/WriteTypes/SceneBundleWriteOperation.cs +++ b/Editor/WriteTypes/SceneBundleWriteOperation.cs @@ -1,25 +1,32 @@ using System; -using UnityEditor.Experimental.Build; -using UnityEditor.Experimental.Build.AssetBundle; +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.Utilities; +using UnityEngine; -namespace UnityEditor.Build.WriteTypes +namespace UnityEditor.Build.Pipeline.WriteTypes { [Serializable] public struct SceneBundleWriteOperation : IWriteOperation { - public WriteCommand command { get; set; } - public BuildUsageTagSet usageSet { get; set; } - public BuildReferenceMap referenceMap { get; set; } + public WriteCommand Command { get; set; } + public BuildUsageTagSet UsageSet { get; set; } + public BuildReferenceMap ReferenceMap { get; set; } - public string scene { get; set; } - public string processedScene { get; set; } - public PreloadInfo preloadInfo { get; set; } + public string Scene { get; set; } + public string ProcessedScene { get; set; } + public PreloadInfo PreloadInfo { get; set; } - public SceneBundleInfo info { get; set; } + public SceneBundleInfo Info { get; set; } public WriteResult Write(string outputFolder, BuildSettings settings, BuildUsageTagGlobal globalUsage) { - return BundleBuildInterface.WriteSceneSerializedFile(outputFolder, scene, processedScene, command, settings, globalUsage, usageSet, referenceMap, preloadInfo, info); + return ContentBuildInterface.WriteSceneSerializedFile(outputFolder, Scene, ProcessedScene, Command, settings, globalUsage, UsageSet, ReferenceMap, PreloadInfo, Info); + } + + public Hash128 GetHash128() + { + return HashingMethods.CalculateMD5Hash(Command, UsageSet.GetHash128(), ReferenceMap.GetHash128(), Scene, ProcessedScene, PreloadInfo, Info); } } } diff --git a/Editor/WriteTypes/SceneDataWriteOperation.cs b/Editor/WriteTypes/SceneDataWriteOperation.cs index b882165..de1cf40 100644 --- a/Editor/WriteTypes/SceneDataWriteOperation.cs +++ b/Editor/WriteTypes/SceneDataWriteOperation.cs @@ -1,23 +1,30 @@ using System; -using UnityEditor.Experimental.Build; -using UnityEditor.Experimental.Build.AssetBundle; +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.Utilities; +using UnityEngine; -namespace UnityEditor.Build.WriteTypes +namespace UnityEditor.Build.Pipeline.WriteTypes { [Serializable] public struct SceneDataWriteOperation : IWriteOperation { - public WriteCommand command { get; set; } - public BuildUsageTagSet usageSet { get; set; } - public BuildReferenceMap referenceMap { get; set; } + public WriteCommand Command { get; set; } + public BuildUsageTagSet UsageSet { get; set; } + public BuildReferenceMap ReferenceMap { get; set; } - public string scene { get; set; } - public string processedScene { get; set; } - public PreloadInfo preloadInfo { get; set; } + public string Scene { get; set; } + public string ProcessedScene { get; set; } + public PreloadInfo PreloadInfo { get; set; } public WriteResult Write(string outputFolder, BuildSettings settings, BuildUsageTagGlobal globalUsage) { - return BundleBuildInterface.WriteSceneSerializedFile(outputFolder, scene, processedScene, command, settings, globalUsage, usageSet, referenceMap, preloadInfo); + return ContentBuildInterface.WriteSceneSerializedFile(outputFolder, Scene, ProcessedScene, Command, settings, globalUsage, UsageSet, ReferenceMap, PreloadInfo); + } + + public Hash128 GetHash128() + { + return HashingMethods.CalculateMD5Hash(Command, UsageSet.GetHash128(), ReferenceMap.GetHash128(), Scene, ProcessedScene, PreloadInfo); } } } diff --git a/Editor/WriteTypes/SceneRawWriteOperation.cs b/Editor/WriteTypes/SceneRawWriteOperation.cs index c6c1df0..3407b97 100644 --- a/Editor/WriteTypes/SceneRawWriteOperation.cs +++ b/Editor/WriteTypes/SceneRawWriteOperation.cs @@ -1,22 +1,29 @@ using System; -using UnityEditor.Experimental.Build; -using UnityEditor.Experimental.Build.AssetBundle; +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.Utilities; +using UnityEngine; -namespace UnityEditor.Build.WriteTypes +namespace UnityEditor.Build.Pipeline.WriteTypes { [Serializable] public struct SceneRawWriteOperation : IWriteOperation { - public WriteCommand command { get; set; } - public BuildUsageTagSet usageSet { get; set; } - public BuildReferenceMap referenceMap { get; set; } + public WriteCommand Command { get; set; } + public BuildUsageTagSet UsageSet { get; set; } + public BuildReferenceMap ReferenceMap { get; set; } - public string scene { get; set; } - public string processedScene { get; set; } + public string Scene { get; set; } + public string ProcessedScene { get; set; } public WriteResult Write(string outputFolder, BuildSettings settings, BuildUsageTagGlobal globalUsage) { - return BundleBuildInterface.WriteSceneSerializedFile(outputFolder, scene, processedScene, command, settings, globalUsage, usageSet, referenceMap); + return ContentBuildInterface.WriteSceneSerializedFile(outputFolder, Scene, ProcessedScene, Command, settings, globalUsage, UsageSet, ReferenceMap); + } + + public Hash128 GetHash128() + { + return HashingMethods.CalculateMD5Hash(Command, UsageSet.GetHash128(), ReferenceMap.GetHash128(), Scene, ProcessedScene); } } } diff --git a/Tests/Editor/ScriptableBuildPipelineTests.cs b/Tests/Editor/ScriptableBuildPipelineTests.cs new file mode 100644 index 0000000..fbfaf9f --- /dev/null +++ b/Tests/Editor/ScriptableBuildPipelineTests.cs @@ -0,0 +1,272 @@ +using System.Collections; +using System.IO; +using System; +using NUnit.Framework; +using UnityEditor; +using UnityEditor.SceneManagement; +using UnityEngine; +using UnityEngine.SceneManagement; +using UnityEngine.TestTools; +using System.Collections.Generic; +using System.Linq; +using UnityEditor.Build.Content; +using UnityEditor.Build.Pipeline; +using UnityEditor.Build.Pipeline.Content; +using UnityEditor.Build.Pipeline.Interfaces; +using UnityEditor.Build.Pipeline.Tasks; + +[TestFixture] +class ScriptableBuildPipelineTests +{ + const string k_FolderPath = "Test"; + const string k_TmpPath = "tmp"; + const string k_ScenePath = "Assets/testScene.unity"; + string k_TestAssetsPath = "Assets/TestAssetsOnlyWillBeDeleted"; + string k_CubePath = ""; + + [OneTimeSetUp] + public void Setup() + { + EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo(); + Directory.CreateDirectory(k_TestAssetsPath); + k_CubePath = k_TestAssetsPath + "/Cube.prefab"; + PrefabUtility.CreatePrefab(k_CubePath, GameObject.CreatePrimitive(PrimitiveType.Cube)); + } + + [OneTimeTearDown] + public void Cleanup() + { + EditorSceneManager.NewScene(NewSceneSetup.EmptyScene); + AssetDatabase.DeleteAsset(k_ScenePath); + CleanupFolders(); + } + + [UnityTest] + public IEnumerator BuildPipeline_AssetBundleBuild_DoesNotResetUnsavedScene() + { + Scene s = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene); + yield return null; + EditorSceneManager.SaveScene(s, k_ScenePath); + GameObject.CreatePrimitive(PrimitiveType.Cube); + EditorSceneManager.MarkSceneDirty(s); + + GameObject objectWeAdded = GameObject.Find("Cube"); + Assert.IsNotNull(objectWeAdded, "No object before entering playmode"); + Assert.AreEqual("testScene", EditorSceneManager.GetActiveScene().name); + + IBuildParameters buildParameters = GetBuildParameters(k_FolderPath, k_TmpPath); + IBundleBuildContent buildContent = GetBundleContent(); + IBundleBuildResults results; + + ReturnCodes code = ContentPipeline.BuildAssetBundles(buildParameters, buildContent, out results); + Assert.AreEqual(ReturnCodes.UnsavedChanges, code); + + Assert.AreEqual("testScene", EditorSceneManager.GetActiveScene().name); + objectWeAdded = GameObject.Find("Cube"); + Assert.IsNotNull(objectWeAdded, "No object after entering playmode"); + } + + [UnityTest] + public IEnumerator DefaultBuildTasks_ProjectInCleanState() + { + Scene s = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene); + yield return null; + ReturnCodes code = ProjectInCleanState.Run(); + Assert.AreEqual(ReturnCodes.Success, code); + EditorSceneManager.MarkSceneDirty(s); + code = ProjectInCleanState.Run(); + Assert.AreEqual(ReturnCodes.UnsavedChanges, code); + } + + + [Test] + public void DefaultBuildTasks_WriteSerialziedFiles() + { + IBuildParameters buildParams = GetBuildParameters(k_FolderPath, k_TmpPath); + IDependencyData dependencyData = new BuildDependencyData(); + IWriteData writeData = new BuildWriteData(); + IBuildResults results = new BuildResults(); + + ReturnCodes code = WriteSerializedFiles.Run(buildParams, dependencyData, writeData, results); + Assert.AreEqual(ReturnCodes.Success, code); + } + + [Test] + public void DefaultBuildTasks_GenerateBundlePacking() + { + IBundleBuildContent buildContent = GetBundleContent(); + IDependencyData dep = GetDependancyData(); + IBundleWriteData writeData = new BundleWriteData(); + IDeterministicIdentifiers determinsiticId = new PrefabPackedIdentifiers(); + + ReturnCodes code = GenerateBundlePacking.Run(buildContent, dep, writeData, determinsiticId); + Assert.AreEqual(ReturnCodes.Success, code); + } + + [Test] + public void DefaultBuildTasks_GenerateBundleCommands() + { + IBundleBuildContent buildContent = GetBundleContent(); + IDependencyData dep = GetDependancyData(); + IBundleWriteData writeData = new BundleWriteData(); + IDeterministicIdentifiers determinsiticId = new PrefabPackedIdentifiers(); + + GenerateBundlePacking.Run(buildContent, dep, writeData, determinsiticId); + + ReturnCodes code = GenerateBundleCommands.Run(buildContent, dep, writeData, determinsiticId); + Assert.AreEqual(ReturnCodes.Success, code); + } + + [Test] + public void DefaultBuildTasks_GenerateBundleMaps() + { + IDependencyData dep = GetDependancyData(); + IBundleWriteData writeData = new BundleWriteData(); + + ReturnCodes code = GenerateBundleMaps.Run(dep, writeData); + Assert.AreEqual(ReturnCodes.Success, code); + } + + [Test] + public void DefaultBuildTasks_PostPackingCallback() + { + bool packingCallbackCalled = false; + + IBuildParameters buildParams = GetBuildParameters(k_FolderPath, k_TmpPath); + IDependencyData dep = GetDependancyData(); + IBundleWriteData writeData = new BundleWriteData(); + BuildCallbacks callback = new BuildCallbacks(); + callback.PostPackingCallback = (parameters, data, arg3) => + { + packingCallbackCalled = true; + return ReturnCodes.Success; + }; + + ReturnCodes code = PostPackingCallback.Run(buildParams, dep, writeData, callback); + Assert.AreEqual(ReturnCodes.Success, code); + Assert.IsTrue(packingCallbackCalled); + } + + [Test] + public void DefaultBuildTasks_PostWritingCallback() + { + bool writingCallbackCalled = false; + + IBuildParameters buildParameters = GetBuildParameters(k_FolderPath, k_TmpPath); + IDependencyData dep = GetDependancyData(); + IWriteData writeData = new BuildWriteData(); + IBuildResults results = new BuildResults(); + BuildCallbacks callback = new BuildCallbacks(); + callback.PostWritingCallback = (parameters, data, arg3, arg4) => + { + writingCallbackCalled = true; + return ReturnCodes.Success; + }; + + ReturnCodes code = PostWritingCallback.Run(buildParameters, dep, writeData, results, callback); + Assert.AreEqual(ReturnCodes.Success, code); + Assert.IsTrue(writingCallbackCalled); + } + + [Test] + public void DefaultBuildTasks_PostDependencyCallback() + { + bool dependencyCallbackCalled = false; + + IBuildParameters buildParameters = GetBuildParameters(k_FolderPath, k_TmpPath); + IDependencyData dep = GetDependancyData(); + BuildCallbacks callback = new BuildCallbacks(); + callback.PostDependencyCallback = (parameters, data) => + { + dependencyCallbackCalled = true; + return ReturnCodes.Success; + }; + + ReturnCodes code = PostDependencyCallback.Run(buildParameters, dep, callback); + Assert.AreEqual(ReturnCodes.Success, code); + Assert.IsTrue(dependencyCallbackCalled); + } + + [Test] + public void DefaultBuildTasks_PostScriptsCallbacks() + { + bool scriptsCallbackCalled = false; + + IBuildParameters buildParameters = GetBuildParameters(k_FolderPath, k_TmpPath); + IBuildResults results = new BuildResults(); + BuildCallbacks callback = new BuildCallbacks(); + callback.PostScriptsCallbacks = (parameters, buildResults) => + { + scriptsCallbackCalled = true; + return ReturnCodes.Success; + }; + + ReturnCodes code = PostScriptsCallback.Run(buildParameters, results, callback); + Assert.AreEqual(ReturnCodes.Success, code); + Assert.IsTrue(scriptsCallbackCalled); + } + + IBundleBuildContent GetBundleContent() + { + List buildData = new List(); + AssetBundleBuild dataPoint1 = new AssetBundleBuild() + { + addressableNames = new string[] { }, + assetBundleName = "bundle", + assetBundleVariant = "", + assetNames = new string[] { k_CubePath } + }; + buildData.Add(dataPoint1); + IBundleBuildContent buildContent = new BundleBuildContent(buildData); + return buildContent; + } + + IDependencyData GetDependancyData() + { + GUID guid; + GUID.TryParse(AssetDatabase.AssetPathToGUID(k_CubePath), out guid); + ObjectIdentifier[] oId = ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(guid, EditorUserBuildSettings.activeBuildTarget); + AssetLoadInfo loadInfo = new AssetLoadInfo() + { + asset = guid, + address = k_CubePath, + includedObjects = oId.ToList(), + referencedObjects = oId.ToList() + }; + + IDependencyData dep = new BuildDependencyData(); + dep.AssetInfo.Add(guid, loadInfo); + + return dep; + } + + IBuildParameters GetBuildParameters(string folderPath, string tmpPath) + { + if (Directory.Exists(folderPath)) + Directory.Delete(folderPath, true); + if (Directory.Exists(tmpPath)) + Directory.Delete(tmpPath, true); + + if (!Directory.Exists(folderPath)) + Directory.CreateDirectory(folderPath); + + if (!Directory.Exists(tmpPath)) + Directory.CreateDirectory(tmpPath); + + IBuildParameters buildParams = new BuildParameters(EditorUserBuildSettings.activeBuildTarget, BuildTargetGroup.Unknown, folderPath); + buildParams.TempOutputFolder = tmpPath; + return buildParams; + } + + void CleanupFolders() + { + if (Directory.Exists(k_FolderPath)) + Directory.Delete(k_FolderPath, true); + if (Directory.Exists(k_TmpPath)) + Directory.Delete(k_TmpPath, true); + if (Directory.Exists(k_TestAssetsPath)) + Directory.Delete(k_TestAssetsPath, true); + if (File.Exists(k_TestAssetsPath + ".meta")) + File.Delete(k_TestAssetsPath + ".meta"); + } +} diff --git a/Tests/Editor/ScriptableBuildPipelineTests.cs.meta b/Tests/Editor/ScriptableBuildPipelineTests.cs.meta new file mode 100644 index 0000000..6356236 --- /dev/null +++ b/Tests/Editor/ScriptableBuildPipelineTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 170ac2c906650624cbab749adb2cc2ed +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package.json b/package.json index 83f6659..d2a62fa 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "com.unity.scriptablebuildpipeline", "displayName": "Scriptable Build Pipeline", - "version": "0.0.6-preview", + "version": "0.0.8-preview", "unity": "2018.2", "description": "The Scriptable Build Pipeline moves the asset bundle build pipeline to C#. Use the pre-defined build flows, or create your own using the divided up APIs. This system improves build time, fixes incremental build, and provides greater flexibility.", "keywords": ["build", "bundle", "bundles", "assetbundles"],