diff --git a/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/GltfExportSettings.cs b/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/GltfExportSettings.cs index 54101e083..de514d0ce 100644 --- a/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/GltfExportSettings.cs +++ b/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/GltfExportSettings.cs @@ -16,5 +16,12 @@ namespace UniGLTF public bool DropNormal; public bool DivideVertexBuffer; + + public MeshExportSettings MeshExportSettings => new MeshExportSettings + { + UseSparseAccessorForMorphTarget = Sparse, + ExportOnlyBlendShapePosition = DropNormal, + DivideVertexBuffer = DivideVertexBuffer, + }; } } diff --git a/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/GltfExportWindow.cs b/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/GltfExportWindow.cs index ec5955c40..7da38e10a 100644 --- a/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/GltfExportWindow.cs +++ b/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/GltfExportWindow.cs @@ -32,11 +32,17 @@ namespace UniGLTF GltfExportSettings m_settings; Editor m_settingsInspector; + MeshExportValidator m_meshes; + Editor m_meshesInspector; + protected override void Initialize() { m_settings = ScriptableObject.CreateInstance(); m_settings.InverseAxis = UniGLTFPreference.GltfIOAxis; m_settingsInspector = Editor.CreateEditor(m_settings); + + m_meshes = ScriptableObject.CreateInstance(); + m_meshesInspector = Editor.CreateEditor(m_meshes); } protected override void Clear() @@ -44,6 +50,12 @@ namespace UniGLTF // m_settingsInspector UnityEditor.Editor.DestroyImmediate(m_settingsInspector); m_settingsInspector = null; + // m_meshesInspector + UnityEditor.Editor.DestroyImmediate(m_meshesInspector); + m_meshesInspector = null; + // m_settings + ScriptableObject.DestroyImmediate(m_settings); + m_settings = null; } protected override IEnumerable ValidatorFactory() @@ -54,7 +66,16 @@ namespace UniGLTF { yield break; } + + // Mesh/Renderer のチェック + yield return m_meshes.Validate; } + + protected override void OnLayout() + { + m_meshes.SetRoot(State.ExportRoot, m_settings.MeshExportSettings); + } + protected override bool DoGUI(bool isValid) { if (!isValid) @@ -67,6 +88,7 @@ namespace UniGLTF switch (_tab) { case Tabs.Mesh: + m_meshesInspector.OnInspectorGUI(); break; case Tabs.ExportSettings: @@ -131,7 +153,6 @@ namespace UniGLTF AssetDatabase.ImportAsset(path.ToUnityRelativePath()); AssetDatabase.Refresh(); } - } } } diff --git a/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/MeshExportValidator.cs b/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/MeshExportValidator.cs index 0dc1a9f49..becf276b1 100644 --- a/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/MeshExportValidator.cs +++ b/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/MeshExportValidator.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; +using UniGLTF.M17N; using UnityEngine; namespace UniGLTF @@ -30,10 +31,6 @@ namespace UniGLTF public int ExpectedExportByteSize => Meshes.Where(x => x.IsRendererActive).Sum(x => x.ExportByteSize); - List m_validations = new List(); - - public IEnumerable Validations => m_validations; - public MeshExportSettings Settings; public virtual bool UseBlendShape(int index, string relativePath) => true; @@ -164,7 +161,6 @@ namespace UniGLTF public void SetRoot(GameObject ExportRoot, MeshExportSettings settings) { Settings = settings; - m_validations.Clear(); Meshes.Clear(); if (ExportRoot == null) { @@ -179,5 +175,65 @@ namespace UniGLTF } } } + + public Func GltfMaterialFromUnityShaderName = DefaultGltfMaterialType; + + public static string DefaultGltfMaterialType(string shaderName) + { + if (shaderName == "Standard") + { + return "pbr"; + } + if (MaterialExporter.IsUnlit(shaderName)) + { + return "unlit"; + } + return null; + } + + public enum Messages + { + DIFFERENT_MATERIAL_COUNT, + MATERIALS_CONTAINS_NULL, + UNKNOWN_SHADER, + } + + public IEnumerable Validate(GameObject ExportRoot) + { + foreach (var info in Meshes) + { + // invalid materials.len + if (info.Renderer.sharedMaterials.Length < info.Mesh.subMeshCount) + { + // すべての submesh に material が割り当てられていない + yield return Validation.Error(Messages.DIFFERENT_MATERIAL_COUNT.Msg()); + } + else if (info.Renderer.sharedMaterials.Length > info.Mesh.subMeshCount) + { + // 未使用の material がある + yield return Validation.Warning(Messages.DIFFERENT_MATERIAL_COUNT.Msg()); + } + else if (info.Renderer.sharedMaterials.Any(x => x == null)) + { + // material に null が含まれる(unity で magenta になっているはず) + yield return Validation.Error($"{info.Renderer}: {Messages.MATERIALS_CONTAINS_NULL.Msg()}"); + } + } + + foreach (var m in Meshes.SelectMany(x => x.Renderer.sharedMaterials).Distinct()) + { + if (m == null) + { + continue; + } + var gltfMaterial = GltfMaterialFromUnityShaderName(m.shader.name); + if (string.IsNullOrEmpty(gltfMaterial)) + { + yield return Validation.Warning($"{m}: unknown shader: {m.shader.name} => export as gltf default"); + } + } + + yield break; + } } } diff --git a/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/MeshExportValidatorEditor.cs b/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/MeshExportValidatorEditor.cs index c112a7f6b..70edf409c 100644 --- a/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/MeshExportValidatorEditor.cs +++ b/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/MeshExportValidatorEditor.cs @@ -17,6 +17,8 @@ namespace UniGLTF public override void OnInspectorGUI() { + EditorGUILayout.HelpBox($"Mesh size: {m_target.ExpectedExportByteSize / 1000000.0f:0.0} MByte", MessageType.Info); + for (int i = 0; i < m_target.Meshes.Count; ++i) { DrawElement(i, m_target.Meshes[i]); diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialExporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialExporter.cs index 20a5ea7b9..b0fc0a210 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialExporter.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialExporter.cs @@ -196,6 +196,22 @@ namespace UniGLTF } } + public static bool IsUnlit(string shaderName) + { + switch (shaderName) + { + case "Unlit/Color": + case "Unlit/Texture": + case "Unlit/Transparent": + case "Unlit/Transparent Cutout": + case "UniGLTF/UniUnlit": + return true; + + default: + return false; + } + } + protected virtual glTFMaterial CreateMaterial(Material m) { switch (m.shader.name) diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/gltfExporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/gltfExporter.cs index 3c0abf80e..4174e7ae2 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/gltfExporter.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/gltfExporter.cs @@ -216,7 +216,7 @@ namespace UniGLTF public virtual void ExportExtensions(Func getTextureBytes) { - + // do nothing } public virtual void Export(MeshExportSettings meshExportSettings, Func useAsset, Func getTextureBytes) diff --git a/Assets/VRM/Editor/Format/VRMExporterWizard.cs b/Assets/VRM/Editor/Format/VRMExporterWizard.cs index 18e10f3b5..768191a32 100644 --- a/Assets/VRM/Editor/Format/VRMExporterWizard.cs +++ b/Assets/VRM/Editor/Format/VRMExporterWizard.cs @@ -35,7 +35,7 @@ namespace VRM Editor m_settingsInspector; - VRMExportMeshes m_meshes; + VRMMeshExportValidator m_meshes; Editor m_meshesInspector; @@ -68,7 +68,7 @@ namespace VRM m_settings = ScriptableObject.CreateInstance(); m_settingsInspector = Editor.CreateEditor(m_settings); - m_meshes = ScriptableObject.CreateInstance(); + m_meshes = ScriptableObject.CreateInstance(); m_meshesInspector = Editor.CreateEditor(m_meshes); State.ExportRootChanged += (root) => @@ -101,41 +101,63 @@ namespace VRM protected override void Clear() { - // m_metaEditor - UnityEditor.Editor.DestroyImmediate(m_metaEditor); - m_metaEditor = null; // m_settingsInspector UnityEditor.Editor.DestroyImmediate(m_settingsInspector); m_settingsInspector = null; // m_meshesInspector UnityEditor.Editor.DestroyImmediate(m_meshesInspector); m_meshesInspector = null; + // m_settings + ScriptableObject.DestroyImmediate(m_settings); + m_settings = null; + + // m_metaEditor + UnityEditor.Editor.DestroyImmediate(m_metaEditor); + m_metaEditor = null; // Meta Meta = null; ScriptableObject.DestroyImmediate(m_tmpMeta); m_tmpMeta = null; - // m_settings - ScriptableObject.DestroyImmediate(m_settings); - m_settings = null; // m_meshes ScriptableObject.DestroyImmediate(m_meshes); m_meshes = null; } + static string GltfMaterialFromUnityShaderName(string shaderName) + { + var name = VRMMaterialExporter.VrmMaterialName(shaderName); + if (!string.IsNullOrEmpty(name)) + { + return name; + } + return MeshExportValidator.DefaultGltfMaterialType(shaderName); + } + protected override IEnumerable ValidatorFactory() { - HumanoidValidator.MeshInformations = m_meshes.Meshes; - HumanoidValidator.EnableFreeze = m_settings.PoseFreeze; - VRMExporterValidator.ReduceBlendshape = m_settings.ReduceBlendshape; - + // ヒエラルキー のチェック yield return HierarchyValidator.Validate; if (!State.ExportRoot) { + // Root が無い yield break; } + // Mesh/Renderer のチェック + m_meshes.GltfMaterialFromUnityShaderName = GltfMaterialFromUnityShaderName; + yield return m_meshes.Validate; + + // Humanoid のチェック + HumanoidValidator.MeshInformations = m_meshes.Meshes; + HumanoidValidator.EnableFreeze = m_settings.PoseFreeze; yield return HumanoidValidator.Validate; + + // + // VRM のチェック + // + VRMExporterValidator.ReduceBlendshape = m_settings.ReduceBlendshape; yield return VRMExporterValidator.Validate; + yield return VRMSpringBoneValidator.Validate; var firstPerson = State.ExportRoot.GetComponent(); @@ -156,10 +178,11 @@ namespace VRM protected override void OnLayout() { - // m_settings, m_meshes.Meshes m_meshes.SetRoot(State.ExportRoot, m_settings); } + static bool s_foldT = true; + protected override bool DoGUI(bool isValid) { if (State.ExportRoot == null) @@ -174,42 +197,46 @@ namespace VRM { var backup = GUI.enabled; GUI.enabled = State.ExportRoot.scene.IsValid(); - if (GUI.enabled) - { - EditorGUILayout.HelpBox(EnableTPose.ENALBE_TPOSE_BUTTON.Msg(), MessageType.Info); - } - else - { - EditorGUILayout.HelpBox(EnableTPose.DISABLE_TPOSE_BUTTON.Msg(), MessageType.Warning); - } - // - // T-Pose - // - if (GUILayout.Button(VRMExportSettingsEditor.Options.DO_TPOSE.Msg())) + if (s_foldT = EditorGUILayout.Foldout(s_foldT, "T-Pose")) { - if (State.ExportRoot != null) + if (GUI.enabled) { - // fallback - Undo.RecordObjects(State.ExportRoot.GetComponentsInChildren(), "tpose"); - VRMBoneNormalizer.EnforceTPose(State.ExportRoot); - Repaint(); + EditorGUILayout.HelpBox(EnableTPose.ENALBE_TPOSE_BUTTON.Msg(), MessageType.Info); } - } - - if (GUILayout.Button(VRMExportSettingsEditor.Options.DO_TPOSE.Msg() + "(unity internal)")) - { - if (State.ExportRoot != null) + else { - Undo.RecordObjects(State.ExportRoot.GetComponentsInChildren(), "tpose.internal"); - if (InternalTPose.TryMakePoseValid(State.ExportRoot)) + EditorGUILayout.HelpBox(EnableTPose.DISABLE_TPOSE_BUTTON.Msg(), MessageType.Warning); + } + + // + // T-Pose + // + if (GUILayout.Button(VRMExportSettingsEditor.Options.DO_TPOSE.Msg())) + { + if (State.ExportRoot != null) { - // done + // fallback + Undo.RecordObjects(State.ExportRoot.GetComponentsInChildren(), "tpose"); + VRMBoneNormalizer.EnforceTPose(State.ExportRoot); Repaint(); } - else + } + + if (GUILayout.Button(VRMExportSettingsEditor.Options.DO_TPOSE.Msg() + "(unity internal)")) + { + if (State.ExportRoot != null) { - Debug.LogWarning("not found"); + Undo.RecordObjects(State.ExportRoot.GetComponentsInChildren(), "tpose.internal"); + if (InternalTPose.TryMakePoseValid(State.ExportRoot)) + { + // done + Repaint(); + } + else + { + Debug.LogWarning("not found"); + } } } } @@ -222,9 +249,6 @@ namespace VRM return false; } - EditorGUILayout.HelpBox($"Mesh size: {m_meshes.ExpectedExportByteSize / 1000000.0f:0.0} MByte", MessageType.Info); - - // // GUI // diff --git a/Assets/VRM/Editor/Format/VRMExportMeshes.cs b/Assets/VRM/Editor/Format/VRMMeshExportValidaotr.cs similarity index 96% rename from Assets/VRM/Editor/Format/VRMExportMeshes.cs rename to Assets/VRM/Editor/Format/VRMMeshExportValidaotr.cs index 595161014..9797057a9 100644 --- a/Assets/VRM/Editor/Format/VRMExportMeshes.cs +++ b/Assets/VRM/Editor/Format/VRMMeshExportValidaotr.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using UniGLTF; using UnityEngine; @@ -14,7 +12,7 @@ namespace VRM /// Meshのエクスポートサイズを試算する。 /// [Serializable] - public class VRMExportMeshes : MeshExportValidator + public class VRMMeshExportValidator : MeshExportValidator { static bool ClipsContainsName(IReadOnlyList clips, bool onlyPreset, BlendShapeBinding binding) { diff --git a/Assets/VRM/Editor/Format/VRMExportMeshes.cs.meta b/Assets/VRM/Editor/Format/VRMMeshExportValidaotr.cs.meta similarity index 83% rename from Assets/VRM/Editor/Format/VRMExportMeshes.cs.meta rename to Assets/VRM/Editor/Format/VRMMeshExportValidaotr.cs.meta index d045660f1..827e80db5 100644 --- a/Assets/VRM/Editor/Format/VRMExportMeshes.cs.meta +++ b/Assets/VRM/Editor/Format/VRMMeshExportValidaotr.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 7961eaa3060a80d43b2bcd80961bbd29 +guid: 18a610aab46d5034cb787ab237e3dea2 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/VRM/Editor/Format/VRMExportMeshesEditor.cs b/Assets/VRM/Editor/Format/VRMMeshExportValidatorEditor.cs similarity index 72% rename from Assets/VRM/Editor/Format/VRMExportMeshesEditor.cs rename to Assets/VRM/Editor/Format/VRMMeshExportValidatorEditor.cs index 9c7f0b676..c96a9711a 100644 --- a/Assets/VRM/Editor/Format/VRMExportMeshesEditor.cs +++ b/Assets/VRM/Editor/Format/VRMMeshExportValidatorEditor.cs @@ -3,7 +3,7 @@ using UnityEditor; namespace VRM { - [CustomEditor(typeof(VRMExportMeshes))] + [CustomEditor(typeof(VRMMeshExportValidator))] public class VRMExportMeshesEditor : MeshExportValidatorEditor { } diff --git a/Assets/VRM/Editor/Format/VRMExportMeshesEditor.cs.meta b/Assets/VRM/Editor/Format/VRMMeshExportValidatorEditor.cs.meta similarity index 83% rename from Assets/VRM/Editor/Format/VRMExportMeshesEditor.cs.meta rename to Assets/VRM/Editor/Format/VRMMeshExportValidatorEditor.cs.meta index bf6e8d24c..7fa901c84 100644 --- a/Assets/VRM/Editor/Format/VRMExportMeshesEditor.cs.meta +++ b/Assets/VRM/Editor/Format/VRMMeshExportValidatorEditor.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 64237fa04d62bfa48a479f54155467c6 +guid: e590565ae8d8e5f45956a20e207d3272 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/VRM/Runtime/IO/VRMMaterialExporter.cs b/Assets/VRM/Runtime/IO/VRMMaterialExporter.cs index 22c3ab11b..e484d256a 100644 --- a/Assets/VRM/Runtime/IO/VRMMaterialExporter.cs +++ b/Assets/VRM/Runtime/IO/VRMMaterialExporter.cs @@ -10,6 +10,24 @@ namespace VRM { public class VRMMaterialExporter : MaterialExporter { + public static string VrmMaterialName(string shaderName) + { + switch (shaderName) + { + case "VRM/UnlitTexture": + case "VRM/UnlitTransparent": + case "VRM/UnlitCutout": + case "VRM/UnlitTransparentZWrite": + return "KHR_materials_unlit"; + + case "VRM/MToon": + return "MToon"; + + default: + return null; + } + } + protected override glTFMaterial CreateMaterial(Material m) { switch (m.shader.name) diff --git a/Assets/VRM10/Editor/Vrm10ExportDialog.cs b/Assets/VRM10/Editor/Vrm10ExportDialog.cs index 7772a7486..2270d2b61 100644 --- a/Assets/VRM10/Editor/Vrm10ExportDialog.cs +++ b/Assets/VRM10/Editor/Vrm10ExportDialog.cs @@ -167,7 +167,7 @@ namespace UniVRM10 protected override void OnLayout() { // m_settings, m_meshes.Meshes - m_meshes.SetRoot(State.ExportRoot, default); + m_meshes.SetRoot(State.ExportRoot, m_settings.MeshExportSettings); } protected override bool DoGUI(bool isValid) diff --git a/Assets/VRM10/Runtime/Components/Expression/MaterialValueBindingMerger.cs b/Assets/VRM10/Runtime/Components/Expression/MaterialValueBindingMerger.cs index ad0384996..91be2fb2b 100644 --- a/Assets/VRM10/Runtime/Components/Expression/MaterialValueBindingMerger.cs +++ b/Assets/VRM10/Runtime/Components/Expression/MaterialValueBindingMerger.cs @@ -57,7 +57,7 @@ namespace UniVRM10 { foreach (var material in renderer.sharedMaterials) { - if (!materialNameMap.ContainsKey(material.name)) + if (material != null && !materialNameMap.ContainsKey(material.name)) { materialNameMap.Add(material.name, material); } diff --git a/Assets/VRM10/Runtime/Components/Expression/MorphTargetBindingMerger.cs b/Assets/VRM10/Runtime/Components/Expression/MorphTargetBindingMerger.cs index 33a4ed166..0606f7fc5 100644 --- a/Assets/VRM10/Runtime/Components/Expression/MorphTargetBindingMerger.cs +++ b/Assets/VRM10/Runtime/Components/Expression/MorphTargetBindingMerger.cs @@ -64,7 +64,7 @@ namespace UniVRM10 } else { - Debug.LogWarningFormat("Invalid morphTarget binding: {0}: {1}", target.name, binding); + Debug.LogWarningFormat("Invalid morphTarget binding: {0}: {1}", target.name, binding.Index); } }