#pragma warning disable 0414, 0649 using UnityEditor; using UnityEngine; using System.Linq; using System; using System.Collections.Generic; using UniGLTF.MeshUtility; namespace VRM { public class MeshIntegratorWizard : ScriptableWizard { const string MENU_KEY = "Assets/UnityEditorScripts/MeshIntegratorWizard"; [SerializeField] GameObject m_root; [SerializeField] Material[] m_uniqueMaterials; [Serializable] struct MaterialKey { public string Shader; public KeyValuePair[] Properties; public override bool Equals(object obj) { if(!(obj is MaterialKey)) { return base.Equals(obj); } var key = (MaterialKey)obj; return Shader == key.Shader && Properties.SequenceEqual(key.Properties) ; } public override int GetHashCode() { return base.GetHashCode(); } } [Serializable] struct MaterialList { public Material[] Materials; public MaterialList(Material[] list) { Materials = list; } } [SerializeField] MaterialList[] m_duplicateMaterials; [Header("Result")] public MeshIntegrationResult[] integrationResults; [MenuItem(MENU_KEY)] static void CreateWizard() { ScriptableWizard.DisplayWizard("MeshIntegrator", "Integrate and close window", "Integrate"); } private void OnEnable() { m_root = Selection.activeGameObject; OnValidate(); } static object GetPropertyValue(Shader shader, int i, Material m) { var propType = ShaderUtil.GetPropertyType(shader, i); switch (propType) { case ShaderUtil.ShaderPropertyType.Color: return m.GetColor(ShaderUtil.GetPropertyName(shader, i)); case ShaderUtil.ShaderPropertyType.Range: case ShaderUtil.ShaderPropertyType.Float: return m.GetFloat(ShaderUtil.GetPropertyName(shader, i)); case ShaderUtil.ShaderPropertyType.Vector: return m.GetVector(ShaderUtil.GetPropertyName(shader, i)); case ShaderUtil.ShaderPropertyType.TexEnv: return m.GetTexture(ShaderUtil.GetPropertyName(shader, i)); default: throw new NotImplementedException(propType.ToString()); } } static MaterialKey GetMaterialKey(Material m) { var key = new MaterialKey { Shader = m.shader.name, }; key.Properties = Enumerable.Range(0, ShaderUtil.GetPropertyCount(m.shader)) .Select(x => new KeyValuePair( ShaderUtil.GetPropertyName(m.shader, x), GetPropertyValue(m.shader, x, m)) ) .OrderBy(x => x.Key) .ToArray() ; return key; } void OnValidate() { Debug.Log("OnValidate"); if (m_root == null) { m_uniqueMaterials = new Material[] { }; m_duplicateMaterials = new MaterialList[] { }; return; } m_uniqueMaterials = MeshIntegratorUtility.EnumerateSkinnedMeshRenderer(m_root.transform, false) .SelectMany(x => x.sharedMaterials) .Distinct() .ToArray(); m_duplicateMaterials = m_uniqueMaterials .GroupBy(x => GetMaterialKey(x), x => x) .Select(x => new MaterialList(x.ToArray())) .Where(x => x.Materials.Length > 1) .ToArray() ; } void OnWizardUpdate() { helpString = "select target mesh root"; } void Integrate() { if (m_root == null) { Debug.LogWarning("no root object"); return; } integrationResults = MeshIntegratorEditor.Integrate(m_root).ToArray(); } void OnWizardCreate() { Debug.Log("OnWizardCreate"); Integrate(); // close } void OnWizardOtherButton() { Debug.Log("OnWizardOtherButton"); Integrate(); } } }