This repository has been archived on 2026-01-20. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
AW_2025/Assets/MeshBaker/Examples/Scripts/MB_MigrateMaterialsToDifferentPipeline.cs
2025-03-06 10:29:25 +09:00

358 lines
16 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
using DigitalOpus.MB.Core;
/// <summary>
/// This script should be added to each example scene for 2017+
/// It is hard to add because it destroys itself and is configured to [ExecuteInEditMode]
///
/// You need to set the MB_ALLOW_ADD_MIGRATE_MAT_SCRIPT in order to add this script and save the scene.
///
/// </summary>
[ExecuteInEditMode]
public class MB_MigrateMaterialsToDifferentPipeline : MonoBehaviour
{
#if UNITY_EDITOR
void Start(){
#if UNITY_2018_4_OR_NEWER
MBVersion.PipelineType pipelineType = MBVersion.DetectPipeline();
int materialPipeline = GetMaterialPipelineType();
// Do not prompt if example materials cannot be found, are using an unsupported shader, or are already suitable for the current pipeline
if (materialPipeline != -1 && pipelineType != (MBVersion.PipelineType)materialPipeline)
{
if(pipelineType != MBVersion.PipelineType.Unsupported)
{
bool convert = EditorUtility.DisplayDialog(
"Different Pipline Detected",
"Would you like to try converting the default Mesh Baker example scene materials to suit the " + pipelineType + " pipeline?",
"Yes",
"No");
if (convert){
MigrateMaterials();
if(pipelineType == MBVersion.PipelineType.HDRP)
{
Debug.LogWarning("If the Mesh Baker Example Scenes appear dark, try adding an Empty GameObject to the scene, adding a 'Volume' component to it, and assigning that volume one of the default profiles.");
}
}
}
else
{
Debug.LogWarning("Mesh Baker's example scenes only support the Default Pipeline, URP, and HDRP.");
}
}
#endif
#if !MB_ALLOW_ADD_MIGRATE_MAT_SCRIPT
// Add the MB_ALLOW_ADD_MIGRATE_MAT_SCRIPT to script defines to add this to scenes.
DestroyImmediate(this.gameObject);
#endif
}
public string[][] shaderMap_Unsupported_Default_URP_HDRP = new string[][]
{
new string[] { "", "Legacy Shaders/Self-Illumin/Bumped Diffuse", "Universal Render Pipeline/Lit", "HDRP/Lit"},
new string[] { "", "Legacy Shaders/Transparent/VertexLit", "Universal Render Pipeline/Lit", "HDRP/Lit"},
new string[] { "", "Legacy Shaders/Lightmapped/Specular", "Universal Render Pipeline/Lit", "HDRP/Lit"},
new string[] { "", "Legacy Shaders/Diffuse", "Universal Render Pipeline/Lit", "HDRP/Lit"},
new string[] { "", "Legacy Shaders/Bumped Specular", "Universal Render Pipeline/Lit", "HDRP/Lit"},
new string[] { "", "Mobile/Diffuse", "Universal Render Pipeline/Lit", "HDRP/Lit"},
new string[] { "", "Universal Render Pipeline/Lit", "Universal Render Pipeline/Lit", "HDRP/Lit"},
new string[] { "", "Standard", "Universal Render Pipeline/Lit", "HDRP/Lit"},
new string[] { "", "Nature/Tree Creator Leaves Fast", "Universal Render Pipeline/Nature/SpeedTree8", "HDRP/Lit"},
new string[] { "", "Legacy Shaders/Bumped Diffuse", "Universal Render Pipeline/Lit", "HDRP/Lit"},
new string[] { "", "Legacy Shaders/Reflective/Diffuse", "Universal Render Pipeline/Lit", "HDRP/Lit"},
new string[] { "", "Legacy Shaders/Specular", "Universal Render Pipeline/Lit", "HDRP/Lit"},
new string[] { "", "MeshBaker/Examples/UnlitTextureArray", "Universal Render Pipeline/Lit", "HDRP/Lit"}
};
string[][] propNameMap_Unsupported_Default_URP_HDRP = new string[][]
{
new string[]{ "_Color", "_Color", "_BaseColor", "_BaseColor"}, // (Color)
new string[]{ "_MainTex", "_MainTex", "_BaseMap", "_BaseColorMap"}, // (Texture)
new string[]{ "_Albedo", "_Albedo", "_BaseMap", "_BaseColorMap" }, // (Texture)
new string[]{ "_BumpMap", "_BumpMap", "_BumpMap", "_NormalMap"}, // (Texture)
new string[]{ "_Illum", "_Illum" , "_EmissionMap", "_EmissiveColorMap"}, // (Texture)
new string[]{ "_LightMap", "_LightMap" , "", ""} // No mapping, not going to assign lightmap to the new shader
};
[ContextMenu("Create Unity Package For All Mats In Examples")]
void CreatePackageForExampleMaterials()
{
// Check if examples folder is "Assets/MeshBaker/Examples"
// Get all materials in examples.
string unityPackageFilename;
string examplesPathRelative = GetRelativeExamplesPath();
if(examplesPathRelative == null) {
Debug.LogError("Cannot package example materials as no Mesh Baker Example scenes were found. Renaming example scenes may cause this error.");
return;
}
MBVersion.PipelineType pipelineType = MBVersion.DetectPipeline();
if (pipelineType == MBVersion.PipelineType.Default)
{
unityPackageFilename = examplesPathRelative + "/Examples_Default.unitypackage";
} else if (pipelineType == MBVersion.PipelineType.HDRP)
{
unityPackageFilename = examplesPathRelative + "/Examples_HDRP.unitypackage";
} else if (pipelineType == MBVersion.PipelineType.URP)
{
unityPackageFilename = examplesPathRelative + "/Examples_URP.unitypackage";
} else
{
Debug.LogError("Unknown pipeline type.");
return;
}
string[] matGIDs = AssetDatabase.FindAssets("t:Material", new string[] { examplesPathRelative });
string[] assetPathNames = new string[matGIDs.Length];
List<string> assetPathNamesList = new List<string>();
for (int i = 0; i < matGIDs.Length; i++)
{
string path = AssetDatabase.GUIDToAssetPath(matGIDs[i]);
if (!path.Contains("SceneBasicTextureArrayAssets") && !path.EndsWith(".fbx")) // don't do texture array assets.
{
assetPathNamesList.Add(path);
// Debug.Log(path);
}
}
assetPathNames = assetPathNamesList.ToArray();
Debug.Log("Found " + assetPathNames.Length + " materials in " + examplesPathRelative);
AssetDatabase.ExportPackage(assetPathNames, unityPackageFilename);
Debug.Log("Create Unity Package: " + unityPackageFilename);
}
[ContextMenu("Migrate Materials In Examples Folder")]
void MigrateMaterials()
{
HashSet<string> shaderNames = new HashSet<string>();
string examplesPathRelative = GetRelativeExamplesPath();
if(examplesPathRelative == null) {
Debug.LogError("Cannot convert example materials as no Mesh Baker Example scenes were found. Renaming example scenes may cause this error.");
return;
}
Debug.Log("Found Mesh Baker Examples at: " + examplesPathRelative);
MBVersion.PipelineType pipelineType = MBVersion.DetectPipeline();
Material[] mats;
{
string[] matGIDs = AssetDatabase.FindAssets("t:Material", new string[] { examplesPathRelative });
List<Material> matList = new List<Material>();
for (int i = 0; i < matGIDs.Length; i++)
{
string path = AssetDatabase.GUIDToAssetPath(matGIDs[i]);
if (!path.Contains("SceneBasicTextureArrayAssets") && !path.EndsWith(".fbx")) // don't do texture array assets.
{
Material m = AssetDatabase.LoadAssetAtPath<Material>(path);
string shaderName = m.shader.name;
if (MapDefault2OtherShader(shaderName, pipelineType) == null)
{
Debug.LogError("Could not find mapping for shader " + shaderName + " in mat " + path);
continue;
}
matList.Add(m);
shaderNames.Add(shaderName);
}
}
mats = matList.ToArray();
}
string nn = "";
foreach (string n in shaderNames)
{
if (MapDefault2OtherShader(n, pipelineType) == null)
{
Debug.LogError("Could not find mapping for shader " + n);
return;
}
nn += "'"+n+"' will map to '" + MapDefault2OtherShader(n, pipelineType) + "',\n";
}
Debug.Log(examplesPathRelative + " Found Mats: " + mats.Length + " Shaders Found " + nn);
for (int i = 0; i < mats.Length; i++)
{
Material m = mats[i];
RemapTextures_Default2OtherPipeline(m, pipelineType);
EditorUtility.SetDirty(m);
}
AssetDatabase.SaveAssets();
}
string MapDefault2OtherShader(string defaultName, MBVersion.PipelineType pipelineType)
{
// pipelineType
// Unsupported = 0
// Default = 1
// URP = 2
// HDRP = 3
for (int i = 0; i < shaderMap_Unsupported_Default_URP_HDRP.Length; i++)
{
if (defaultName == shaderMap_Unsupported_Default_URP_HDRP[i][(int)MBVersion.PipelineType.Default])
{
return shaderMap_Unsupported_Default_URP_HDRP[i][(int)pipelineType];
}
}
return null;
}
[ContextMenu("Find Examples Filepath")]
string GetRelativeExamplesPath(){
// One of the example scenes, it should always be found directly in the root Examples directory
string exampleScene = "BatchPrepareObjectsForDynamicBatching";
string[] targetGID = AssetDatabase.FindAssets(exampleScene + " t:SceneAsset");
if (targetGID.Length != 1) {
Debug.LogWarning("Could not find Mesh Baker Example Scenes");
return null;
}
string relativeAssetPath = AssetDatabase.GUIDToAssetPath(targetGID[0]);
// Parent directory should therefore give us a relative path to Examples, even if it is not in the default MeshBaker/Examples location
relativeAssetPath = relativeAssetPath.Substring(0, relativeAssetPath.Length - ("/".Length + exampleScene.Length + ".unity".Length));
relativeAssetPath = relativeAssetPath.Replace('\\', '/');
relativeAssetPath = relativeAssetPath.Replace("//", "/");
string examplesPath = relativeAssetPath;
// Debug.Log("Found Mesh Baker Examples at " + path);
return examplesPath;
}
// Use a known material inside the examples to find out what pipeline the examples materials are set to
// Returns as an int to handle the case of the examples directory missing or being altered, otherwise result can be cast to PipelineType
int GetMaterialPipelineType(){
string relativePath = GetRelativeExamplesPath();
if(relativePath == null){
return -1;
}
string pathToTestMat = relativePath + "/Assets/Materials/firstFloorPlatform.mat";
Material targetMat = AssetDatabase.LoadAssetAtPath<Material>(pathToTestMat);
if(targetMat == null){
Debug.LogWarning("Cannot get example material pipeline type. Contents of Mesh Baker Examples directory have changed.");
return -1;
}
string shaderName = targetMat.shader.name;
if(shaderName == "Legacy Shaders/Self-Illumin/Bumped Diffuse"){
return 1;
}
if(shaderName == "Universal Render Pipeline/Lit"){
return 2;
}
if(shaderName == "HDRP/Lit"){
return 3;
}
return 0;
}
[ContextMenu("Test Transparency")]
Material HandleHDRPTreeTransparency(Material m)
{
// Surface Type
// 0 = Opaque
// 1 = Transparent
m.SetFloat("_SurfaceType", 1.0f);
// Preserve Specular Lighting Checkbox
// 0 = Unchecked
// 1 = Checked
m.SetFloat("_EnableBlendModePreserveSpecularLighting", 0.0f);
return m;
}
void RemapTextures_Default2OtherPipeline(Material m, MBVersion.PipelineType pipelineType)
{
#if !UNITY_2018_4_OR_NEWER
Debug.LogError("Must use Unity 2018.4 or greater");
return;
#else
if(m.shader == null) {
Debug.LogError("Null shader found in material " + m + ", skipping");
return;
}
string oldShaderName = m.shader.name;
string newShaderName = MapDefault2OtherShader(m.shader.name, pipelineType);
if(newShaderName == null) {
Debug.LogError("Could not find mapping for shader " + newShaderName + " in " + AssetDatabase.GetAssetPath(m) + ", skipping");
return;
}
Dictionary<string, string> propMap = new Dictionary<string, string>();
for (int i = 0; i < propNameMap_Unsupported_Default_URP_HDRP.Length; i++)
{
// pipelineType
// Unsupported = 0
// Default = 1
// URP = 2
// HDRP = 3
propMap[propNameMap_Unsupported_Default_URP_HDRP[i][(int)MBVersion.PipelineType.Default]] = propNameMap_Unsupported_Default_URP_HDRP[i][(int)pipelineType];
}
Dictionary<string, Texture> texMap = new Dictionary<string, Texture>();
Dictionary<string, Color> colorMap = new Dictionary<string, Color>();
for (int i = 0; i < propNameMap_Unsupported_Default_URP_HDRP.Length; i++)
{
string p = propNameMap_Unsupported_Default_URP_HDRP[i][(int)MBVersion.PipelineType.Default];
if(m.HasProperty(p))
{
// So far the only property that we map of type (Color) is the main color, if this changes we might want to make a colorPropertyMap up top
if(p == "_Color")
{
Color c = m.GetColor(p);
if (m.HasProperty(p))
{
Debug.Assert(propMap.ContainsKey(p), "No mapping for " + p + " mat " + m + " " + m.shader);
//Debug.Log("Will Map " + p + " to " + colorMap[p]);
colorMap[propMap[p]] = c;
}
}
else
{
Texture t = m.GetTexture(p);
if (t != null)
{
Debug.Assert(propMap.ContainsKey(p), "No mapping for " + p + " mat " + m + " " + m.shader);
//Debug.Log("Will Map " + p + " to " + propMap[p]);
texMap[propMap[p]] = t;
}
}
}
}
m.shader = Shader.Find(newShaderName);
// Can be removed when HDRP adds a nice tree shader
if(pipelineType == MBVersion.PipelineType.HDRP && oldShaderName == "Nature/Tree Creator Leaves Fast")
{
m = HandleHDRPTreeTransparency(m);
}
foreach (string p in texMap.Keys)
{
// Debug.Log("Mat " + m + " setting prop " + p + " to " + texMap[p]);
m.SetTexture(p, texMap[p]);
}
foreach (string p in colorMap.Keys)
{
// Debug.Log("Mat " + m + " setting prop " + p + " to " + colorMap[p]);
m.SetColor(p, colorMap[p]);
}
#endif
}
#endif
}