// Copyright (c) Valve Corporation, All rights reserved. ====================================================================================================== #if (UNITY_EDITOR) using UnityEngine; using System; using System.Collections; using System.Collections.Generic; using UnityEditor.VersionControl; //--------------------------------------------------------------------------------------------------------------------------------------------------- public class ValveRefreshStandardShader { static void SaveAssetsAndFreeMemory() { UnityEditor.AssetDatabase.SaveAssets(); GC.Collect(); UnityEditor.EditorUtility.UnloadUnusedAssetsImmediate(); UnityEditor.AssetDatabase.Refresh(); } private static void RenameShadersInAllMaterials(string nameBefore, string nameAfter) { Shader destShader = Shader.Find(nameAfter); if (destShader == null) { return; } int i = 0; int nCount = 0; foreach (string s in UnityEditor.AssetDatabase.GetAllAssetPaths()) { if (s.EndsWith(".mat", StringComparison.OrdinalIgnoreCase)) { nCount++; } } foreach (string s in UnityEditor.AssetDatabase.GetAllAssetPaths()) { if (s.EndsWith(".mat", StringComparison.OrdinalIgnoreCase)) { i++; if (UnityEditor.EditorUtility.DisplayCancelableProgressBar("Valve Material Conversion", string.Format("({0} of {1}) {2}", i, nCount, s), (float)i / (float)nCount)) { break; } Material m = UnityEditor.AssetDatabase.LoadMainAssetAtPath(s) as Material; //Debug.Log( m.name + "\n" ); //Debug.Log( m.shader.name + "\n" ); if (m.shader.name.Equals(nameBefore)) { Debug.Log("Converting from \"" + nameBefore + "\"-->\"" + nameAfter + "\": " + m.name + "\n"); m.shader = destShader; SaveAssetsAndFreeMemory(); } } } //object[] obj = GameObject.FindObjectsOfType( typeof( GameObject ) ); //foreach ( object o in obj ) //{ // GameObject g = ( GameObject )o; // // Renderer[] renderers = g.GetComponents(); // foreach ( Renderer r in renderers ) // { // foreach ( Material m in r.sharedMaterials ) // { // //Debug.Log( m.name + "\n" ); // //Debug.Log( m.shader.name + "\n" ); // if ( m.shader.name.Equals( "Standard" ) ) // { // Debug.Log( "Refreshing Standard shader for material: " + m.name + "\n" ); // m.shader = destShader; // SaveAssetsAndFreeMemory(); // } // } // } //} UnityEditor.EditorUtility.ClearProgressBar(); } //--------------------------------------------------------------------------------------------------------------------------------------------------- public static bool StandardToValveSingleMaterial(Material m, Shader srcShader, Shader destShader, bool bRecordUnknownShaders, List unknownShaders) { string n = srcShader.name; if (n.Equals(destShader.name)) { // Do nothing //Debug.Log( " Skipping " + m.name + "\n" ); return false; } else if (n.Equals("Standard") || n.Equals("Valve/VR/Standard")) { // Metallic specular Debug.Log(" Converting from \"" + n + "\"-->\"" + destShader.name + "\": " + m.name + "\n"); m.shader = destShader; m.SetOverrideTag("OriginalShader", n); m.SetInt("_SpecularMode", 2); m.DisableKeyword("S_SPECULAR_NONE"); m.DisableKeyword("S_SPECULAR_BLINNPHONG"); m.EnableKeyword("S_SPECULAR_METALLIC"); return true; } else if (n.Equals("Standard (Specular setup)") || n.Equals("Legacy Shaders/Bumped Diffuse") || n.Equals("Legacy Shaders/Transparent/Diffuse")) { // Regular specular Debug.Log(" Converting from \"" + n + "\"-->\"" + destShader.name + "\": " + m.name + "\n"); m.shader = destShader; m.SetOverrideTag("OriginalShader", n); m.SetInt("_SpecularMode", 1); m.DisableKeyword("S_SPECULAR_NONE"); m.EnableKeyword("S_SPECULAR_BLINNPHONG"); m.DisableKeyword("S_SPECULAR_METALLIC"); if (n.Equals("Legacy Shaders/Transparent/Diffuse")) { m.SetFloat("_Mode", 2); m.SetOverrideTag("RenderType", "Transparent"); m.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); m.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); m.SetInt("_ZWrite", 0); m.DisableKeyword("_ALPHATEST_ON"); m.EnableKeyword("_ALPHABLEND_ON"); m.DisableKeyword("_ALPHAPREMULTIPLY_ON"); m.renderQueue = 3000; } return true; } else if (n.Equals("Unlit/Color") || n.Equals("Unlit/Texture") || n.Equals("Unlit/Transparent") || n.Equals("Unlit/Transparent Cutout")) { // Unlit Debug.Log(" Converting from \"" + n + "\"-->\"" + destShader.name + "\": " + m.name + "\n"); m.shader = destShader; m.SetOverrideTag("OriginalShader", n); m.SetInt("g_bUnlit", 1); m.EnableKeyword("S_UNLIT"); m.SetColor("_EmissionColor", Color.black); if (n.Equals("Unlit/Color")) { m.SetTexture("_MainTex", Texture2D.whiteTexture); } else { m.SetColor("_Color", Color.white); if (n.Equals("Unlit/Transparent Cutout")) { m.SetFloat("_Mode", 1); m.SetOverrideTag("RenderType", "TransparentCutout"); m.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); m.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); m.SetInt("_ZWrite", 1); m.EnableKeyword("_ALPHATEST_ON"); m.DisableKeyword("_ALPHABLEND_ON"); m.DisableKeyword("_ALPHAPREMULTIPLY_ON"); m.renderQueue = 2450; } else if (n.Equals("Unlit/Transparent")) { m.SetFloat("_Mode", 2); m.SetOverrideTag("RenderType", "Transparent"); m.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); m.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); m.SetInt("_ZWrite", 0); m.DisableKeyword("_ALPHATEST_ON"); m.EnableKeyword("_ALPHABLEND_ON"); m.DisableKeyword("_ALPHAPREMULTIPLY_ON"); m.renderQueue = 3000; } } return true; } else if (bRecordUnknownShaders) { // Don't know how to convert, so add to list to spew at the end Debug.LogWarning(" Don't know how to convert shader \"" + n + "\"" + " in material \"" + m.name + "\"" + "\n"); if (!unknownShaders.Contains(n)) { unknownShaders.Add(n); } return false; } return false; } //--------------------------------------------------------------------------------------------------------------------------------------------------- private static void StandardToValve(bool bConvertAllMaterials) { int nNumMaterialsConverted = 0; Debug.Log("Begin Convert to Valve Shaders\n\n" + Time.realtimeSinceStartup); Shader destShader = Shader.Find("Valve/vr_standard"); if (destShader == null) { Debug.LogWarning(" ERROR! Cannot find the \"Valve/vr_standard\" shader!" + "\n"); return; } List unknownShaders = new List(); List alreadyConvertedMaterials = new List(); if (bConvertAllMaterials) { int i = 0; int nCount = 0; foreach (string s in UnityEditor.AssetDatabase.GetAllAssetPaths()) { if (s.EndsWith(".mat", StringComparison.OrdinalIgnoreCase)) { nCount++; } } foreach (string s in UnityEditor.AssetDatabase.GetAllAssetPaths()) { if (s.EndsWith(".mat", StringComparison.OrdinalIgnoreCase)) { i++; if (UnityEditor.EditorUtility.DisplayCancelableProgressBar("Valve Material Conversion to Valve Shaders", string.Format("({0} of {1}) {2}", i, nCount, s), (float)i / (float)nCount)) { break; } Material m = UnityEditor.AssetDatabase.LoadMainAssetAtPath(s) as Material; if ((m == null) || (m.shader == null)) continue; if (!m.name.StartsWith("")) continue; if (alreadyConvertedMaterials.Contains(m.name)) continue; alreadyConvertedMaterials.Add(m.name); if (StandardToValveSingleMaterial(m, m.shader, destShader, true, unknownShaders)) { nNumMaterialsConverted++; } SaveAssetsAndFreeMemory(); } } } else { int i = 0; int nCount = 0; Renderer[] renderers = GameObject.FindObjectsOfType(); List countedMaterials = new List(); foreach (Renderer r in renderers) { if (r.sharedMaterials == null) continue; foreach (Material m in r.sharedMaterials) { if ((m == null) || (m.shader == null)) continue; if (!m.name.StartsWith("")) continue; if (countedMaterials.Contains(m.name)) continue; countedMaterials.Add(m.name); string assetPath = UnityEditor.AssetDatabase.GetAssetPath(m); Material mainAsset = UnityEditor.AssetDatabase.LoadMainAssetAtPath(assetPath) as Material; if (!mainAsset) { Debug.LogError("Error calling LoadMainAssetAtPath( " + assetPath + " )!\n\n"); continue; } nCount++; } } bool bCanceled = false; foreach (Renderer r in renderers) { if (r.sharedMaterials == null) continue; foreach (Material m in r.sharedMaterials) { if ((m == null) || (m.shader == null)) continue; if (!m.name.StartsWith("")) continue; if (alreadyConvertedMaterials.Contains(m.name)) continue; alreadyConvertedMaterials.Add(m.name); string assetPath = UnityEditor.AssetDatabase.GetAssetPath(m); Material mainAsset = UnityEditor.AssetDatabase.LoadMainAssetAtPath(assetPath) as Material; if (!mainAsset) { Debug.LogError("Error calling LoadMainAssetAtPath( " + assetPath + " )!\n\n"); continue; } i++; if (UnityEditor.EditorUtility.DisplayCancelableProgressBar("Valve Material Conversion to Valve Shaders", string.Format("({0} of {1}) {2}", i, nCount, assetPath), (float)i / (float)nCount)) { bCanceled = true; break; } if (StandardToValveSingleMaterial(mainAsset, mainAsset.shader, destShader, true, unknownShaders)) { nNumMaterialsConverted++; } SaveAssetsAndFreeMemory(); } if (bCanceled) break; } } foreach (string s in unknownShaders) { Debug.LogWarning(" Don't know how to convert shader \"" + s + "\"" + "\n"); } Debug.Log("Converted " + nNumMaterialsConverted + " materials to Valve Shaders\n\n" + Time.realtimeSinceStartup); UnityEditor.EditorUtility.ClearProgressBar(); } [UnityEditor.MenuItem("Valve/Shader Dev/Convert Active Materials to Valve Shaders", false, 50)] private static void StandardToValveCurrent() { StandardToValve(false); } [UnityEditor.MenuItem("Valve/Shader Dev/Convert All Materials to Valve Shaders", false, 100)] private static void StandardToValveAll() { StandardToValve(true); } //--------------------------------------------------------------------------------------------------------------------------------------------------- private static bool ValveToStandardSingleMaterial(Material m, Shader destShaderStandard, Shader destShaderStandardSpecular) { if (m.shader.name.Equals("Valve/vr_standard")) { if ((m.GetTag("OriginalShader", true) != null) && (m.GetTag("OriginalShader", true).Length > 0)) { Debug.Log(" Converting from \"" + m.shader.name + "\"-->\"" + m.GetTag("OriginalShader", true) + "\": " + m.name + "\n"); m.shader = Shader.Find(m.GetTag("OriginalShader", true)); return true; } else if (m.GetInt("_SpecularMode") == 2) { // Metallic specular Debug.Log(" Converting from \"" + m.shader.name + "\"-->\"" + destShaderStandard.name + "\": " + m.name + "\n"); m.shader = destShaderStandard; return true; } else { // Regular specular Debug.Log(" Converting from \"" + m.shader.name + "\"-->\"" + destShaderStandardSpecular.name + "\": " + m.name + "\n"); m.shader = destShaderStandardSpecular; return true; } } return false; } //--------------------------------------------------------------------------------------------------------------------------------------------------- [UnityEditor.MenuItem("Valve/Shader Dev/Convert All Materials Back to Unity Shaders", false, 101)] private static void ValveToStandard(bool bConvertAllMaterials) { int nNumMaterialsConverted = 0; Debug.Log("Begin Convert to Unity Shaders\n\n" + Time.realtimeSinceStartup); Shader destShaderStandard = Shader.Find("Standard"); if (destShaderStandard == null) { Debug.LogWarning(" ERROR! Cannot find the \"Standard\" shader!" + "\n"); return; } Shader destShaderStandardSpecular = Shader.Find("Standard (Specular setup)"); if (destShaderStandardSpecular == null) { Debug.LogWarning(" ERROR! Cannot find the \"Standard (Specular setup)\" shader!" + "\n"); return; } List alreadyConvertedMaterials = new List(); if (bConvertAllMaterials) { int i = 0; int nCount = 0; foreach (string s in UnityEditor.AssetDatabase.GetAllAssetPaths()) { if (s.EndsWith(".mat", StringComparison.OrdinalIgnoreCase)) { nCount++; } } foreach (string s in UnityEditor.AssetDatabase.GetAllAssetPaths()) { if (s.EndsWith(".mat", StringComparison.OrdinalIgnoreCase)) { i++; if (UnityEditor.EditorUtility.DisplayCancelableProgressBar("Valve Material Conversion Back to Unity Shaders", string.Format("({0} of {1}) {2}", i, nCount, s), (float)i / (float)nCount)) { break; } Material m = UnityEditor.AssetDatabase.LoadMainAssetAtPath(s) as Material; if (ValveToStandardSingleMaterial(m, destShaderStandard, destShaderStandardSpecular)) { nNumMaterialsConverted++; } SaveAssetsAndFreeMemory(); } } } else { int i = 0; int nCount = 0; Renderer[] renderers = GameObject.FindObjectsOfType(); List countedMaterials = new List(); foreach (Renderer r in renderers) { if (r.sharedMaterials == null) continue; foreach (Material m in r.sharedMaterials) { if ((m == null) || (m.shader == null)) continue; if (!m.name.StartsWith("")) continue; if (countedMaterials.Contains(m.name)) continue; countedMaterials.Add(m.name); string assetPath = UnityEditor.AssetDatabase.GetAssetPath(m); Material mainAsset = UnityEditor.AssetDatabase.LoadMainAssetAtPath(assetPath) as Material; if (!mainAsset) { Debug.LogError("Error calling LoadMainAssetAtPath( " + assetPath + " )!\n\n"); continue; } nCount++; } } bool bCanceled = false; foreach (Renderer r in renderers) { if (r.sharedMaterials == null) continue; foreach (Material m in r.sharedMaterials) { if ((m == null) || (m.shader == null)) continue; if (!m.name.StartsWith("")) continue; if (alreadyConvertedMaterials.Contains(m.name)) continue; alreadyConvertedMaterials.Add(m.name); string assetPath = UnityEditor.AssetDatabase.GetAssetPath(m); Material mainAsset = UnityEditor.AssetDatabase.LoadMainAssetAtPath(assetPath) as Material; if (!mainAsset) { Debug.LogError("Error calling LoadMainAssetAtPath( " + assetPath + " )!\n\n"); continue; } i++; if (UnityEditor.EditorUtility.DisplayCancelableProgressBar("Valve Material Conversion Back to Unity Shaders", string.Format("({0} of {1}) {2}", i, nCount, assetPath), (float)i / (float)nCount)) { bCanceled = true; break; } if (ValveToStandardSingleMaterial(mainAsset, destShaderStandard, destShaderStandardSpecular)) { nNumMaterialsConverted++; } SaveAssetsAndFreeMemory(); } if (bCanceled) break; } } Debug.Log("Converted " + nNumMaterialsConverted + " materials to Unity Shaders\n\n" + Time.realtimeSinceStartup); UnityEditor.EditorUtility.ClearProgressBar(); } [UnityEditor.MenuItem("Valve/Shader Dev/Convert Active Materials Back to Unity Shaders", false, 51)] private static void ValveToStandardCurrent() { ValveToStandard(false); } [UnityEditor.MenuItem("Valve/Shader Dev/Convert All Materials Back to Unity Shaders", false, 101)] private static void ValveToStandardAll() { ValveToStandard(true); } //--------------------------------------------------------------------------------------------------------------------------------------------------- //[UnityEditor.MenuItem( "Valve/Shader Dev/Refresh Standard", false, 150 )] //private static void RefreshStandard() //{ // RenameShadersInAllMaterials( "Standard", "Standard" ); //} //--------------------------------------------------------------------------------------------------------------------------------------------------- [UnityEditor.MenuItem("Valve/Shader Dev/Ensure Consistency in Valve Materials", false, 200)] private static void EnsureConsistencyInValveMaterials() { int nNumMaterialChanges = 0; Debug.Log("Begin consistency check for all Valve materials\n\n" + Time.realtimeSinceStartup); int i = 0; int nCount = 0; foreach (string s in UnityEditor.AssetDatabase.GetAllAssetPaths()) { if (s.EndsWith(".mat", StringComparison.OrdinalIgnoreCase)) { nCount++; } } foreach (string s in UnityEditor.AssetDatabase.GetAllAssetPaths()) { if (s.EndsWith(".mat", StringComparison.OrdinalIgnoreCase)) { i++; if (UnityEditor.EditorUtility.DisplayCancelableProgressBar("Consistency check for all Valve materials", string.Format("({0} of {1}) {2}", i, nCount, s), (float)i / (float)nCount)) { break; } Material m = UnityEditor.AssetDatabase.LoadMainAssetAtPath(s) as Material; if (m.shader.name.Equals("Valve/vr_standard")) { // Convert old metallic bool to new specular mode if ((m.HasProperty("g_bEnableMetallic") && m.GetInt("g_bEnableMetallic") == 1) || (m.IsKeywordEnabled("_METALLIC_ENABLED"))) { Debug.Log(" Converting old metallic checkbox to specular mode on material \"" + m.name + "\"\n"); m.DisableKeyword("_METALLIC_ENABLED"); m.SetInt("g_bEnableMetallic", 0); m.SetInt("_SpecularMode", 2); m.EnableKeyword("S_SPECULAR_METALLIC"); nNumMaterialChanges++; } else if (!m.IsKeywordEnabled("S_SPECULAR_NONE") && !m.IsKeywordEnabled("S_SPECULAR_BLINNPHONG") && !m.IsKeywordEnabled("S_SPECULAR_METALLIC")) { Debug.Log(" Converting old specular to BlinnPhong specular mode on material \"" + m.name + "\"\n"); m.SetInt("_SpecularMode", 1); m.EnableKeyword("S_SPECULAR_BLINNPHONG"); nNumMaterialChanges++; } // If occlusion map is set, enable S_OCCLUSION static combo if (m.GetTexture("_OcclusionMap") && !m.IsKeywordEnabled("S_OCCLUSION")) { Debug.Log(" Enabling new occlusion combo S_OCCLUSION on material \"" + m.name + "\"\n"); m.EnableKeyword("S_OCCLUSION"); nNumMaterialChanges++; } SaveAssetsAndFreeMemory(); } } } Debug.Log("Consistency check made " + nNumMaterialChanges + " changes to Valve materials\n\n" + Time.realtimeSinceStartup); UnityEditor.EditorUtility.ClearProgressBar(); } } #endif