using System; using System.Collections.Generic; using System.Reflection; using UnityEditor.Build.Pipeline.Interfaces; using UnityEngine; namespace UnityEditor.Build.Pipeline.Utilities { /// /// Internal interface so switch platform build task can initialize editor build callbacks /// internal interface IEditorBuildCallbacks : IContextObject { /// /// Callbacks need to be Initialized after platform switch /// void InitializeCallbacks(); } /// /// Manages initialization and cleanup of Unity Editor IPreprocessShaders, IProcessScene, & IProcessSceneWithReport build callbacks. /// public class BuildInterfacesWrapper : IDisposable, IEditorBuildCallbacks { Type m_Type = null; bool m_Disposed = false; internal static Hash128 SceneCallbackVersionHash = new Hash128(); internal static Hash128 ShaderCallbackVersionHash = new Hash128(); /// /// Default constructor, initializes properties to defaults /// public BuildInterfacesWrapper() { m_Type = Type.GetType("UnityEditor.Build.BuildPipelineInterfaces, UnityEditor"); InitializeCallbacks(); } /// /// Public dispose function when instance is not in a using statement and manual dispose is required /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Disposes the build interfaces wrapper instance. /// /// Obsolete parameter. protected virtual void Dispose(bool disposing) { if (m_Disposed) return; CleanupCallbacks(); m_Disposed = true; } /// /// Initializes Unity Editor IPreprocessShaders, IPreprocessComputeShaders, IProcessScene, & IProcessSceneWithReport build callbacks. /// public void InitializeCallbacks() { var init = m_Type.GetMethod("InitializeBuildCallbacks", BindingFlags.NonPublic | BindingFlags.Static); #if UNITY_2020_2_OR_NEWER init.Invoke(null, new object[] { 274 }); // 274 = BuildCallbacks.SceneProcessors | BuildCallbacks.ShaderProcessors | BuildCallbacks.ComputeShader #else init.Invoke(null, new object[] { 18 }); // 18 = BuildCallbacks.SceneProcessors | BuildCallbacks.ShaderProcessors #endif #if UNITY_2019_4_OR_NEWER GatherCallbackVersions(); #endif } #if UNITY_2019_4_OR_NEWER internal void GatherCallbackVersions() { var versionedType = typeof(VersionedCallbackAttribute); var typeCollection = TypeCache.GetTypesWithAttribute(versionedType); List sceneInputs = new List(); List shaderInputs = new List(); foreach (var type in typeCollection) { var attribute = (VersionedCallbackAttribute)Attribute.GetCustomAttribute(type, versionedType); #if UNITY_2020_2_OR_NEWER if (typeof(IPreprocessShaders).IsAssignableFrom(type) || typeof(IPreprocessComputeShaders).IsAssignableFrom(type)) #else if (typeof(IPreprocessShaders).IsAssignableFrom(type)) #endif { shaderInputs.Add(HashingMethods.Calculate(type.AssemblyQualifiedName, attribute.version).ToHash128()); } #pragma warning disable CS0618 // Type or member is obsolete else if (typeof(IProcessScene).IsAssignableFrom(type) || typeof(IProcessSceneWithReport).IsAssignableFrom(type)) #pragma warning restore CS0618 // Type or member is obsolete { sceneInputs.Add(HashingMethods.Calculate(type.AssemblyQualifiedName, attribute.version).ToHash128()); } } SceneCallbackVersionHash = new Hash128(); if (sceneInputs.Count > 0) { sceneInputs.Sort(); SceneCallbackVersionHash = HashingMethods.Calculate(sceneInputs).ToHash128(); } ShaderCallbackVersionHash = new Hash128(); if (shaderInputs.Count > 0) { shaderInputs.Sort(); ShaderCallbackVersionHash = HashingMethods.Calculate(shaderInputs).ToHash128(); } } #endif /// /// Cleanup Unity Editor IPreprocessShaders, IProcessScene, & IProcessSceneWithReport build callbacks. /// public void CleanupCallbacks() { var clean = m_Type.GetMethod("CleanupBuildCallbacks", BindingFlags.NonPublic | BindingFlags.Static); clean.Invoke(null, null); } } }