MaterialPostprocessor.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEditor.Rendering.Universal.ShaderGUI;
  5. using UnityEngine;
  6. using UnityEngine.Rendering.Universal;
  7. namespace UnityEditor.Rendering.Universal
  8. {
  9. class MaterialModificationProcessor : AssetModificationProcessor
  10. {
  11. static void OnWillCreateAsset(string asset)
  12. {
  13. if (!asset.ToLowerInvariant().EndsWith(".mat"))
  14. {
  15. return;
  16. }
  17. MaterialPostprocessor.s_CreatedAssets.Add(asset);
  18. }
  19. }
  20. class MaterialReimporter : Editor
  21. {
  22. static bool s_NeedToCheckProjSettingExistence = true;
  23. static void ReimportAllMaterials()
  24. {
  25. string[] guids = AssetDatabase.FindAssets("t:material", null);
  26. // There can be several materials subAssets per guid ( ie : FBX files ), remove duplicate guids.
  27. var distinctGuids = guids.Distinct();
  28. int materialIdx = 0;
  29. int totalMaterials = distinctGuids.Count();
  30. foreach (var asset in distinctGuids)
  31. {
  32. materialIdx++;
  33. var path = AssetDatabase.GUIDToAssetPath(asset);
  34. EditorUtility.DisplayProgressBar("Material Upgrader re-import", string.Format("({0} of {1}) {2}", materialIdx, totalMaterials, path), (float)materialIdx / (float)totalMaterials);
  35. AssetDatabase.ImportAsset(path);
  36. }
  37. EditorUtility.ClearProgressBar();
  38. MaterialPostprocessor.s_NeedsSavingAssets = true;
  39. }
  40. [InitializeOnLoadMethod]
  41. static void RegisterUpgraderReimport()
  42. {
  43. EditorApplication.update += () =>
  44. {
  45. if (Time.renderedFrameCount > 0)
  46. {
  47. bool fileExist = true;
  48. // We check the file existence only once to avoid IO operations every frame.
  49. if (s_NeedToCheckProjSettingExistence)
  50. {
  51. fileExist = System.IO.File.Exists(UniversalProjectSettings.filePath);
  52. s_NeedToCheckProjSettingExistence = false;
  53. }
  54. //This method is called at opening and when URP package change (update of manifest.json)
  55. var curUpgradeVersion = UniversalProjectSettings.materialVersionForUpgrade;
  56. if (curUpgradeVersion != MaterialPostprocessor.k_Upgraders.Length)
  57. {
  58. string commandLineOptions = Environment.CommandLine;
  59. bool inTestSuite = commandLineOptions.Contains("-testResults");
  60. if (!inTestSuite && fileExist)
  61. {
  62. EditorUtility.DisplayDialog("URP Material upgrade", "The Materials in your Project were created using an older version of the Universal Render Pipeline (URP)." +
  63. " Unity must upgrade them to be compatible with your current version of URP. \n" +
  64. " Unity will re-import all of the Materials in your project, save the upgraded Materials to disk, and check them out in source control if needed.\n" +
  65. " Please see the Material upgrade guide in the URP documentation for more information.", "Ok");
  66. }
  67. ReimportAllMaterials();
  68. }
  69. if (MaterialPostprocessor.s_NeedsSavingAssets)
  70. MaterialPostprocessor.SaveAssetsToDisk();
  71. }
  72. };
  73. }
  74. }
  75. class MaterialPostprocessor : AssetPostprocessor
  76. {
  77. public static List<string> s_CreatedAssets = new List<string>();
  78. internal static List<string> s_ImportedAssetThatNeedSaving = new List<string>();
  79. internal static bool s_NeedsSavingAssets = false;
  80. internal static readonly Action<Material, ShaderPathID>[] k_Upgraders = { UpgradeV1 };
  81. static internal void SaveAssetsToDisk()
  82. {
  83. string commandLineOptions = System.Environment.CommandLine;
  84. bool inTestSuite = commandLineOptions.Contains("-testResults");
  85. if (inTestSuite)
  86. return;
  87. foreach (var asset in s_ImportedAssetThatNeedSaving)
  88. {
  89. AssetDatabase.MakeEditable(asset);
  90. }
  91. AssetDatabase.SaveAssets();
  92. //to prevent data loss, only update the saved version if user applied change and assets are written to
  93. UniversalProjectSettings.materialVersionForUpgrade = k_Upgraders.Length;
  94. s_ImportedAssetThatNeedSaving.Clear();
  95. s_NeedsSavingAssets = false;
  96. }
  97. static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
  98. {
  99. var upgradeLog = "UniversalRP Material log:";
  100. var upgradeCount = 0;
  101. foreach (var asset in importedAssets)
  102. {
  103. if (!asset.ToLowerInvariant().EndsWith(".mat"))
  104. continue;
  105. var material = (Material)AssetDatabase.LoadAssetAtPath(asset, typeof(Material));
  106. if (!ShaderUtils.IsLWShader(material.shader))
  107. continue;
  108. ShaderPathID id = ShaderUtils.GetEnumFromPath(material.shader.name);
  109. var wasUpgraded = false;
  110. var assetVersions = AssetDatabase.LoadAllAssetsAtPath(asset);
  111. AssetVersion assetVersion = null;
  112. foreach (var subAsset in assetVersions)
  113. {
  114. if(subAsset.GetType() == typeof(AssetVersion))
  115. assetVersion = subAsset as AssetVersion;
  116. }
  117. var debug = "\n" + material.name;
  118. if (!assetVersion)
  119. {
  120. wasUpgraded = true;
  121. assetVersion = ScriptableObject.CreateInstance<AssetVersion>();
  122. if (s_CreatedAssets.Contains(asset))
  123. {
  124. assetVersion.version = k_Upgraders.Length;
  125. s_CreatedAssets.Remove(asset);
  126. InitializeLatest(material, id);
  127. }
  128. else
  129. {
  130. assetVersion.version = 0;
  131. }
  132. assetVersion.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector | HideFlags.NotEditable;
  133. AssetDatabase.AddObjectToAsset(assetVersion, asset);
  134. debug += " initialized.";
  135. }
  136. while (assetVersion.version < k_Upgraders.Length)
  137. {
  138. k_Upgraders[assetVersion.version](material, id);
  139. debug += $" upgrading:v{assetVersion.version} to v{assetVersion.version + 1}";
  140. assetVersion.version++;
  141. wasUpgraded = true;
  142. }
  143. if (wasUpgraded)
  144. {
  145. upgradeLog += debug;
  146. upgradeCount++;
  147. EditorUtility.SetDirty(assetVersion);
  148. s_ImportedAssetThatNeedSaving.Add(asset);
  149. s_NeedsSavingAssets = true;
  150. }
  151. }
  152. }
  153. static void InitializeLatest(Material material, ShaderPathID id)
  154. {
  155. }
  156. static void UpgradeV1(Material material, ShaderPathID shaderID)
  157. {
  158. var shaderPath = ShaderUtils.GetShaderPath(shaderID);
  159. var upgradeFlag = MaterialUpgrader.UpgradeFlags.LogMessageWhenNoUpgraderFound;
  160. switch (shaderID)
  161. {
  162. case ShaderPathID.Unlit:
  163. MaterialUpgrader.Upgrade(material, new UnlitUpdaterV1(shaderPath), upgradeFlag);
  164. UnlitShader.SetMaterialKeywords(material);
  165. break;
  166. case ShaderPathID.SimpleLit:
  167. MaterialUpgrader.Upgrade(material, new SimpleLitUpdaterV1(shaderPath), upgradeFlag);
  168. SimpleLitShader.SetMaterialKeywords(material, SimpleLitGUI.SetMaterialKeywords);
  169. break;
  170. case ShaderPathID.Lit:
  171. MaterialUpgrader.Upgrade(material, new LitUpdaterV1(shaderPath), upgradeFlag);
  172. LitShader.SetMaterialKeywords(material, LitGUI.SetMaterialKeywords);
  173. break;
  174. case ShaderPathID.ParticlesLit:
  175. MaterialUpgrader.Upgrade(material, new ParticleUpdaterV1(shaderPath), upgradeFlag);
  176. ParticlesLitShader.SetMaterialKeywords(material, LitGUI.SetMaterialKeywords, ParticleGUI.SetMaterialKeywords);
  177. break;
  178. case ShaderPathID.ParticlesSimpleLit:
  179. MaterialUpgrader.Upgrade(material, new ParticleUpdaterV1(shaderPath), upgradeFlag);
  180. ParticlesSimpleLitShader.SetMaterialKeywords(material, SimpleLitGUI.SetMaterialKeywords, ParticleGUI.SetMaterialKeywords);
  181. break;
  182. case ShaderPathID.ParticlesUnlit:
  183. MaterialUpgrader.Upgrade(material, new ParticleUpdaterV1(shaderPath), upgradeFlag);
  184. ParticlesUnlitShader.SetMaterialKeywords(material, null, ParticleGUI.SetMaterialKeywords);
  185. break;
  186. }
  187. }
  188. }
  189. // Upgraders v1
  190. #region UpgradersV1
  191. internal class LitUpdaterV1 : MaterialUpgrader
  192. {
  193. public static void UpdateLitDetails(Material material)
  194. {
  195. if (material == null)
  196. throw new ArgumentNullException("material");
  197. if(material.GetTexture("_MetallicGlossMap") || material.GetTexture("_SpecGlossMap") || material.GetFloat("_SmoothnessTextureChannel") >= 0.5f)
  198. material.SetFloat("_Smoothness", material.GetFloat("_GlossMapScale"));
  199. else
  200. material.SetFloat("_Smoothness", material.GetFloat("_Glossiness"));
  201. }
  202. public LitUpdaterV1(string oldShaderName)
  203. {
  204. if (oldShaderName == null)
  205. throw new ArgumentNullException("oldShaderName");
  206. string standardShaderPath = ShaderUtils.GetShaderPath(ShaderPathID.Lit);
  207. RenameShader(oldShaderName, standardShaderPath, UpdateLitDetails);
  208. RenameTexture("_MainTex", "_BaseMap");
  209. RenameColor("_Color", "_BaseColor");
  210. RenameFloat("_GlossyReflections", "_EnvironmentReflections");
  211. }
  212. }
  213. internal class UnlitUpdaterV1 : MaterialUpgrader
  214. {
  215. static Shader bakedLit = Shader.Find(ShaderUtils.GetShaderPath(ShaderPathID.BakedLit));
  216. public static void UpgradeToUnlit(Material material)
  217. {
  218. if (material == null)
  219. throw new ArgumentNullException("material");
  220. if (material.GetFloat("_SampleGI") != 0)
  221. {
  222. material.shader = bakedLit;
  223. material.EnableKeyword("_NORMALMAP");
  224. }
  225. }
  226. public UnlitUpdaterV1(string oldShaderName)
  227. {
  228. if (oldShaderName == null)
  229. throw new ArgumentNullException("oldShaderName");
  230. RenameShader(oldShaderName, ShaderUtils.GetShaderPath(ShaderPathID.Unlit), UpgradeToUnlit);
  231. RenameTexture("_MainTex", "_BaseMap");
  232. RenameColor("_Color", "_BaseColor");
  233. }
  234. }
  235. internal class SimpleLitUpdaterV1 : MaterialUpgrader
  236. {
  237. public SimpleLitUpdaterV1(string oldShaderName)
  238. {
  239. if (oldShaderName == null)
  240. throw new ArgumentNullException("oldShaderName");
  241. RenameShader(oldShaderName, ShaderUtils.GetShaderPath(ShaderPathID.SimpleLit), UpgradeToSimpleLit);
  242. RenameTexture("_MainTex", "_BaseMap");
  243. RenameColor("_Color", "_BaseColor");
  244. RenameFloat("_SpecSource", "_SpecularHighlights");
  245. RenameFloat("_Shininess", "_Smoothness");
  246. }
  247. public static void UpgradeToSimpleLit(Material material)
  248. {
  249. if (material == null)
  250. throw new ArgumentNullException("material");
  251. var smoothnessSource = 1 - (int)material.GetFloat("_GlossinessSource");
  252. material.SetFloat("_SmoothnessSource" ,smoothnessSource);
  253. if (material.GetTexture("_SpecGlossMap") == null)
  254. {
  255. var col = material.GetColor("_SpecColor");
  256. var colBase = material.GetColor("_Color");
  257. var smoothness = material.GetFloat("_Shininess");
  258. if (material.GetFloat("_Surface") == 0)
  259. {
  260. if (smoothnessSource == 1)
  261. colBase.a = smoothness;
  262. else
  263. col.a = smoothness;
  264. material.SetColor("_BaseColor", colBase);
  265. }
  266. material.SetColor("_BaseColor", colBase);
  267. material.SetColor("_SpecColor", col);
  268. }
  269. }
  270. }
  271. internal class ParticleUpdaterV1 : MaterialUpgrader
  272. {
  273. public ParticleUpdaterV1(string shaderName)
  274. {
  275. if (shaderName == null)
  276. throw new ArgumentNullException("oldShaderName");
  277. RenameShader(shaderName, shaderName, ParticleUpgrader.UpdateSurfaceBlendModes);
  278. RenameTexture("_MainTex", "_BaseMap");
  279. RenameColor("_Color", "_BaseColor");
  280. RenameFloat("_FlipbookMode", "_FlipbookBlending");
  281. switch (ShaderUtils.GetEnumFromPath(shaderName))
  282. {
  283. case ShaderPathID.ParticlesLit:
  284. RenameFloat("_Glossiness", "_Smoothness");
  285. break;
  286. case ShaderPathID.ParticlesSimpleLit:
  287. RenameFloat("_Glossiness", "_Smoothness");
  288. break;
  289. case ShaderPathID.ParticlesUnlit:
  290. break;
  291. }
  292. }
  293. }
  294. #endregion
  295. }