using System; using System.Collections.Generic; using UnityEngine; namespace UnityEditor.Rendering { public partial class MaterialUpgrader { /// /// The priority of the upgrader. /// public virtual int priority => 0; /// /// Material Upgrader finalizer delegate. /// /// Material public delegate void MaterialFinalizer(Material mat); string m_OldShader; string m_NewShader; /// /// Retrieves path to new shader. /// public string NewShaderPath => m_NewShader; /// /// Retrieves path to old shader. /// public string OldShaderPath => m_OldShader; MaterialFinalizer m_Finalizer; Dictionary m_TextureRename = new Dictionary(); Dictionary m_FloatRename = new Dictionary(); Dictionary m_ColorRename = new Dictionary(); Dictionary m_FloatPropertiesToSet = new Dictionary(); Dictionary m_ColorPropertiesToSet = new Dictionary(); List m_TexturesToRemove = new List(); Dictionary m_TexturesToSet = new Dictionary(); class KeywordFloatRename { public string keyword; public string property; public float setVal, unsetVal; } List m_KeywordFloatRename = new List(); Dictionary)> m_ConditionalFloatRename; /// /// Type of property to rename. /// public enum MaterialPropertyType { /// Texture reference property. Texture, /// Float property. Float, /// Color property. Color } /// /// Retrieves a collection of renamed parameters of a specific MaterialPropertyType. /// /// Material Property Type /// Dictionary of property names to their renamed values. /// type is not valid. public IReadOnlyDictionary GetPropertyRenameMap(MaterialPropertyType type) { switch (type) { case MaterialPropertyType.Texture: return m_TextureRename; case MaterialPropertyType.Float: return m_FloatRename; case MaterialPropertyType.Color: return m_ColorRename; default: throw new ArgumentException(nameof(type)); } } /// /// Upgrade Flags /// [Flags] public enum UpgradeFlags { /// None. None = 0, /// LogErrorOnNonExistingProperty. LogErrorOnNonExistingProperty = 1, /// CleanupNonUpgradedProperties. CleanupNonUpgradedProperties = 2, /// LogMessageWhenNoUpgraderFound. LogMessageWhenNoUpgraderFound = 4 } /// /// Upgrade method. /// /// Material to upgrade. /// Upgrade flag public void Upgrade(Material material, UpgradeFlags flags) { Material newMaterial; if ((flags & UpgradeFlags.CleanupNonUpgradedProperties) != 0) { newMaterial = new Material(Shader.Find(m_NewShader)); } else { newMaterial = UnityEngine.Object.Instantiate(material) as Material; newMaterial.shader = Shader.Find(m_NewShader); } Convert(material, newMaterial); material.shader = Shader.Find(m_NewShader); material.CopyPropertiesFromMaterial(newMaterial); UnityEngine.Object.DestroyImmediate(newMaterial); if (m_Finalizer != null) m_Finalizer(material); } // Overridable function to implement custom material upgrading functionality /// /// Custom material conversion method. /// /// Source material. /// Destination material. public virtual void Convert(Material srcMaterial, Material dstMaterial) { foreach (var t in m_TextureRename) { if (!srcMaterial.HasProperty(t.Key) || !dstMaterial.HasProperty(t.Value)) continue; dstMaterial.SetTextureScale(t.Value, srcMaterial.GetTextureScale(t.Key)); dstMaterial.SetTextureOffset(t.Value, srcMaterial.GetTextureOffset(t.Key)); dstMaterial.SetTexture(t.Value, srcMaterial.GetTexture(t.Key)); } foreach (var t in m_FloatRename) { if (!srcMaterial.HasProperty(t.Key) || !dstMaterial.HasProperty(t.Value)) continue; dstMaterial.SetFloat(t.Value, srcMaterial.GetFloat(t.Key)); } foreach (var t in m_ColorRename) { if (!srcMaterial.HasProperty(t.Key) || !dstMaterial.HasProperty(t.Value)) continue; dstMaterial.SetColor(t.Value, srcMaterial.GetColor(t.Key)); } foreach (var prop in m_TexturesToRemove) { if (!dstMaterial.HasProperty(prop)) continue; dstMaterial.SetTexture(prop, null); } foreach (var prop in m_TexturesToSet) { if (!dstMaterial.HasProperty(prop.Key)) continue; dstMaterial.SetTexture(prop.Key, prop.Value); } foreach (var prop in m_FloatPropertiesToSet) { if (!dstMaterial.HasProperty(prop.Key)) continue; dstMaterial.SetFloat(prop.Key, prop.Value); } foreach (var prop in m_ColorPropertiesToSet) { if (!dstMaterial.HasProperty(prop.Key)) continue; dstMaterial.SetColor(prop.Key, prop.Value); } foreach (var t in m_KeywordFloatRename) { if (!dstMaterial.HasProperty(t.property)) continue; dstMaterial.SetFloat(t.property, srcMaterial.IsKeywordEnabled(t.keyword) ? t.setVal : t.unsetVal); } // Handle conditional float renaming if (m_ConditionalFloatRename != null) { foreach (var (oldName, (newName, condition)) in m_ConditionalFloatRename) { if (srcMaterial.HasProperty(oldName) && condition(srcMaterial.GetFloat(oldName)) && dstMaterial.HasProperty(newName)) { dstMaterial.SetFloat(newName, 1.0f); } } } } /// /// Rename shader. /// /// Old name. /// New name. /// Finalizer delegate. public void RenameShader(string oldName, string newName, MaterialFinalizer finalizer = null) { m_OldShader = oldName; m_NewShader = newName; m_Finalizer = finalizer; } /// /// Rename Texture Parameter. /// /// Old name. /// New name. public void RenameTexture(string oldName, string newName) { m_TextureRename[oldName] = newName; } /// /// Rename Float Parameter. /// /// Old name. /// New name. public void RenameFloat(string oldName, string newName) { m_FloatRename[oldName] = newName; } /// /// Rename Color Parameter. /// /// Old name. /// New name. public void RenameColor(string oldName, string newName) { m_ColorRename[oldName] = newName; } /// /// Remove Texture Parameter. /// /// Parameter name. public void RemoveTexture(string name) { m_TexturesToRemove.Add(name); } /// /// Set float property. /// /// Property name. /// Property value. public void SetFloat(string propertyName, float value) { m_FloatPropertiesToSet[propertyName] = value; } /// /// Set color property. /// /// Property name. /// Property value. public void SetColor(string propertyName, Color value) { m_ColorPropertiesToSet[propertyName] = value; } /// /// Set texture property. /// /// Property name. /// Property value. public void SetTexture(string propertyName, Texture value) { m_TexturesToSet[propertyName] = value; } /// /// Rename a keyword to float. /// /// Old name. /// New name. /// Value when set. /// Value when unset. public void RenameKeywordToFloat(string oldName, string newName, float setVal, float unsetVal) { m_KeywordFloatRename.Add(new KeywordFloatRename { keyword = oldName, property = newName, setVal = setVal, unsetVal = unsetVal }); } /// /// Rename a float property conditionally based on its value /// /// Old property name /// New property name /// Condition function that takes the float value and returns true if renaming should occur protected void RenameFloat(string oldName, string newName, System.Func condition) { (m_ConditionalFloatRename ??= new Dictionary)>())[oldName] = (newName, condition); } } }