using System.Collections; using System.Collections.Generic; using UnityEngine; using System; namespace UnityEditor.Experimental.ScriptableRenderLoop { public class MaterialUpgrader { string m_OldShader; string m_NewShader; Dictionary m_TextureRename = new Dictionary(); Dictionary m_FloatRename = new Dictionary(); Dictionary m_ColorRename = new Dictionary(); [Flags] public enum UpgradeFlags { None = 0, LogErrorOnNonExistingProperty = 1, CleanupNonUpgradedProperties = 2, } 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); } // Overridable function to implement custom material upgrading functionality public virtual void Convert(Material srcMaterial, Material dstMaterial) { foreach (var t in m_TextureRename) dstMaterial.SetTexture (t.Value, srcMaterial.GetTexture (t.Key)); foreach (var t in m_FloatRename) dstMaterial.SetFloat (t.Value, srcMaterial.GetFloat(t.Key)); foreach (var t in m_ColorRename) dstMaterial.SetColor (t.Value, srcMaterial.GetColor(t.Key)); } public void RenameShader(string oldName, string newName) { m_OldShader = oldName; m_NewShader = newName; } public void RenameTexture(string oldName, string newName) { m_TextureRename[oldName] = newName; } public void RenameFloat(string oldName, string newName) { m_FloatRename[oldName] = newName; } public void RenameColor(string oldName, string newName) { m_ColorRename[oldName] = newName; } static bool IsMaterialPath(string path) { return path.EndsWith (".mat", StringComparison.OrdinalIgnoreCase); } static MaterialUpgrader GetUpgrader(List upgraders, Material material) { if (material == null || material.shader == null) return null; string shaderName = material.shader.name; for (int i = 0;i != upgraders.Count;i++) { if (upgraders[i].m_OldShader == shaderName) return upgraders[i]; } return null; } //@TODO: Only do this when it exceeds memory consumption... static void SaveAssetsAndFreeMemory() { AssetDatabase.SaveAssets(); GC.Collect(); EditorUtility.UnloadUnusedAssetsImmediate(); AssetDatabase.Refresh(); } static public void UpgradeProjectFolder(List upgraders, string progressBarName) { int totalMaterialCount = 0; foreach ( string s in UnityEditor.AssetDatabase.GetAllAssetPaths() ) { if (IsMaterialPath(s)) totalMaterialCount++; } int materialIndex = 0; foreach ( string path in UnityEditor.AssetDatabase.GetAllAssetPaths() ) { if (IsMaterialPath(path)) { materialIndex++; if ( UnityEditor.EditorUtility.DisplayCancelableProgressBar(progressBarName, string.Format( "({0} of {1}) {2}", materialIndex, totalMaterialCount, path ), ( float )materialIndex / ( float )totalMaterialCount ) ) break; Material m = UnityEditor.AssetDatabase.LoadMainAssetAtPath( path ) as Material; Upgrade (m, upgraders, UpgradeFlags.None); SaveAssetsAndFreeMemory(); } } UnityEditor.EditorUtility.ClearProgressBar(); } public static void Upgrade(Material material, MaterialUpgrader upgrader, UpgradeFlags flags) { var upgraders = new List (); upgraders.Add (upgrader); Upgrade (material, upgraders, flags); } public static void Upgrade(Material material, List upgraders, UpgradeFlags flags) { var upgrader = GetUpgrader (upgraders, material); if (upgrader != null) upgrader.Upgrade (material, flags); } public static void UpgradeSelection(List upgraders, string progressBarName) { string lastMaterialName = ""; var selection = Selection.objects; for (int i = 0; i < selection.Length;i++) { if ( UnityEditor.EditorUtility.DisplayCancelableProgressBar(progressBarName, string.Format( "({0} of {1}) {2}", i, selection.Length, lastMaterialName ), ( float )i / ( float )selection.Length ) ) break; var material = selection[i] as Material; Upgrade (material, upgraders, UpgradeFlags.None); if (material != null) lastMaterialName = material.name; } UnityEditor.EditorUtility.ClearProgressBar(); } } }