mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-05-14 14:29:52 -05:00
commit
6e5388361b
179
Assets/VRM/UniVRM/Editor/EditorLanguages.cs
Normal file
179
Assets/VRM/UniVRM/Editor/EditorLanguages.cs
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
|
||||
namespace VRM.M17N
|
||||
{
|
||||
/// <summary>
|
||||
/// 多言語対応
|
||||
/// </summary>
|
||||
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<T> where T : Enum
|
||||
{
|
||||
static Dictionary<Languages, Dictionary<T, string>> s_cache = new Dictionary<Languages, Dictionary<T, string>>();
|
||||
|
||||
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<T, string> map))
|
||||
{
|
||||
map = new Dictionary<T, string>();
|
||||
|
||||
var t = typeof(T);
|
||||
foreach (T value in Enum.GetValues(t))
|
||||
{
|
||||
var match = GetAttribute(value, language);
|
||||
// Attribute。無かったら enum の ToString
|
||||
map.Add(value, match != null ? match.Message : key.ToString());
|
||||
}
|
||||
|
||||
s_cache.Add(language, map);
|
||||
}
|
||||
return map[key];
|
||||
}
|
||||
}
|
||||
public static class Getter
|
||||
{
|
||||
const string LANG_KEY = "VRM_LANG";
|
||||
|
||||
static Languages? m_lang;
|
||||
|
||||
public static Languages Lang
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!m_lang.HasValue)
|
||||
{
|
||||
m_lang = EnumUtil.TryParseOrDefault<Languages>(EditorPrefs.GetString(LANG_KEY, default(Languages).ToString()));
|
||||
}
|
||||
return m_lang.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public static string Msg<T>(T key) where T : Enum
|
||||
{
|
||||
return M17N.MsgCache<T>.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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/VRM/UniVRM/Editor/EditorLanguages.cs.meta
Normal file
11
Assets/VRM/UniVRM/Editor/EditorLanguages.cs.meta
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7829d135d35830f4bb9235eb10b3de1f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -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<string> Description;
|
||||
|
||||
public CheckBoxProp(SerializedProperty property, string desc)
|
||||
public CheckBoxProp(SerializedProperty property, Func<string> 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()
|
||||
|
|
|
|||
|
|
@ -153,6 +153,11 @@ namespace VRM
|
|||
return true;
|
||||
}
|
||||
|
||||
static string Msg(VRMExporterWizardMessages key)
|
||||
{
|
||||
return M17N.Getter.Msg(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// エクスポート可能か検証する
|
||||
/// </summary>
|
||||
|
|
@ -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<VRMBlendShapeProxy>() == null)
|
||||
{
|
||||
yield return Validation.Error(Msg.NEEDS_VRM_BLENDSHAPE_PROXY);
|
||||
yield return Validation.Error(Msg(VRMExporterWizardMessages.NEEDS_VRM_BLENDSHAPE_PROXY));
|
||||
}
|
||||
|
||||
var vertexColor = ExportRoot.GetComponentsInChildren<SkinnedMeshRenderer>().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<Renderer>();
|
||||
|
|
@ -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<string>();
|
||||
|
|
@ -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<VRMMeta>();
|
||||
|
|
@ -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<MeshFilter>();
|
||||
|
|
@ -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<SkinnedMeshRenderer>();
|
||||
|
|
@ -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,9 +296,8 @@ namespace VRM
|
|||
m_Inspector = Editor.CreateEditor(m_settings);
|
||||
}
|
||||
|
||||
m_lang = EnumUtil.TryParseOrDefault<VRMExporterWizardMessages.Languages>(EditorPrefs.GetString(LANG_KEY, default(VRMExporterWizardMessages.Languages).ToString()));
|
||||
M17N.Getter.OnGuiSelectLang();
|
||||
}
|
||||
const string LANG_KEY = "VRM_LANG";
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
|
|
@ -344,11 +348,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,12 +359,7 @@ 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());
|
||||
}
|
||||
M17N.Getter.OnGuiSelectLang();
|
||||
|
||||
EditorGUILayout.LabelField("ExportRoot");
|
||||
{
|
||||
|
|
@ -382,24 +376,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<Renderer>();
|
||||
if (renderers.All(x => !EnableRenderer(x)))
|
||||
{
|
||||
Validation.Error(Msg.NO_ACTIVE_MESH).DrawGUI();
|
||||
Validation.Error(Msg(VRMExporterWizardMessages.NO_ACTIVE_MESH)).DrawGUI();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -411,14 +405,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 +426,7 @@ namespace VRM
|
|||
var animator = ExportRoot.GetComponent<Animator>();
|
||||
if (animator == null)
|
||||
{
|
||||
Validation.Error(Msg.NO_ANIMATOR).DrawGUI();
|
||||
Validation.Error(Msg(VRMExporterWizardMessages.NO_ANIMATOR)).DrawGUI();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -441,30 +435,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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,84 +1,80 @@
|
|||
using System.Collections.Generic;
|
||||
using VRM.M17N;
|
||||
|
||||
namespace VRM
|
||||
{
|
||||
/// <summary>
|
||||
/// エクスポートダイアログ用の簡易なメッセージカタログ
|
||||
/// </summary>
|
||||
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<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: ",
|
||||
}
|
||||
},
|
||||
};
|
||||
[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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,20 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using VRM.M17N;
|
||||
|
||||
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,129 +32,207 @@ namespace VRM
|
|||
// return old != m_prop.stringValue;
|
||||
}
|
||||
}
|
||||
List<KeyValuePair<string, CustomProperty>> m_customPropMap = new List<KeyValuePair<string, CustomProperty>>();
|
||||
|
||||
Dictionary<string, SerializedProperty> m_propMap = new Dictionary<string, SerializedProperty>();
|
||||
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;
|
||||
|
||||
static string RequiredMessage(string name)
|
||||
{
|
||||
m_propMap.Clear();
|
||||
m_customPropMap.Clear();
|
||||
if (so == null)
|
||||
switch (M17N.Getter.Lang)
|
||||
{
|
||||
return;
|
||||
}
|
||||
case M17N.Languages.ja:
|
||||
return $"必須項目。{name} を入力してください";
|
||||
|
||||
for (var it = so.GetIterator(); it.NextVisible(true);)
|
||||
{
|
||||
switch (it.name)
|
||||
{
|
||||
case "m_Script":
|
||||
break;
|
||||
case M17N.Languages.en:
|
||||
return $"{name} is required";
|
||||
|
||||
case "Title":
|
||||
case "Version":
|
||||
case "Author":
|
||||
m_customPropMap.Add(new KeyValuePair<string, CustomProperty>(it.name, new CustomProperty(so.FindProperty(it.name), prop =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(prop.stringValue))
|
||||
{
|
||||
return ($"必須項目。{prop.name} を入力してください", MessageType.Error);
|
||||
}
|
||||
return ("", MessageType.None);
|
||||
})));
|
||||
break;
|
||||
|
||||
case "ContactInformation":
|
||||
case "Reference":
|
||||
m_customPropMap.Add(new KeyValuePair<string, CustomProperty>(it.name,
|
||||
new CustomProperty(so.FindProperty(it.name), prop =>
|
||||
{
|
||||
return ("", MessageType.None);
|
||||
})));
|
||||
break;
|
||||
|
||||
default:
|
||||
m_propMap.Add(it.name, so.FindProperty(it.name));
|
||||
break;
|
||||
}
|
||||
//Debug.LogFormat("{0}", it.name);
|
||||
default:
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
// m_ScriptProp = serializedObject.FindProperty("m_Script");
|
||||
InitMap(serializedObject);
|
||||
}
|
||||
m_target = (VRMMetaObject)target;
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
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 (RequiredMessage(prop.name), MessageType.Error);
|
||||
}
|
||||
return ("", MessageType.None);
|
||||
});
|
||||
m_version = new ValidateProperty(serializedObject.FindProperty(nameof(m_target.Version)), prop =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(prop.stringValue))
|
||||
{
|
||||
return (RequiredMessage(prop.name), MessageType.Error);
|
||||
}
|
||||
return ("", MessageType.None);
|
||||
});
|
||||
m_author = new ValidateProperty(serializedObject.FindProperty(nameof(m_target.Author)), prop =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(prop.stringValue))
|
||||
{
|
||||
return (RequiredMessage(prop.name), MessageType.Error);
|
||||
}
|
||||
return ("", MessageType.None);
|
||||
});
|
||||
m_contact = new ValidateProperty(serializedObject.FindProperty(nameof(m_target.ContactInformation)), prop =>
|
||||
{
|
||||
return ("", MessageType.None);
|
||||
});
|
||||
m_reference = new ValidateProperty(serializedObject.FindProperty(nameof(m_target.Reference)), prop =>
|
||||
{
|
||||
return ("", MessageType.None);
|
||||
});
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
enum MessageKeys
|
||||
{
|
||||
serializedObject.Update();
|
||||
// GUI.enabled = false;
|
||||
// EditorGUILayout.PropertyField(m_ScriptProp, true);
|
||||
// GUI.enabled = true;
|
||||
[LangMsg(Languages.ja, "アバターの人格に関する許諾範囲")]
|
||||
[LangMsg(Languages.en, "Personation / Characterization Permission")]
|
||||
PERSONATION,
|
||||
|
||||
EditorGUILayout.Space();
|
||||
VRMMetaObjectGUI(serializedObject);
|
||||
[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;
|
||||
void VRMMetaObjectGUI(SerializedObject so)
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
InitMap(so);
|
||||
if (m_propMap == null || m_propMap.Count == 0) return;
|
||||
serializedObject.Update();
|
||||
|
||||
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);
|
||||
|
||||
m_foldoutPermission = EditorGUILayout.Foldout(m_foldoutPermission, "Personation / Characterization Permission");
|
||||
// EditorGUILayout.LabelField("License ", EditorStyles.boldLabel);
|
||||
m_foldoutPermission = EditorGUILayout.Foldout(m_foldoutPermission, Msg(MessageKeys.PERSONATION));
|
||||
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"));
|
||||
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_propMap["LicenseType"];
|
||||
var licenseType = m_LicenseType;
|
||||
EditorGUILayout.PropertyField(licenseType);
|
||||
if ((LicenseType)licenseType.intValue == LicenseType.Other)
|
||||
{
|
||||
EditorGUILayout.PropertyField(m_propMap["OtherLicenseUrl"]);
|
||||
EditorGUILayout.PropertyField(m_OtherLicenseUrl);
|
||||
}
|
||||
}
|
||||
|
||||
so.ApplyModifiedProperties();
|
||||
serializedObject.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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user