diff --git a/Assets/VRM/UniGLTF/Scripts/IO/MeshExporter.cs b/Assets/VRM/UniGLTF/Scripts/IO/MeshExporter.cs index 35dd674d56..de44ec80a3 100644 --- a/Assets/VRM/UniGLTF/Scripts/IO/MeshExporter.cs +++ b/Assets/VRM/UniGLTF/Scripts/IO/MeshExporter.cs @@ -22,6 +22,16 @@ public struct MeshExportInfo public bool IsRendererActive; public bool Skinned; + public bool HasNormal => Mesh != null && Mesh.normals != null && Mesh.normals.Length == Mesh.vertexCount; + public bool HasUV => Mesh != null && Mesh.uv != null && Mesh.uv.Length == Mesh.vertexCount; + + public bool HasVertexColor => Mesh.colors != null && Mesh.colors.Length == Mesh.vertexCount + && VertexColor == VertexColorState.ExistsAndIsUsed + || VertexColor == VertexColorState.ExistsAndMixed // Export する + ; + + public bool HasSkinning => Mesh.boneWeights != null && Mesh.boneWeights.Length == Mesh.vertexCount; + /// /// Mesh に頂点カラーが含まれているか。 /// 含まれている場合にマテリアルは Unlit.VColorMultiply になっているか? diff --git a/Assets/VRM/UniVRM/Editor/Format/VRMExportMeshes.cs b/Assets/VRM/UniVRM/Editor/Format/VRMExportMeshes.cs index ed4b451629..00a4dc74ad 100644 --- a/Assets/VRM/UniVRM/Editor/Format/VRMExportMeshes.cs +++ b/Assets/VRM/UniVRM/Editor/Format/VRMExportMeshes.cs @@ -79,25 +79,22 @@ public static void CalcMeshSize(ref UniGLTF.MeshExportInfo info, // float4 x 3 // vertices sb.Append($"(Pos"); - if (info.Mesh.normals != null && info.Mesh.normals.Length == info.Mesh.vertexCount) + if (info.HasNormal) { sb.Append("+Nom"); info.ExportVertexSize += 4 * 3; } - if (info.Mesh.uv != null && info.Mesh.uv.Length == info.Mesh.vertexCount) + if (info.HasUV) { sb.Append("+UV"); info.ExportVertexSize += 4 * 2; } - if (info.Mesh.colors != null && info.Mesh.colors.Length == info.Mesh.vertexCount - && info.VertexColor == UniGLTF.MeshExportInfo.VertexColorState.ExistsAndIsUsed - || info.VertexColor == UniGLTF.MeshExportInfo.VertexColorState.ExistsAndMixed // Export する - ) + if (info.HasVertexColor) { sb.Append("+Col"); info.ExportVertexSize += 4 * 4; } - if (info.Mesh.boneWeights != null && info.Mesh.boneWeights.Length == info.Mesh.vertexCount) + if (info.HasSkinning) { // short, float x 4 weights sb.Append("+Skin"); @@ -143,6 +140,12 @@ public static void CalcMeshSize(ref UniGLTF.MeshExportInfo info, sb.Insert(0, "[remove vcolor]"); break; } + if (info.ExportBlendShapeCount > 0 && !info.HasSkinning) + { + sb.Insert(0, "[morph without skin]"); + } + + // total bytes sb.Insert(0, $"{info.ExportByteSize:#,0} Bytes = "); info.Summary = sb.ToString(); } diff --git a/Assets/VRM/UniVRM/Editor/Format/VRMExporterVaildator.cs b/Assets/VRM/UniVRM/Editor/Format/VRMExporterVaildator.cs index 2461d566d4..14d3c81311 100644 --- a/Assets/VRM/UniVRM/Editor/Format/VRMExporterVaildator.cs +++ b/Assets/VRM/UniVRM/Editor/Format/VRMExporterVaildator.cs @@ -84,7 +84,7 @@ static string Msg(VRMExporterWizardMessages key) /// /// /// - public bool RootAndHumanoidCheck(GameObject ExportRoot, VRMExportSettings m_settings) + public bool RootAndHumanoidCheck(GameObject ExportRoot, VRMExportSettings m_settings, IReadOnlyList info) { // // root @@ -107,25 +107,31 @@ public bool RootAndHumanoidCheck(GameObject ExportRoot, VRMExportSettings m_sett return false; } - if (HasRotationOrScale(ExportRoot)) + if (HasRotationOrScale(ExportRoot) || info.Any(x => x.ExportBlendShapeCount > 0 && !x.HasSkinning)) { + // 正規化必用 if (m_settings.PoseFreeze) { - EditorGUILayout.HelpBox("Root OK", MessageType.Info); + // する + EditorGUILayout.HelpBox("PoseFreeze checked. OK", MessageType.Info); } else { + // しない Validation.Warning(Msg(VRMExporterWizardMessages.ROTATION_OR_SCALEING_INCLUDED_IN_NODE)).DrawGUI(); } } else { + // 不要 if (m_settings.PoseFreeze) { + // する Validation.Warning(Msg(VRMExporterWizardMessages.IS_POSE_FREEZE_DONE)).DrawGUI(); } else { + // しない EditorGUILayout.HelpBox("Root OK", MessageType.Info); } } diff --git a/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizard.cs b/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizard.cs index 1bec989214..3b4984eac7 100644 --- a/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizard.cs +++ b/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizard.cs @@ -78,8 +78,14 @@ void UpdateRoot(GameObject root) } else { + // do validation + Validate(); + // default setting - m_settings.PoseFreeze = VRMExporterValidator.HasRotationOrScale(ExportRoot); + m_settings.PoseFreeze = + VRMExporterValidator.HasRotationOrScale(ExportRoot) + || m_meshes.Meshes.Any(x => x.ExportBlendShapeCount > 0 && !x.HasSkinning) + ; var meta = ExportRoot.GetComponent(); if (meta != null) @@ -93,6 +99,17 @@ void UpdateRoot(GameObject root) } } + void Validate() + { + if (!m_requireValidation) + { + return; + } + m_validator.Validate(ExportRoot, m_settings, Meta != null ? Meta : m_tmpMeta); + m_requireValidation = false; + m_meshes.SetRoot(ExportRoot, m_settings); + } + VRMMetaObject m_tmpMeta; Editor m_metaEditor; @@ -202,18 +219,13 @@ private void OnGUI() // EventType.Layout と EventType.Repaint 間で内容が変わらないようしている。 if (Event.current.type == EventType.Layout) { - if (m_requireValidation) - { - m_validator.Validate(ExportRoot, m_settings, Meta != null ? Meta : m_tmpMeta); - m_requireValidation = false; - m_meshes.SetRoot(ExportRoot, m_settings); - } + Validate(); } // // Humanoid として適正か? ここで失敗する場合は Export UI を表示しない // - if (!m_validator.RootAndHumanoidCheck(ExportRoot, m_settings)) + if (!m_validator.RootAndHumanoidCheck(ExportRoot, m_settings, m_meshes.Meshes)) { return; } diff --git a/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizardMessages.cs b/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizardMessages.cs index 9cc63ecf02..e9e521f55b 100644 --- a/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizardMessages.cs +++ b/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizardMessages.cs @@ -21,8 +21,8 @@ public enum VRMExporterWizardMessages [LangMsg(Languages.en, "Prefab Asset cannot be exported. Prefab Asset has different behaviour with Scene GameObject. Please put the prefab into the scene")] PREFAB_CANNOT_EXPORT, - [LangMsg(Languages.ja, "回転・拡大縮小を持つノードが含まれています。正規化が必用です。Setting の PoseFreeze を有効にしてください")] - [LangMsg(Languages.en, " Normalization is required. There are nodes (child GameObject) where rotation and scaling are not default. Please enable PoseFreeze")] + [LangMsg(Languages.ja, "回転・拡大縮小もしくはWeightの無いBlendShapeが含まれています。正規化が必用です。Setting の PoseFreeze を有効にしてください")] + [LangMsg(Languages.en, " Normalization is required. There are nodes (child GameObject) where rotation and scaling or blendshape without bone weight are not default. Please enable PoseFreeze")] ROTATION_OR_SCALEING_INCLUDED_IN_NODE, [LangMsg(Languages.ja, "正規化済みです。Setting の PoseFreeze は不要です")]