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);
}
}
}