mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-05-13 22:09:53 -05:00
add language support in export dialog
This commit is contained in:
parent
3bbeb96fbd
commit
d45ebcdcb9
|
|
@ -86,25 +86,34 @@ namespace VRM
|
|||
private void OnEnable()
|
||||
{
|
||||
m_forceTPose = new CheckBoxProp(serializedObject.FindProperty(nameof(ForceTPose)),
|
||||
"エクスポート時に強制的にT-Pose化する。これを使わずに手動でT-Poseを作っても問題ありません");
|
||||
"エクスポート時に強制的に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を使う");
|
||||
"エクスポート時に新しいJsonSerializerを使う \n" +
|
||||
"The new version of JsonSerializer for model export");
|
||||
m_useSparseAccessor = new CheckBoxProp(serializedObject.FindProperty(nameof(UseSparseAccessor)),
|
||||
"BlendShapeの容量を GLTF の Sparse Accessor 機能で削減する。修正中: UniGLTF以外でロードできません");
|
||||
"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 以前ではロードがエラーになるのに注意してください");
|
||||
"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をエクスポートに含めない");
|
||||
"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をエクスポートに含めない");
|
||||
"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");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
EditorGUIUtility.labelWidth = 160;
|
||||
serializedObject.Update();
|
||||
m_forceTPose.Draw();
|
||||
m_poseFreeze.Draw();
|
||||
|
|
|
|||
|
|
@ -152,24 +152,24 @@ namespace VRM
|
|||
|
||||
if (DuplicateBoneNameExists())
|
||||
{
|
||||
yield return Validation.Warning("There is a bone with the same name in the hierarchy. If exported, these bones will be automatically renamed.");
|
||||
yield return Validation.Warning(Msg.DUPLICATE_BONE_NAME_EXISTS);
|
||||
}
|
||||
|
||||
if (m_settings.ReduceBlendshape && ExportRoot.GetComponent<VRMBlendShapeProxy>() == null)
|
||||
{
|
||||
yield return Validation.Error("ReduceBlendshapeSize needs VRMBlendShapeProxy. You need to convert to VRM once.");
|
||||
yield return Validation.Error(Msg.NEEDS_VRM_BLENDSHAPE_PROXY);
|
||||
}
|
||||
|
||||
var vertexColor = ExportRoot.GetComponentsInChildren<SkinnedMeshRenderer>().Any(x => x.sharedMesh.colors.Length > 0);
|
||||
if (vertexColor)
|
||||
{
|
||||
yield return Validation.Warning("This model contains vertex color");
|
||||
yield return Validation.Warning(Msg.VERTEX_COLOR_IS_INCLUDED);
|
||||
}
|
||||
|
||||
var renderers = ExportRoot.GetComponentsInChildren<Renderer>();
|
||||
if (renderers.All(x => !x.gameObject.activeInHierarchy))
|
||||
{
|
||||
yield return Validation.Error("No active mesh");
|
||||
yield return Validation.Error(Msg.NO_ACTIVE_MESH);
|
||||
}
|
||||
|
||||
var materials = renderers.SelectMany(x => x.sharedMaterials).Distinct();
|
||||
|
|
@ -193,15 +193,13 @@ namespace VRM
|
|||
continue;
|
||||
}
|
||||
|
||||
yield return Validation.Warning(string.Format("{0}: unknown shader '{1}' is used. this will export as `Standard` fallback",
|
||||
material.name,
|
||||
material.shader.name));
|
||||
yield return Validation.Warning($"Material: {material.name}. Unknown Shader: \"{material.shader.name}\" is used. {Msg.UNKNOWN_SHADER}");
|
||||
}
|
||||
|
||||
foreach (var material in materials)
|
||||
{
|
||||
if (IsFileNameLengthTooLong(material.name))
|
||||
yield return Validation.Error(string.Format("FileName '{0}' is too long. ", material.name));
|
||||
yield return Validation.Error(Msg.FILENAME_TOO_LONG + material.name);
|
||||
}
|
||||
|
||||
var textureNameList = new List<string>();
|
||||
|
|
@ -226,7 +224,7 @@ namespace VRM
|
|||
foreach (var textureName in textureNameList)
|
||||
{
|
||||
if (IsFileNameLengthTooLong(textureName))
|
||||
yield return Validation.Error(string.Format("FileName '{0}' is too long. ", textureName));
|
||||
yield return Validation.Error(Msg.FILENAME_TOO_LONG + textureName);
|
||||
}
|
||||
|
||||
var vrmMeta = ExportRoot.GetComponent<VRMMeta>();
|
||||
|
|
@ -234,7 +232,7 @@ namespace VRM
|
|||
{
|
||||
var thumbnailName = vrmMeta.Meta.Thumbnail.name;
|
||||
if (IsFileNameLengthTooLong(thumbnailName))
|
||||
yield return Validation.Error(string.Format("FileName '{0}' is too long. ", thumbnailName));
|
||||
yield return Validation.Error(Msg.FILENAME_TOO_LONG + thumbnailName);
|
||||
}
|
||||
|
||||
var meshFilters = ExportRoot.GetComponentsInChildren<MeshFilter>();
|
||||
|
|
@ -242,7 +240,7 @@ namespace VRM
|
|||
foreach (var meshName in meshesName)
|
||||
{
|
||||
if (IsFileNameLengthTooLong(meshName))
|
||||
yield return Validation.Error(string.Format("FileName '{0}' is too long. ", meshName));
|
||||
yield return Validation.Error(Msg.FILENAME_TOO_LONG + meshName);
|
||||
}
|
||||
|
||||
var skinnedmeshRenderers = ExportRoot.GetComponentsInChildren<SkinnedMeshRenderer>();
|
||||
|
|
@ -250,7 +248,7 @@ namespace VRM
|
|||
foreach (var skinnedmeshName in skinnedmeshesName)
|
||||
{
|
||||
if (IsFileNameLengthTooLong(skinnedmeshName))
|
||||
yield return Validation.Error(string.Format("FileName '{0}' is too long. ", skinnedmeshName));
|
||||
yield return Validation.Error(Msg.FILENAME_TOO_LONG + skinnedmeshName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -283,7 +281,10 @@ namespace VRM
|
|||
{
|
||||
m_Inspector = Editor.CreateEditor(m_settings);
|
||||
}
|
||||
|
||||
m_lang = EnumUtil.TryParseOrDefault<VRMExporterWizardMessages.Languages>(EditorPrefs.GetString(LANG_KEY, default(VRMExporterWizardMessages.Languages).ToString()));
|
||||
}
|
||||
const string LANG_KEY = "VRM_LANG";
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
|
|
@ -334,7 +335,11 @@ 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)
|
||||
|
|
@ -345,6 +350,14 @@ namespace VRM
|
|||
|
||||
EditorGUIUtility.labelWidth = 150;
|
||||
|
||||
// lang
|
||||
var lang = (VRMExporterWizardMessages.Languages)EditorGUILayout.EnumPopup("lang", m_lang);
|
||||
if (lang != m_lang)
|
||||
{
|
||||
m_lang = lang;
|
||||
EditorPrefs.SetString(LANG_KEY, m_lang.ToString());
|
||||
}
|
||||
|
||||
EditorGUILayout.LabelField("ExportRoot");
|
||||
var root = (GameObject)EditorGUILayout.ObjectField(ExportRoot, typeof(GameObject), true);
|
||||
UpdateRoot(root);
|
||||
|
|
@ -358,24 +371,24 @@ namespace VRM
|
|||
//
|
||||
if (root == null)
|
||||
{
|
||||
Validation.Error("ExportRootをセットしてください").DrawGUI();
|
||||
Validation.Error(Msg.ROOT_EXISTS).DrawGUI();
|
||||
return;
|
||||
}
|
||||
if (root.transform.parent != null)
|
||||
{
|
||||
Validation.Error("ExportRootに親はオブジェクトは持てません").DrawGUI();
|
||||
Validation.Error(Msg.NO_PARENT).DrawGUI();
|
||||
return;
|
||||
}
|
||||
if (root.transform.localRotation != Quaternion.identity || root.transform.localScale != Vector3.one)
|
||||
{
|
||||
Validation.Error("ExportRootに回転・拡大縮小は持てません。子階層で回転・拡大縮小してください").DrawGUI();
|
||||
Validation.Error(Msg.ROOT_WITHOUT_ROTATION_AND_SCALING_CHANGED).DrawGUI();
|
||||
return;
|
||||
}
|
||||
if (!root.scene.IsValid())
|
||||
{
|
||||
// Prefab でシーンに出していないものを判定したい
|
||||
// FIXME: もっと適切な判定があればそれに
|
||||
Validation.Error("シーンに出していない Prefab はエクスポートできません(細かい挙動が違い、想定外の動作をところがあるため)。シーンに展開してからエクスポートしてください").DrawGUI();
|
||||
Validation.Error(Msg.PREFAB_CANNOT_EXPORT).DrawGUI();
|
||||
return;
|
||||
}
|
||||
if (HasRotationOrScale(ExportRoot))
|
||||
|
|
@ -386,14 +399,14 @@ namespace VRM
|
|||
}
|
||||
else
|
||||
{
|
||||
Validation.Warning("回転・拡大縮小を持つノードが含まれています。正規化が必用です。Setting の PoseFreeze を有効にしてください").DrawGUI();
|
||||
Validation.Warning(Msg.ROTATION_OR_SCALEING_INCLUDED_IN_NODE).DrawGUI();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_settings.PoseFreeze)
|
||||
{
|
||||
Validation.Warning("正規化済みです。Setting の PoseFreeze は不要です").DrawGUI();
|
||||
Validation.Warning(Msg.IS_POSE_FREEZE_DONE).DrawGUI();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -407,7 +420,7 @@ namespace VRM
|
|||
var animator = root.GetComponent<Animator>();
|
||||
if (animator == null)
|
||||
{
|
||||
Validation.Error("ExportRootに Animator がありません").DrawGUI();
|
||||
Validation.Error(Msg.NO_ANIMATOR).DrawGUI();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -416,30 +429,30 @@ namespace VRM
|
|||
var f = GetForward(l, r);
|
||||
if (Vector3.Dot(f, Vector3.forward) < 0.8f)
|
||||
{
|
||||
Validation.Error("Z+ 向きにしてください").DrawGUI();
|
||||
Validation.Error(Msg.FACE_Z_POSITIVE_DIRECTION).DrawGUI();
|
||||
return;
|
||||
}
|
||||
|
||||
var avatar = animator.avatar;
|
||||
if (avatar == null)
|
||||
{
|
||||
Validation.Error("ExportRootの Animator に Avatar がありません").DrawGUI();
|
||||
Validation.Error(Msg.NO_AVATAR_IN_ANIMATOR).DrawGUI();
|
||||
return;
|
||||
}
|
||||
if (!avatar.isValid)
|
||||
{
|
||||
Validation.Error("ExportRootの Animator.Avatar が不正です").DrawGUI();
|
||||
Validation.Error(Msg.AVATAR_IS_NOT_VALID).DrawGUI();
|
||||
return;
|
||||
}
|
||||
if (!avatar.isHuman)
|
||||
{
|
||||
Validation.Error("ExportRootの Animator.Avatar がヒューマノイドではありません。FBX importer の Rig で設定してください").DrawGUI();
|
||||
Validation.Error(Msg.AVATAR_IS_NOT_HUMANOID).DrawGUI();
|
||||
return;
|
||||
}
|
||||
var jaw = animator.GetBoneTransform(HumanBodyBones.Jaw);
|
||||
if (jaw != null)
|
||||
{
|
||||
Validation.Warning("Jaw bone is included. It may not be what you intended. Please check the humanoid avatar setting screen").DrawGUI();
|
||||
Validation.Warning(Msg.JAW_BONE_IS_INCLUDED).DrawGUI();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
84
Assets/VRM/UniVRM/Editor/Format/VRMExporterWizardMessages.cs
Normal file
84
Assets/VRM/UniVRM/Editor/Format/VRMExporterWizardMessages.cs
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace VRM
|
||||
{
|
||||
/// <summary>
|
||||
/// エクスポートダイアログ用の簡易なメッセージカタログ
|
||||
/// </summary>
|
||||
public static class VRMExporterWizardMessages
|
||||
{
|
||||
public enum Languages
|
||||
{
|
||||
ja,
|
||||
en,
|
||||
}
|
||||
|
||||
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<Languages, LangMessages> M17N = new Dictionary<Languages, LangMessages>
|
||||
{
|
||||
{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: ",
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 515984b15b5b5bf4baca4fa2d6344fcf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Loading…
Reference in New Issue
Block a user