From 22733bc2b165a43663a8bbf527deaba5d72318c2 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 26 Aug 2020 13:03:02 +0900 Subject: [PATCH 1/6] =?UTF-8?q?=E3=83=A1=E3=83=83=E3=82=BB=E3=83=BC?= =?UTF-8?q?=E3=82=B8=E3=81=AE=E8=A8=98=E8=BF=B0=E6=96=B9=E6=B3=95=E3=82=92?= =?UTF-8?q?=E5=A4=89=E6=9B=B4=E3=80=82enum=20=E3=81=AB=20Attribute=20?= =?UTF-8?q?=E3=81=A4=E3=81=91=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/VRM/UniVRM/Editor/EditorLanguages.cs | 154 ++++++++++++++++++ .../VRM/UniVRM/Editor/EditorLanguages.cs.meta | 11 ++ .../UniVRM/Editor/Format/VRMExporterWizard.cs | 62 +++---- .../Format/VRMExporterWizardMessages.cs | 148 ++++++++--------- 4 files changed, 268 insertions(+), 107 deletions(-) create mode 100644 Assets/VRM/UniVRM/Editor/EditorLanguages.cs create mode 100644 Assets/VRM/UniVRM/Editor/EditorLanguages.cs.meta diff --git a/Assets/VRM/UniVRM/Editor/EditorLanguages.cs b/Assets/VRM/UniVRM/Editor/EditorLanguages.cs new file mode 100644 index 000000000..7b496cfc5 --- /dev/null +++ b/Assets/VRM/UniVRM/Editor/EditorLanguages.cs @@ -0,0 +1,154 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace VRM.M17N +{ + /// + /// 多言語対応 + /// + public enum Languages + { + ja, + en, + } + + [System.AttributeUsage(System.AttributeTargets.Field, AllowMultiple = true, Inherited = false)] + public class LangMsgAttribute : System.Attribute + { + public Languages Language; + public string Message; + + public LangMsgAttribute(Languages language, string msg) + { + Language = language; + Message = msg; + } + } + + public enum VRMExporterWizardMessages + { + [LangMsg(Languages.ja, "ExportRootをセットしてください")] + [LangMsg(Languages.en, "Please set up a ExportRoot for model export")] + ROOT_EXISTS, + + + [LangMsg(Languages.ja, "ExportRootに親はオブジェクトは持てません")] + [LangMsg(Languages.en, "ExportRoot must be topmost parent")] + NO_PARENT, + + [LangMsg(Languages.ja, "ExportRootに回転・拡大縮小は持てません。子階層で回転・拡大縮小してください")] + [LangMsg(Languages.en, "ExportRoot's rotation and scaling are not allowed to change. Please set up rotation and scaling in child node")] + ROOT_WITHOUT_ROTATION_AND_SCALING_CHANGED, + + [LangMsg(Languages.ja, "シーンに出していない Prefab はエクスポートできません(細かい挙動が違い、想定外の動作をところがあるため)。シーンに展開してからエクスポートしてください")] + [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")] + ROTATION_OR_SCALEING_INCLUDED_IN_NODE, + + [LangMsg(Languages.ja, "正規化済みです。Setting の PoseFreeze は不要です")] + [LangMsg(Languages.en, "Normalization has been done. PoseFreeze is not required")] + IS_POSE_FREEZE_DONE, + + [LangMsg(Languages.ja, "ExportRootに Animator がありません")] + [LangMsg(Languages.en, "No Animator in ExportRoot")] + NO_ANIMATOR, + + [LangMsg(Languages.ja, "Z+ 向きにしてください")] + [LangMsg(Languages.en, "The model needs to face the positive Z-axis")] + FACE_Z_POSITIVE_DIRECTION, + + [LangMsg(Languages.ja, "ExportRootの Animator に Avatar がありません")] + [LangMsg(Languages.en, "No Avatar in ExportRoot's Animator")] + NO_AVATAR_IN_ANIMATOR, + + [LangMsg(Languages.ja, "ExportRootの Animator.Avatar が不正です")] + [LangMsg(Languages.en, "Animator.avatar in ExportRoot is not valid")] + AVATAR_IS_NOT_VALID, + + [LangMsg(Languages.ja, "ExportRootの Animator.Avatar がヒューマノイドではありません。FBX importer の Rig で設定してください")] + [LangMsg(Languages.en, "Animator.avatar is not humanoid. Please change model's AnimationType to humanoid")] + AVATAR_IS_NOT_HUMANOID, + + [LangMsg(Languages.ja, "humanoid設定に顎が含まれている。FBX importer の rig 設定に戻って設定を解除することをおすすめします")] + [LangMsg(Languages.en, "Jaw bone is included. It may not what you intended. Please check the humanoid avatar setting screen")] + JAW_BONE_IS_INCLUDED, + + [LangMsg(Languages.ja, "ヒエラルキーの中に同じ名前のGameObjectが含まれている。 エクスポートした場合に自動でリネームする")] + [LangMsg(Languages.en, "There are bones with the same name in the hierarchy. They will be automatically renamed after export")] + DUPLICATE_BONE_NAME_EXISTS, + + [LangMsg(Languages.ja, "VRMBlendShapeProxyが必要です。先にVRMフォーマットに変換してください")] + [LangMsg(Languages.en, "VRMBlendShapeProxy is required. Please convert to VRM format first")] + NEEDS_VRM_BLENDSHAPE_PROXY, + + [LangMsg(Languages.en, "This model contains vertex color")] + [LangMsg(Languages.ja, "ヒエラルキーに含まれる mesh に頂点カラーが含まれている")] + VERTEX_COLOR_IS_INCLUDED, + + [LangMsg(Languages.ja, "ヒエラルキーに active なメッシュが含まれていない")] + [LangMsg(Languages.en, "No active mesh")] + NO_ACTIVE_MESH, + + [LangMsg(Languages.ja, "Standard, Unlit, MToon 以外のマテリアルは、Standard になります")] + [LangMsg(Languages.en, "It will export as `Standard` fallback")] + UNKNOWN_SHADER, + + [LangMsg(Languages.ja, "名前が長すぎる。リネームしてください: ")] + [LangMsg(Languages.en, "FileName is too long: ")] + FILENAME_TOO_LONG, + } + + static class MsgCache where T : Enum + { + static Dictionary> s_cache = new Dictionary>(); + + static LangMsgAttribute GetAttribute(T value, Languages language) + { + var t = typeof(T); + var memberInfos = t.GetMember(value.ToString()); + var enumValueMemberInfo = memberInfos.FirstOrDefault(m => m.DeclaringType == t); + var attr = enumValueMemberInfo.GetCustomAttributes(typeof(LangMsgAttribute), false).Select(x => (LangMsgAttribute)x).ToArray(); + if (attr == null || attr.Length == 0) + { + return null; + } + var match = attr.FirstOrDefault(x => x.Language == language); + if (match != null) + { + return match; + } + return attr.First(); + } + + public static string Get(Languages language, T key) + { + if (!s_cache.TryGetValue(language, out Dictionary map)) + { + map = new Dictionary(); + + var t = typeof(T); + foreach (T value in Enum.GetValues(t)) + { + var match = GetAttribute(value, language); + map.Add(value, match != null ? match.Message : ""); + } + + s_cache.Add(language, map); + } + return map[key]; + } + } + public static class Getter + { + public static M17N.Languages Lang; + + public static string Msg(T key) where T : Enum + { + return M17N.MsgCache.Get(Lang, key); + } + } +} diff --git a/Assets/VRM/UniVRM/Editor/EditorLanguages.cs.meta b/Assets/VRM/UniVRM/Editor/EditorLanguages.cs.meta new file mode 100644 index 000000000..179168ee0 --- /dev/null +++ b/Assets/VRM/UniVRM/Editor/EditorLanguages.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7829d135d35830f4bb9235eb10b3de1f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizard.cs b/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizard.cs index 9820deb65..87f162cc7 100644 --- a/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizard.cs +++ b/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizard.cs @@ -153,6 +153,11 @@ namespace VRM return true; } + static string Msg(VRMExporterWizardMessages key) + { + return M17N.Getter.Msg(key); + } + /// /// エクスポート可能か検証する /// @@ -166,18 +171,18 @@ namespace VRM if (DuplicateBoneNameExists()) { - yield return Validation.Warning(Msg.DUPLICATE_BONE_NAME_EXISTS); + yield return Validation.Warning(Msg(VRMExporterWizardMessages.DUPLICATE_BONE_NAME_EXISTS)); } if (m_settings.ReduceBlendshape && ExportRoot.GetComponent() == null) { - yield return Validation.Error(Msg.NEEDS_VRM_BLENDSHAPE_PROXY); + yield return Validation.Error(Msg(VRMExporterWizardMessages.NEEDS_VRM_BLENDSHAPE_PROXY)); } var vertexColor = ExportRoot.GetComponentsInChildren().Any(x => x.sharedMesh.colors.Length > 0); if (vertexColor) { - yield return Validation.Warning(Msg.VERTEX_COLOR_IS_INCLUDED); + yield return Validation.Warning(Msg(VRMExporterWizardMessages.VERTEX_COLOR_IS_INCLUDED)); } var renderers = ExportRoot.GetComponentsInChildren(); @@ -202,13 +207,13 @@ namespace VRM continue; } - yield return Validation.Warning($"Material: {material.name}. Unknown Shader: \"{material.shader.name}\" is used. {Msg.UNKNOWN_SHADER}"); + yield return Validation.Warning($"Material: {material.name}. Unknown Shader: \"{material.shader.name}\" is used. {Msg(VRMExporterWizardMessages.UNKNOWN_SHADER)}"); } foreach (var material in materials) { if (IsFileNameLengthTooLong(material.name)) - yield return Validation.Error(Msg.FILENAME_TOO_LONG + material.name); + yield return Validation.Error(Msg(VRMExporterWizardMessages.FILENAME_TOO_LONG) + material.name); } var textureNameList = new List(); @@ -233,7 +238,7 @@ namespace VRM foreach (var textureName in textureNameList) { if (IsFileNameLengthTooLong(textureName)) - yield return Validation.Error(Msg.FILENAME_TOO_LONG + textureName); + yield return Validation.Error(Msg(VRMExporterWizardMessages.FILENAME_TOO_LONG) + textureName); } var vrmMeta = ExportRoot.GetComponent(); @@ -241,7 +246,7 @@ namespace VRM { var thumbnailName = vrmMeta.Meta.Thumbnail.name; if (IsFileNameLengthTooLong(thumbnailName)) - yield return Validation.Error(Msg.FILENAME_TOO_LONG + thumbnailName); + yield return Validation.Error(Msg(VRMExporterWizardMessages.FILENAME_TOO_LONG) + thumbnailName); } var meshFilters = ExportRoot.GetComponentsInChildren(); @@ -249,7 +254,7 @@ namespace VRM foreach (var meshName in meshesName) { if (IsFileNameLengthTooLong(meshName)) - yield return Validation.Error(Msg.FILENAME_TOO_LONG + meshName); + yield return Validation.Error(Msg(VRMExporterWizardMessages.FILENAME_TOO_LONG) + meshName); } var skinnedmeshRenderers = ExportRoot.GetComponentsInChildren(); @@ -257,7 +262,7 @@ namespace VRM foreach (var skinnedmeshName in skinnedmeshesName) { if (IsFileNameLengthTooLong(skinnedmeshName)) - yield return Validation.Error(Msg.FILENAME_TOO_LONG + skinnedmeshName); + yield return Validation.Error(Msg(VRMExporterWizardMessages.FILENAME_TOO_LONG) + skinnedmeshName); } } @@ -291,7 +296,7 @@ namespace VRM m_Inspector = Editor.CreateEditor(m_settings); } - m_lang = EnumUtil.TryParseOrDefault(EditorPrefs.GetString(LANG_KEY, default(VRMExporterWizardMessages.Languages).ToString())); + M17N.Getter.Lang = EnumUtil.TryParseOrDefault(EditorPrefs.GetString(LANG_KEY, default(M17N.Languages).ToString())); } const string LANG_KEY = "VRM_LANG"; @@ -344,11 +349,6 @@ namespace VRM } } - VRMExporterWizardMessages.Languages m_lang; - VRMExporterWizardMessages.LangMessages Msg => VRMExporterWizardMessages.M17N[m_lang]; - - //@TODO: Force repaint if scripts recompile - private void OnGUI() { if (m_tmpMeta == null) @@ -360,11 +360,11 @@ namespace VRM EditorGUIUtility.labelWidth = 150; // lang - var lang = (VRMExporterWizardMessages.Languages)EditorGUILayout.EnumPopup("lang", m_lang); - if (lang != m_lang) + var lang = (M17N.Languages)EditorGUILayout.EnumPopup("lang", M17N.Getter.Lang); + if (lang != M17N.Getter.Lang) { - m_lang = lang; - EditorPrefs.SetString(LANG_KEY, m_lang.ToString()); + M17N.Getter.Lang = lang; + EditorPrefs.SetString(LANG_KEY, M17N.Getter.Lang.ToString()); } EditorGUILayout.LabelField("ExportRoot"); @@ -382,24 +382,24 @@ namespace VRM // if (ExportRoot == null) { - Validation.Error(Msg.ROOT_EXISTS).DrawGUI(); + Validation.Error(Msg(VRMExporterWizardMessages.ROOT_EXISTS)).DrawGUI(); return; } if (ExportRoot.transform.parent != null) { - Validation.Error(Msg.NO_PARENT).DrawGUI(); + Validation.Error(Msg(VRMExporterWizardMessages.NO_PARENT)).DrawGUI(); return; } if (ExportRoot.transform.localRotation != Quaternion.identity || ExportRoot.transform.localScale != Vector3.one) { - Validation.Error(Msg.ROOT_WITHOUT_ROTATION_AND_SCALING_CHANGED).DrawGUI(); + Validation.Error(Msg(VRMExporterWizardMessages.ROOT_WITHOUT_ROTATION_AND_SCALING_CHANGED)).DrawGUI(); return; } var renderers = ExportRoot.GetComponentsInChildren(); if (renderers.All(x => !EnableRenderer(x))) { - Validation.Error(Msg.NO_ACTIVE_MESH).DrawGUI(); + Validation.Error(Msg(VRMExporterWizardMessages.NO_ACTIVE_MESH)).DrawGUI(); return; } @@ -411,14 +411,14 @@ namespace VRM } else { - Validation.Warning(Msg.ROTATION_OR_SCALEING_INCLUDED_IN_NODE).DrawGUI(); + Validation.Warning(Msg(VRMExporterWizardMessages.ROTATION_OR_SCALEING_INCLUDED_IN_NODE)).DrawGUI(); } } else { if (m_settings.PoseFreeze) { - Validation.Warning(Msg.IS_POSE_FREEZE_DONE).DrawGUI(); + Validation.Warning(Msg(VRMExporterWizardMessages.IS_POSE_FREEZE_DONE)).DrawGUI(); } else { @@ -432,7 +432,7 @@ namespace VRM var animator = ExportRoot.GetComponent(); if (animator == null) { - Validation.Error(Msg.NO_ANIMATOR).DrawGUI(); + Validation.Error(Msg(VRMExporterWizardMessages.NO_ANIMATOR)).DrawGUI(); return; } @@ -441,30 +441,30 @@ namespace VRM var f = GetForward(l, r); if (Vector3.Dot(f, Vector3.forward) < 0.8f) { - Validation.Error(Msg.FACE_Z_POSITIVE_DIRECTION).DrawGUI(); + Validation.Error(Msg(VRMExporterWizardMessages.FACE_Z_POSITIVE_DIRECTION)).DrawGUI(); return; } var avatar = animator.avatar; if (avatar == null) { - Validation.Error(Msg.NO_AVATAR_IN_ANIMATOR).DrawGUI(); + Validation.Error(Msg(VRMExporterWizardMessages.NO_AVATAR_IN_ANIMATOR)).DrawGUI(); return; } if (!avatar.isValid) { - Validation.Error(Msg.AVATAR_IS_NOT_VALID).DrawGUI(); + Validation.Error(Msg(VRMExporterWizardMessages.AVATAR_IS_NOT_VALID)).DrawGUI(); return; } if (!avatar.isHuman) { - Validation.Error(Msg.AVATAR_IS_NOT_HUMANOID).DrawGUI(); + Validation.Error(Msg(VRMExporterWizardMessages.AVATAR_IS_NOT_HUMANOID)).DrawGUI(); return; } var jaw = animator.GetBoneTransform(HumanBodyBones.Jaw); if (jaw != null) { - Validation.Warning(Msg.JAW_BONE_IS_INCLUDED).DrawGUI(); + Validation.Warning(Msg(VRMExporterWizardMessages.JAW_BONE_IS_INCLUDED)).DrawGUI(); } else { diff --git a/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizardMessages.cs b/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizardMessages.cs index 668c50215..16f4c53ba 100644 --- a/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizardMessages.cs +++ b/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizardMessages.cs @@ -1,84 +1,80 @@ -using System.Collections.Generic; +using VRM.M17N; namespace VRM { - /// - /// エクスポートダイアログ用の簡易なメッセージカタログ - /// - public static class VRMExporterWizardMessages + public enum VRMExporterWizardMessages { - public enum Languages - { - ja, - en, - } + [LangMsg(Languages.ja, "ExportRootをセットしてください")] + [LangMsg(Languages.en, "Please set up a ExportRoot for model export")] + ROOT_EXISTS, - public struct LangMessages - { - public string ROOT_EXISTS; - public string NO_PARENT; - public string ROOT_WITHOUT_ROTATION_AND_SCALING_CHANGED; - public string PREFAB_CANNOT_EXPORT; - public string ROTATION_OR_SCALEING_INCLUDED_IN_NODE; - public string IS_POSE_FREEZE_DONE; - public string NO_ANIMATOR; - public string FACE_Z_POSITIVE_DIRECTION; - public string NO_AVATAR_IN_ANIMATOR; - public string AVATAR_IS_NOT_VALID; - public string AVATAR_IS_NOT_HUMANOID; - public string JAW_BONE_IS_INCLUDED; - public string DUPLICATE_BONE_NAME_EXISTS; - public string NEEDS_VRM_BLENDSHAPE_PROXY; - public string VERTEX_COLOR_IS_INCLUDED; - public string NO_ACTIVE_MESH; - public string UNKNOWN_SHADER; - public string FILENAME_TOO_LONG; - } - public static readonly Dictionary M17N = new Dictionary - { - {Languages.ja, new LangMessages{ - ROOT_EXISTS ="ExportRootをセットしてください", - NO_PARENT = "ExportRootに親はオブジェクトは持てません", - ROOT_WITHOUT_ROTATION_AND_SCALING_CHANGED = "ExportRootに回転・拡大縮小は持てません。子階層で回転・拡大縮小してください", - PREFAB_CANNOT_EXPORT = "シーンに出していない Prefab はエクスポートできません(細かい挙動が違い、想定外の動作をところがあるため)。シーンに展開してからエクスポートしてください", - ROTATION_OR_SCALEING_INCLUDED_IN_NODE = "回転・拡大縮小を持つノードが含まれています。正規化が必用です。Setting の PoseFreeze を有効にしてください", - IS_POSE_FREEZE_DONE = "正規化済みです。Setting の PoseFreeze は不要です", - NO_ANIMATOR = "ExportRootに Animator がありません", - FACE_Z_POSITIVE_DIRECTION = "Z+ 向きにしてください", - NO_AVATAR_IN_ANIMATOR = "ExportRootの Animator に Avatar がありません", - AVATAR_IS_NOT_VALID = "ExportRootの Animator.Avatar が不正です", - AVATAR_IS_NOT_HUMANOID = "ExportRootの Animator.Avatar がヒューマノイドではありません。FBX importer の Rig で設定してください", - JAW_BONE_IS_INCLUDED = "humanoid設定に顎が含まれている。FBX importer の rig 設定に戻って設定を解除することをおすすめします", - DUPLICATE_BONE_NAME_EXISTS = "ヒエラルキーの中に同じ名前のGameObjectが含まれている。 エクスポートした場合に自動でリネームする", - NEEDS_VRM_BLENDSHAPE_PROXY = "VRMBlendShapeProxyが必要です。先にVRMフォーマットに変換してください", - VERTEX_COLOR_IS_INCLUDED = "ヒエラルキーに含まれる mesh に頂点カラーが含まれている", - NO_ACTIVE_MESH = "ヒエラルキーに active なメッシュが含まれていない", - UNKNOWN_SHADER = "Standard, Unlit, MToon 以外のマテリアルは、Standard になります", - FILENAME_TOO_LONG = "名前が長すぎる。リネームしてください: ", - } - }, - {Languages.en, new LangMessages{ - ROOT_EXISTS = "Please set up a ExportRoot for model export", - NO_PARENT = "ExportRoot must be topmost parent", - ROOT_WITHOUT_ROTATION_AND_SCALING_CHANGED = "ExportRoot's rotation and scaling are not allowed to change. Please set up rotation and scaling in child node", - PREFAB_CANNOT_EXPORT = "Prefab Asset cannot be exported. Prefab Asset has different behaviour with Scene GameObject. Please put the prefab into the scene", - ROTATION_OR_SCALEING_INCLUDED_IN_NODE = " Normalization is required. There are nodes (child GameObject) where rotation and scaling are not default. Please enable PoseFreeze", - IS_POSE_FREEZE_DONE = "Normalization has been done. PoseFreeze is not required", - NO_ANIMATOR = "No Animator in ExportRoot", - FACE_Z_POSITIVE_DIRECTION = "The model needs to face the positive Z-axis", - NO_AVATAR_IN_ANIMATOR = "No Avatar in ExportRoot's Animator", - AVATAR_IS_NOT_VALID = "Animator.avatar in ExportRoot is not valid", - AVATAR_IS_NOT_HUMANOID = "Animator.avatar is not humanoid. Please change model's AnimationType to humanoid", - JAW_BONE_IS_INCLUDED = "Jaw bone is included. It may not what you intended. Please check the humanoid avatar setting screen", - DUPLICATE_BONE_NAME_EXISTS = "There are bones with the same name in the hierarchy. They will be automatically renamed after export", - NEEDS_VRM_BLENDSHAPE_PROXY = "VRMBlendShapeProxy is required. Please convert to VRM format first", - VERTEX_COLOR_IS_INCLUDED = "This model contains vertex color", - NO_ACTIVE_MESH = "No active mesh", - UNKNOWN_SHADER = "It will export as `Standard` fallback", - FILENAME_TOO_LONG = "FileName is too long: ", - } - }, - }; + [LangMsg(Languages.ja, "ExportRootに親はオブジェクトは持てません")] + [LangMsg(Languages.en, "ExportRoot must be topmost parent")] + NO_PARENT, + + [LangMsg(Languages.ja, "ExportRootに回転・拡大縮小は持てません。子階層で回転・拡大縮小してください")] + [LangMsg(Languages.en, "ExportRoot's rotation and scaling are not allowed to change. Please set up rotation and scaling in child node")] + ROOT_WITHOUT_ROTATION_AND_SCALING_CHANGED, + + [LangMsg(Languages.ja, "シーンに出していない Prefab はエクスポートできません(細かい挙動が違い、想定外の動作をところがあるため)。シーンに展開してからエクスポートしてください")] + [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")] + ROTATION_OR_SCALEING_INCLUDED_IN_NODE, + + [LangMsg(Languages.ja, "正規化済みです。Setting の PoseFreeze は不要です")] + [LangMsg(Languages.en, "Normalization has been done. PoseFreeze is not required")] + IS_POSE_FREEZE_DONE, + + [LangMsg(Languages.ja, "ExportRootに Animator がありません")] + [LangMsg(Languages.en, "No Animator in ExportRoot")] + NO_ANIMATOR, + + [LangMsg(Languages.ja, "Z+ 向きにしてください")] + [LangMsg(Languages.en, "The model needs to face the positive Z-axis")] + FACE_Z_POSITIVE_DIRECTION, + + [LangMsg(Languages.ja, "ExportRootの Animator に Avatar がありません")] + [LangMsg(Languages.en, "No Avatar in ExportRoot's Animator")] + NO_AVATAR_IN_ANIMATOR, + + [LangMsg(Languages.ja, "ExportRootの Animator.Avatar が不正です")] + [LangMsg(Languages.en, "Animator.avatar in ExportRoot is not valid")] + AVATAR_IS_NOT_VALID, + + [LangMsg(Languages.ja, "ExportRootの Animator.Avatar がヒューマノイドではありません。FBX importer の Rig で設定してください")] + [LangMsg(Languages.en, "Animator.avatar is not humanoid. Please change model's AnimationType to humanoid")] + AVATAR_IS_NOT_HUMANOID, + + [LangMsg(Languages.ja, "humanoid設定に顎が含まれている。FBX importer の rig 設定に戻って設定を解除することをおすすめします")] + [LangMsg(Languages.en, "Jaw bone is included. It may not what you intended. Please check the humanoid avatar setting screen")] + JAW_BONE_IS_INCLUDED, + + [LangMsg(Languages.ja, "ヒエラルキーの中に同じ名前のGameObjectが含まれている。 エクスポートした場合に自動でリネームする")] + [LangMsg(Languages.en, "There are bones with the same name in the hierarchy. They will be automatically renamed after export")] + DUPLICATE_BONE_NAME_EXISTS, + + [LangMsg(Languages.ja, "VRMBlendShapeProxyが必要です。先にVRMフォーマットに変換してください")] + [LangMsg(Languages.en, "VRMBlendShapeProxy is required. Please convert to VRM format first")] + NEEDS_VRM_BLENDSHAPE_PROXY, + + [LangMsg(Languages.en, "This model contains vertex color")] + [LangMsg(Languages.ja, "ヒエラルキーに含まれる mesh に頂点カラーが含まれている")] + VERTEX_COLOR_IS_INCLUDED, + + [LangMsg(Languages.ja, "ヒエラルキーに active なメッシュが含まれていない")] + [LangMsg(Languages.en, "No active mesh")] + NO_ACTIVE_MESH, + + [LangMsg(Languages.ja, "Standard, Unlit, MToon 以外のマテリアルは、Standard になります")] + [LangMsg(Languages.en, "It will export as `Standard` fallback")] + UNKNOWN_SHADER, + + [LangMsg(Languages.ja, "名前が長すぎる。リネームしてください: ")] + [LangMsg(Languages.en, "FileName is too long: ")] + FILENAME_TOO_LONG, } } From 28f5529d5ca79bcf81f463e79b73aef609fbd8ca Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 26 Aug 2020 13:22:30 +0900 Subject: [PATCH 2/6] VRMExportSettingsEditor.Options --- Assets/VRM/UniVRM/Editor/EditorLanguages.cs | 1 - .../Editor/Format/VRMExportSettingsEditor.cs | 88 +++++++++++++------ 2 files changed, 61 insertions(+), 28 deletions(-) diff --git a/Assets/VRM/UniVRM/Editor/EditorLanguages.cs b/Assets/VRM/UniVRM/Editor/EditorLanguages.cs index 7b496cfc5..14416d7ce 100644 --- a/Assets/VRM/UniVRM/Editor/EditorLanguages.cs +++ b/Assets/VRM/UniVRM/Editor/EditorLanguages.cs @@ -32,7 +32,6 @@ namespace VRM.M17N [LangMsg(Languages.en, "Please set up a ExportRoot for model export")] ROOT_EXISTS, - [LangMsg(Languages.ja, "ExportRootに親はオブジェクトは持てません")] [LangMsg(Languages.en, "ExportRoot must be topmost parent")] NO_PARENT, diff --git a/Assets/VRM/UniVRM/Editor/Format/VRMExportSettingsEditor.cs b/Assets/VRM/UniVRM/Editor/Format/VRMExportSettingsEditor.cs index 1a4707f08..5b05edae9 100644 --- a/Assets/VRM/UniVRM/Editor/Format/VRMExportSettingsEditor.cs +++ b/Assets/VRM/UniVRM/Editor/Format/VRMExportSettingsEditor.cs @@ -1,6 +1,8 @@ +using System; using UnityEditor; using UnityEngine; +using VRM.M17N; namespace VRM { @@ -10,18 +12,26 @@ namespace VRM class CheckBoxProp { public SerializedProperty Property; - public string Description; + public Func Description; - public CheckBoxProp(SerializedProperty property, string desc) + public CheckBoxProp(SerializedProperty property, Func desc) { Property = property; Description = desc; } + public CheckBoxProp(SerializedProperty property, Options desc) : this(property, () => Msg(desc)) + { + } + + public CheckBoxProp(SerializedProperty property, string desc) : this(property, () => desc) + { + } + public void Draw() { EditorGUILayout.PropertyField(Property); - EditorGUILayout.HelpBox(Description, MessageType.None); + EditorGUILayout.HelpBox(Description(), MessageType.None); EditorGUILayout.Space(); } } @@ -83,32 +93,56 @@ namespace VRM CheckBoxProp m_reduceBlendShapeClip; CheckBoxProp m_removeVertexColor; + static string Msg(Options key) + { + return M17N.Getter.Msg(key); + } + + enum Options + { + [LangMsg(Languages.ja, "エクスポート時に強制的にT-Pose化する。これを使わずに手動でT-Poseを作っても問題ありません")] + [LangMsg(Languages.en, "Force T-Pose before export. Manually making T-Pose for model without enabling this is ok")] + FORCE_T_POSE, + + [LangMsg(Languages.ja, "エクスポート時に正規化(ヒエラルキーから回転と拡大縮小を取り除くためにベイク)する")] + [LangMsg(Languages.en, "Model's normalization (bake to remove roation and scaling from the hierarchy)")] + NORMALIZE, + + [LangMsg(Languages.ja, "エクスポート時に新しいJsonSerializerを使う")] + [LangMsg(Languages.en, "The new version of JsonSerializer for model export")] + USE_GENERATED_SERIALIZER, + + [LangMsg(Languages.ja, "BlendShapeの容量を GLTF の Sparse Accessor 機能で削減する。修正中: UniGLTF以外でロードできません")] + [LangMsg(Languages.en, "BlendShape size can be reduced by using Sparse Accessor")] + BLENDSHAPE_USE_SPARSE, + + [LangMsg(Languages.ja, "BlendShapeClipのエクスポートに法線とTangentを含めない。UniVRM-0.53 以前ではロードがエラーになるのに注意してください")] + [LangMsg(Languages.en, "BlendShape's Normal and Tangent will not be exported. Be aware that errors may occur during import if the model is made by UniVRM-0.53 or earlier versions")] + BLENDSHAPE_EXCLUDE_NORMAL_AND_TANGENT, + + [LangMsg(Languages.ja, "BlendShapeClipから参照されないBlendShapeをエクスポートに含めない")] + [LangMsg(Languages.en, "BlendShapes that are not referenced by BlendShapeClips will not be exported")] + BLENDSHAPE_ONLY_CLIP_USE, + + [LangMsg(Languages.ja, "BlendShapeClip.Preset == Unknown のBlendShapeClipをエクスポートに含めない")] + [LangMsg(Languages.en, "BlendShapeClip will not be exported if BlendShapeClip.Preset == Unknown")] + BLENDSHAPE_EXCLUDE_UNKNOWN, + + [LangMsg(Languages.ja, "エクスポートに頂点カラーを含めない")] + [LangMsg(Languages.en, "Vertex color will not be exported")] + REMOVE_VERTEX_COLOR, + } + private void OnEnable() { - m_forceTPose = new CheckBoxProp(serializedObject.FindProperty(nameof(ForceTPose)), - "エクスポート時に強制的にT-Pose化する。これを使わずに手動でT-Poseを作っても問題ありません \n" + - "Force T-Pose before export. Manually making T-Pose for model without enabling this is ok"); - m_poseFreeze = new CheckBoxProp(serializedObject.FindProperty(nameof(PoseFreeze)), - "エクスポート時に正規化(ヒエラルキーから回転と拡大縮小を取り除くためにベイク)する \n" + - "Model's normalization (bake to remove roation and scaling from the hierarchy)"); - m_useExcperimentalExporter = new CheckBoxProp(serializedObject.FindProperty(nameof(UseExperimentalExporter)), - "エクスポート時に新しいJsonSerializerを使う \n" + - "The new version of JsonSerializer for model export"); - m_useSparseAccessor = new CheckBoxProp(serializedObject.FindProperty(nameof(UseSparseAccessor)), - "BlendShapeの容量を GLTF の Sparse Accessor 機能で削減する。修正中: UniGLTF以外でロードできません \n" + - "BlendShape size can be reduced by using Sparse Accessor"); - m_onlyBlendShapePosition = new CheckBoxProp(serializedObject.FindProperty(nameof(OnlyBlendshapePosition)), - "BlendShapeClipのエクスポートに法線とTangentを含めない。UniVRM-0.53 以前ではロードがエラーになるのに注意してください \n" + - "BlendShape's Normal and Tangent will not be exported. Be aware that errors may occur during import if the model is made by UniVRM-0.53 or earlier versions"); - m_reduceBlendShape = new CheckBoxProp(serializedObject.FindProperty(nameof(ReduceBlendshape)), - "BlendShapeClipから参照されないBlendShapeをエクスポートに含めない \n" + - "BlendShapes that are not referenced by BlendShapeClips will not be exported"); - m_reduceBlendShapeClip = new CheckBoxProp(serializedObject.FindProperty(nameof(ReduceBlendshapeClip)), - "BlendShapeClip.Preset == Unknown のBlendShapeClipをエクスポートに含めない \n" + - "BlendShapeClip will not be exported if BlendShapeClip.Preset == Unknown"); - m_removeVertexColor = new CheckBoxProp(serializedObject.FindProperty(nameof(RemoveVertexColor)), - "エクスポートに頂点カラーを含めない \n" + - "Vertex color will not be exported"); + m_forceTPose = new CheckBoxProp(serializedObject.FindProperty(nameof(ForceTPose)), Options.FORCE_T_POSE); + m_poseFreeze = new CheckBoxProp(serializedObject.FindProperty(nameof(PoseFreeze)), Options.NORMALIZE); + m_useExcperimentalExporter = new CheckBoxProp(serializedObject.FindProperty(nameof(UseExperimentalExporter)), Options.USE_GENERATED_SERIALIZER); + m_useSparseAccessor = new CheckBoxProp(serializedObject.FindProperty(nameof(UseSparseAccessor)), Options.BLENDSHAPE_USE_SPARSE); + m_onlyBlendShapePosition = new CheckBoxProp(serializedObject.FindProperty(nameof(OnlyBlendshapePosition)), Options.BLENDSHAPE_EXCLUDE_NORMAL_AND_TANGENT); + m_reduceBlendShape = new CheckBoxProp(serializedObject.FindProperty(nameof(ReduceBlendshape)), Options.BLENDSHAPE_ONLY_CLIP_USE); + m_reduceBlendShapeClip = new CheckBoxProp(serializedObject.FindProperty(nameof(ReduceBlendshapeClip)), Options.BLENDSHAPE_EXCLUDE_UNKNOWN); + m_removeVertexColor = new CheckBoxProp(serializedObject.FindProperty(nameof(RemoveVertexColor)), Options.REMOVE_VERTEX_COLOR); } public override void OnInspectorGUI() From 605ea0b6186311f0b2d755c9ef69df79da9f9262 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 26 Aug 2020 14:54:29 +0900 Subject: [PATCH 3/6] =?UTF-8?q?=E5=8D=98=E7=B4=94=E5=8C=96(Dictionary?= =?UTF-8?q?=E5=89=8A=E9=99=A4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UniVRM/Editor/Meta/VRMMetaObjectEditor.cs | 165 ++++++++++-------- 1 file changed, 88 insertions(+), 77 deletions(-) diff --git a/Assets/VRM/UniVRM/Editor/Meta/VRMMetaObjectEditor.cs b/Assets/VRM/UniVRM/Editor/Meta/VRMMetaObjectEditor.cs index c06ca3675..25cd3cf11 100644 --- a/Assets/VRM/UniVRM/Editor/Meta/VRMMetaObjectEditor.cs +++ b/Assets/VRM/UniVRM/Editor/Meta/VRMMetaObjectEditor.cs @@ -1,5 +1,3 @@ -using System; -using System.Collections.Generic; using UnityEditor; using UnityEngine; @@ -8,16 +6,14 @@ namespace VRM [CustomEditor(typeof(VRMMetaObject))] public class VRMMetaObjectEditor : Editor { - // SerializedProperty m_ScriptProp; - - class CustomProperty + class ValidateProperty { public SerializedProperty m_prop; public delegate (string, MessageType) Validator(SerializedProperty prop); Validator m_validator; - public CustomProperty(SerializedProperty prop, Validator validator) + public ValidateProperty(SerializedProperty prop, Validator validator) { m_prop = prop; m_validator = validator; @@ -35,67 +31,82 @@ namespace VRM // return old != m_prop.stringValue; } } - List> m_customPropMap = new List>(); - Dictionary m_propMap = new Dictionary(); - void InitMap(SerializedObject so) + VRMMetaObject m_target; + SerializedProperty m_Script; + SerializedProperty m_exporterVersion; + SerializedProperty m_thumbnail; + ValidateProperty m_title; + ValidateProperty m_version; + ValidateProperty m_author; + ValidateProperty m_contact; + ValidateProperty m_reference; + + SerializedProperty m_AllowedUser; + SerializedProperty m_ViolentUssage; + SerializedProperty m_SexualUssage; + SerializedProperty m_CommercialUssage; + SerializedProperty m_OtherPermissionUrl; + + SerializedProperty m_LicenseType; + SerializedProperty m_OtherLicenseUrl; + + private void OnEnable() { - m_propMap.Clear(); - m_customPropMap.Clear(); - if (so == null) - { - return; - } + m_target = (VRMMetaObject)target; - for (var it = so.GetIterator(); it.NextVisible(true);) - { - switch (it.name) - { - case "m_Script": - break; - - case "Title": - case "Version": - case "Author": - m_customPropMap.Add(new KeyValuePair(it.name, new CustomProperty(so.FindProperty(it.name), prop => + m_Script = serializedObject.FindProperty("m_Script"); + m_exporterVersion = serializedObject.FindProperty(nameof(m_target.ExporterVersion)); + m_thumbnail = serializedObject.FindProperty(nameof(m_target.Thumbnail)); + m_title = new ValidateProperty(serializedObject.FindProperty(nameof(m_target.Title)), prop => { if (string.IsNullOrEmpty(prop.stringValue)) { return ($"必須項目。{prop.name} を入力してください", MessageType.Error); } return ("", MessageType.None); - }))); - break; - - case "ContactInformation": - case "Reference": - m_customPropMap.Add(new KeyValuePair(it.name, - new CustomProperty(so.FindProperty(it.name), prop => + }); + m_version = new ValidateProperty(serializedObject.FindProperty(nameof(m_target.Version)), prop => + { + if (string.IsNullOrEmpty(prop.stringValue)) + { + return ($"必須項目。{prop.name} を入力してください", MessageType.Error); + } + return ("", MessageType.None); + }); + m_author = new ValidateProperty(serializedObject.FindProperty(nameof(m_target.Author)), prop => + { + if (string.IsNullOrEmpty(prop.stringValue)) + { + return ($"必須項目。{prop.name} を入力してください", MessageType.Error); + } + return ("", MessageType.None); + }); + m_contact = new ValidateProperty(serializedObject.FindProperty(nameof(m_target.ContactInformation)), prop => { return ("", MessageType.None); - }))); - break; + }); + m_reference = new ValidateProperty(serializedObject.FindProperty(nameof(m_target.Reference)), prop => + { + return ("", MessageType.None); + }); - default: - m_propMap.Add(it.name, so.FindProperty(it.name)); - break; - } - //Debug.LogFormat("{0}", it.name); - } + m_AllowedUser = serializedObject.FindProperty(nameof(m_target.AllowedUser)); + m_ViolentUssage = serializedObject.FindProperty(nameof(m_target.ViolentUssage)); + m_SexualUssage = serializedObject.FindProperty(nameof(m_target.SexualUssage)); + m_CommercialUssage = serializedObject.FindProperty(nameof(m_target.CommercialUssage)); + m_OtherPermissionUrl = serializedObject.FindProperty(nameof(m_target.OtherLicenseUrl)); + + m_LicenseType = serializedObject.FindProperty(nameof(m_target.LicenseType)); + m_OtherLicenseUrl = serializedObject.FindProperty(nameof(m_target.OtherLicenseUrl)); } - private void OnEnable() - { - // m_ScriptProp = serializedObject.FindProperty("m_Script"); - InitMap(serializedObject); - } - public override void OnInspectorGUI() { serializedObject.Update(); - // GUI.enabled = false; - // EditorGUILayout.PropertyField(m_ScriptProp, true); - // GUI.enabled = true; + GUI.enabled = false; + EditorGUILayout.PropertyField(m_Script, true); + GUI.enabled = true; EditorGUILayout.Space(); VRMMetaObjectGUI(serializedObject); @@ -106,54 +117,54 @@ namespace VRM bool m_foldoutDistribution = true; void VRMMetaObjectGUI(SerializedObject so) { - InitMap(so); - if (m_propMap == null || m_propMap.Count == 0) return; - so.Update(); - GUI.enabled = false; - - EditorGUILayout.PropertyField(m_propMap["ExporterVersion"]); - if (VRMVersion.IsNewer(m_propMap["ExporterVersion"].stringValue)) + if (VRMVersion.IsNewer(m_exporterVersion.stringValue)) { EditorGUILayout.HelpBox("Check UniVRM new version. https://github.com/dwango/UniVRM/releases", MessageType.Warning); } - GUI.enabled = true; + + // texture + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.BeginVertical(); + GUI.enabled = false; + EditorGUILayout.PropertyField(m_exporterVersion); + GUI.enabled = true; + EditorGUILayout.PropertyField(m_thumbnail); + EditorGUILayout.EndVertical(); + m_thumbnail.objectReferenceValue = TextureField("", (Texture2D)m_thumbnail.objectReferenceValue, 100); + } + EditorGUILayout.EndHorizontal(); m_foldoutInfo = EditorGUILayout.Foldout(m_foldoutInfo, "Information"); if (m_foldoutInfo) { - // texture - var thumbnail = m_propMap["Thumbnail"]; - EditorGUILayout.PropertyField(thumbnail); - thumbnail.objectReferenceValue = TextureField("", (Texture2D)thumbnail.objectReferenceValue, 100); - - foreach (var kv in m_customPropMap) - { - kv.Value.OnGUI(); - } + m_title.OnGUI(); + m_version.OnGUI(); + m_author.OnGUI(); + m_contact.OnGUI(); + m_reference.OnGUI(); } - - EditorGUILayout.LabelField("License ", EditorStyles.boldLabel); - + // EditorGUILayout.LabelField("License ", EditorStyles.boldLabel); m_foldoutPermission = EditorGUILayout.Foldout(m_foldoutPermission, "Personation / Characterization Permission"); if (m_foldoutPermission) { - EditorGUILayout.PropertyField(m_propMap["AllowedUser"], new GUIContent("A person who can perform with this avatar"), false); - EditorGUILayout.PropertyField(m_propMap["ViolentUssage"], new GUIContent("Violent acts using this avatar")); - EditorGUILayout.PropertyField(m_propMap["SexualUssage"], new GUIContent("Sexuality acts using this avatar")); - EditorGUILayout.PropertyField(m_propMap["CommercialUssage"], new GUIContent("For commercial use")); - EditorGUILayout.PropertyField(m_propMap["OtherPermissionUrl"], new GUIContent("Other License Url")); + EditorGUILayout.PropertyField(m_AllowedUser, new GUIContent("A person who can perform with this avatar"), false); + EditorGUILayout.PropertyField(m_ViolentUssage, new GUIContent("Violent acts using this avatar")); + EditorGUILayout.PropertyField(m_SexualUssage, new GUIContent("Sexuality acts using this avatar")); + EditorGUILayout.PropertyField(m_CommercialUssage, new GUIContent("For commercial use")); + EditorGUILayout.PropertyField(m_OtherPermissionUrl, new GUIContent("Other License Url")); } m_foldoutDistribution = EditorGUILayout.Foldout(m_foldoutDistribution, "Redistribution / Modifications License"); if (m_foldoutDistribution) { - var licenseType = m_propMap["LicenseType"]; + var licenseType = m_LicenseType; EditorGUILayout.PropertyField(licenseType); if ((LicenseType)licenseType.intValue == LicenseType.Other) { - EditorGUILayout.PropertyField(m_propMap["OtherLicenseUrl"]); + EditorGUILayout.PropertyField(m_OtherLicenseUrl); } } From 88923dc4af693aade970c59fc4a0009b130df37e Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 26 Aug 2020 15:04:39 +0900 Subject: [PATCH 4/6] OnGuiSelectLang --- Assets/VRM/UniVRM/Editor/EditorLanguages.cs | 27 ++++++++++++++++++- .../UniVRM/Editor/Format/VRMExporterWizard.cs | 10 ++----- .../UniVRM/Editor/Meta/VRMMetaObjectEditor.cs | 23 +++++++++++++--- 3 files changed, 48 insertions(+), 12 deletions(-) diff --git a/Assets/VRM/UniVRM/Editor/EditorLanguages.cs b/Assets/VRM/UniVRM/Editor/EditorLanguages.cs index 14416d7ce..b2cf23463 100644 --- a/Assets/VRM/UniVRM/Editor/EditorLanguages.cs +++ b/Assets/VRM/UniVRM/Editor/EditorLanguages.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using UnityEditor; namespace VRM.M17N { @@ -143,11 +144,35 @@ namespace VRM.M17N } public static class Getter { - public static M17N.Languages Lang; + const string LANG_KEY = "VRM_LANG"; + + static Languages? m_lang; + + public static Languages Lang + { + get + { + if (!m_lang.HasValue) + { + m_lang = EnumUtil.TryParseOrDefault(EditorPrefs.GetString(LANG_KEY, default(Languages).ToString())); + } + return m_lang.Value; + } + } public static string Msg(T key) where T : Enum { return M17N.MsgCache.Get(Lang, key); } + + public static void OnGuiSelectLang() + { + var lang = (M17N.Languages)EditorGUILayout.EnumPopup("lang", Lang); + if (lang != Lang) + { + m_lang = lang; + EditorPrefs.SetString(LANG_KEY, M17N.Getter.Lang.ToString()); + } + } } } diff --git a/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizard.cs b/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizard.cs index 87f162cc7..a981a8403 100644 --- a/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizard.cs +++ b/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizard.cs @@ -296,9 +296,8 @@ namespace VRM m_Inspector = Editor.CreateEditor(m_settings); } - M17N.Getter.Lang = EnumUtil.TryParseOrDefault(EditorPrefs.GetString(LANG_KEY, default(M17N.Languages).ToString())); + M17N.Getter.OnGuiSelectLang(); } - const string LANG_KEY = "VRM_LANG"; void OnDisable() { @@ -360,12 +359,7 @@ namespace VRM EditorGUIUtility.labelWidth = 150; // lang - var lang = (M17N.Languages)EditorGUILayout.EnumPopup("lang", M17N.Getter.Lang); - if (lang != M17N.Getter.Lang) - { - M17N.Getter.Lang = lang; - EditorPrefs.SetString(LANG_KEY, M17N.Getter.Lang.ToString()); - } + M17N.Getter.OnGuiSelectLang(); EditorGUILayout.LabelField("ExportRoot"); { diff --git a/Assets/VRM/UniVRM/Editor/Meta/VRMMetaObjectEditor.cs b/Assets/VRM/UniVRM/Editor/Meta/VRMMetaObjectEditor.cs index 25cd3cf11..bfa24652b 100644 --- a/Assets/VRM/UniVRM/Editor/Meta/VRMMetaObjectEditor.cs +++ b/Assets/VRM/UniVRM/Editor/Meta/VRMMetaObjectEditor.cs @@ -51,6 +51,21 @@ namespace VRM SerializedProperty m_LicenseType; SerializedProperty m_OtherLicenseUrl; + static string RequiredMessage(string name) + { + switch (M17N.Getter.Lang) + { + case M17N.Languages.ja: + return $"必須項目。{name} を入力してください"; + + case M17N.Languages.en: + return $"{name} is required"; + + default: + throw new System.NotImplementedException(); + } + } + private void OnEnable() { m_target = (VRMMetaObject)target; @@ -62,7 +77,7 @@ namespace VRM { if (string.IsNullOrEmpty(prop.stringValue)) { - return ($"必須項目。{prop.name} を入力してください", MessageType.Error); + return (RequiredMessage(prop.name), MessageType.Error); } return ("", MessageType.None); }); @@ -70,7 +85,7 @@ namespace VRM { if (string.IsNullOrEmpty(prop.stringValue)) { - return ($"必須項目。{prop.name} を入力してください", MessageType.Error); + return (RequiredMessage(prop.name), MessageType.Error); } return ("", MessageType.None); }); @@ -78,7 +93,7 @@ namespace VRM { if (string.IsNullOrEmpty(prop.stringValue)) { - return ($"必須項目。{prop.name} を入力してください", MessageType.Error); + return (RequiredMessage(prop.name), MessageType.Error); } return ("", MessageType.None); }); @@ -117,6 +132,8 @@ namespace VRM bool m_foldoutDistribution = true; void VRMMetaObjectGUI(SerializedObject so) { + M17N.Getter.OnGuiSelectLang(); + so.Update(); if (VRMVersion.IsNewer(m_exporterVersion.stringValue)) From 142754bdcc12297f42b2382303dc427a44113ad8 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 26 Aug 2020 15:51:19 +0900 Subject: [PATCH 5/6] Meta messages --- .../UniVRM/Editor/Meta/VRMMetaObjectEditor.cs | 71 +++++++++++++++++-- 1 file changed, 65 insertions(+), 6 deletions(-) diff --git a/Assets/VRM/UniVRM/Editor/Meta/VRMMetaObjectEditor.cs b/Assets/VRM/UniVRM/Editor/Meta/VRMMetaObjectEditor.cs index bfa24652b..84e7c0f92 100644 --- a/Assets/VRM/UniVRM/Editor/Meta/VRMMetaObjectEditor.cs +++ b/Assets/VRM/UniVRM/Editor/Meta/VRMMetaObjectEditor.cs @@ -1,5 +1,6 @@ using UnityEditor; using UnityEngine; +using VRM.M17N; namespace VRM { @@ -127,6 +128,41 @@ namespace VRM VRMMetaObjectGUI(serializedObject); } + enum MessageKeys + { + [LangMsg(Languages.ja, "アバターの人格に関する許諾範囲")] + [LangMsg(Languages.en, "Personation / Characterization Permission")] + PERSONATION, + + [LangMsg(Languages.ja, "アバターに人格を与えることの許諾範囲")] + [LangMsg(Languages.en, "A person who can perform with this avatar")] + ALLOWED_USER, + + [LangMsg(Languages.ja, "このアバターを用いて暴力表現を演じることの許可")] + [LangMsg(Languages.en, "Violent acts using this avatar")] + VIOLENT_USAGE, + + [LangMsg(Languages.ja, "このアバターを用いて性的表現を演じることの許可")] + [LangMsg(Languages.en, "Sexuality acts using this avatar")] + SEXUAL_USAGE, + + [LangMsg(Languages.ja, "商用利用の許可")] + [LangMsg(Languages.en, "For commercial use")] + COMMERCIAL_USAGE, + + [LangMsg(Languages.ja, "再配布・改変に関する許諾範囲")] + [LangMsg(Languages.en, "Redistribution / Modifications License")] + REDISTRIBUTION_MODIFICATIONS, + + // [LangMsg(Languages.ja, "")] + // [LangMsg(Languages.en, "")] + } + + static string Msg(MessageKeys key) + { + return M17N.Getter.Msg(key); + } + bool m_foldoutInfo = true; bool m_foldoutPermission = true; bool m_foldoutDistribution = true; @@ -164,17 +200,19 @@ namespace VRM m_reference.OnGUI(); } // EditorGUILayout.LabelField("License ", EditorStyles.boldLabel); - m_foldoutPermission = EditorGUILayout.Foldout(m_foldoutPermission, "Personation / Characterization Permission"); + m_foldoutPermission = EditorGUILayout.Foldout(m_foldoutPermission, Msg(MessageKeys.PERSONATION)); if (m_foldoutPermission) { - EditorGUILayout.PropertyField(m_AllowedUser, new GUIContent("A person who can perform with this avatar"), false); - EditorGUILayout.PropertyField(m_ViolentUssage, new GUIContent("Violent acts using this avatar")); - EditorGUILayout.PropertyField(m_SexualUssage, new GUIContent("Sexuality acts using this avatar")); - EditorGUILayout.PropertyField(m_CommercialUssage, new GUIContent("For commercial use")); + var backup = EditorGUIUtility.labelWidth; + RightFixedPropField(m_AllowedUser, Msg(MessageKeys.ALLOWED_USER)); + RightFixedPropField(m_ViolentUssage, Msg(MessageKeys.VIOLENT_USAGE)); + RightFixedPropField(m_SexualUssage, Msg(MessageKeys.SEXUAL_USAGE)); + RightFixedPropField(m_CommercialUssage, Msg(MessageKeys.COMMERCIAL_USAGE)); EditorGUILayout.PropertyField(m_OtherPermissionUrl, new GUIContent("Other License Url")); + EditorGUIUtility.labelWidth = backup; } - m_foldoutDistribution = EditorGUILayout.Foldout(m_foldoutDistribution, "Redistribution / Modifications License"); + m_foldoutDistribution = EditorGUILayout.Foldout(m_foldoutDistribution, Msg(MessageKeys.REDISTRIBUTION_MODIFICATIONS)); if (m_foldoutDistribution) { var licenseType = m_LicenseType; @@ -188,6 +226,27 @@ namespace VRM so.ApplyModifiedProperties(); } + static (Rect, Rect) FixedRight(Rect r, int width) + { + if (width > r.width) + { + width = (int)r.width; + } + return ( + new Rect(r.x, r.y, r.width - width, r.height), + new Rect(r.x + r.width - width, r.y, width, r.height) + ); + } + + static void RightFixedPropField(SerializedProperty prop, string label) + { + var r = GUILayoutUtility.GetRect(GUIContent.none, GUIStyle.none, GUILayout.Height(EditorGUIUtility.singleLineHeight)); + var (left, right) = FixedRight(r, 64); + // Debug.Log($"{left}, {right}"); + EditorGUI.LabelField(left, label); + EditorGUI.PropertyField(right, prop, new GUIContent(""), false); + } + private static Texture2D TextureField(string name, Texture2D texture, int size) { GUILayout.BeginHorizontal(); From d1661f177ea380b9a2f92c8916045400b2cb1f85 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 26 Aug 2020 15:59:34 +0900 Subject: [PATCH 6/6] OnInspectorGUI --- Assets/VRM/UniVRM/Editor/EditorLanguages.cs | 3 ++- .../UniVRM/Editor/Meta/VRMMetaObjectEditor.cs | 20 ++++--------------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/Assets/VRM/UniVRM/Editor/EditorLanguages.cs b/Assets/VRM/UniVRM/Editor/EditorLanguages.cs index b2cf23463..38c8ed01a 100644 --- a/Assets/VRM/UniVRM/Editor/EditorLanguages.cs +++ b/Assets/VRM/UniVRM/Editor/EditorLanguages.cs @@ -134,7 +134,8 @@ namespace VRM.M17N foreach (T value in Enum.GetValues(t)) { var match = GetAttribute(value, language); - map.Add(value, match != null ? match.Message : ""); + // Attribute。無かったら enum の ToString + map.Add(value, match != null ? match.Message : key.ToString()); } s_cache.Add(language, map); diff --git a/Assets/VRM/UniVRM/Editor/Meta/VRMMetaObjectEditor.cs b/Assets/VRM/UniVRM/Editor/Meta/VRMMetaObjectEditor.cs index 84e7c0f92..206ce5a2d 100644 --- a/Assets/VRM/UniVRM/Editor/Meta/VRMMetaObjectEditor.cs +++ b/Assets/VRM/UniVRM/Editor/Meta/VRMMetaObjectEditor.cs @@ -117,17 +117,6 @@ namespace VRM m_OtherLicenseUrl = serializedObject.FindProperty(nameof(m_target.OtherLicenseUrl)); } - public override void OnInspectorGUI() - { - serializedObject.Update(); - GUI.enabled = false; - EditorGUILayout.PropertyField(m_Script, true); - GUI.enabled = true; - - EditorGUILayout.Space(); - VRMMetaObjectGUI(serializedObject); - } - enum MessageKeys { [LangMsg(Languages.ja, "アバターの人格に関する許諾範囲")] @@ -166,11 +155,10 @@ namespace VRM bool m_foldoutInfo = true; bool m_foldoutPermission = true; bool m_foldoutDistribution = true; - void VRMMetaObjectGUI(SerializedObject so) - { - M17N.Getter.OnGuiSelectLang(); - so.Update(); + public override void OnInspectorGUI() + { + serializedObject.Update(); if (VRMVersion.IsNewer(m_exporterVersion.stringValue)) { @@ -223,7 +211,7 @@ namespace VRM } } - so.ApplyModifiedProperties(); + serializedObject.ApplyModifiedProperties(); } static (Rect, Rect) FixedRight(Rect r, int width)