Skip to content

Commit

Permalink
Merge pull request #601 from ousttrue/feature/tpose_button
Browse files Browse the repository at this point in the history
Feature/tpose button
  • Loading branch information
hiroj committed Nov 16, 2020
2 parents 60da512 + 743340e commit 82de5ea
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 20 deletions.
Expand Up @@ -25,6 +25,10 @@ public enum ValidationMessages
[LangMsg(Languages.en, "The model needs to face the positive Z-axis")]
FACE_Z_POSITIVE_DIRECTION,

[LangMsg(Languages.ja, "T-Pose にしてください")]
[LangMsg(Languages.en, "Set T-Pose")]
NOT_TPOSE,

[LangMsg(Languages.ja, "ExportRootの Animator に Avatar がありません")]
[LangMsg(Languages.en, "No Avatar in ExportRoot's Animator")]
NO_AVATAR_IN_ANIMATOR,
Expand All @@ -37,7 +41,7 @@ public enum ValidationMessages
[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.ja, "Jaw(顎)ボーンが含まれています。意図していない場合は設定解除をおすすめします。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,
}
Expand Down Expand Up @@ -150,15 +154,23 @@ public static IEnumerable<Validation> Validate(GameObject ExportRoot)
}
}

{
var lu = animator.GetBoneTransform(HumanBodyBones.LeftUpperArm);
var ll = animator.GetBoneTransform(HumanBodyBones.LeftLowerArm);
var ru = animator.GetBoneTransform(HumanBodyBones.RightUpperArm);
var rl = animator.GetBoneTransform(HumanBodyBones.RightLowerArm);
if (Vector3.Dot((ll.position - lu.position).normalized, Vector3.left) < 0.8f
|| Vector3.Dot((rl.position - ru.position).normalized, Vector3.right) < 0.8f)
{
yield return Validation.Error(ValidationMessages.NOT_TPOSE.Msg());
}
}

var jaw = animator.GetBoneTransform(HumanBodyBones.Jaw);
if (jaw != null)
{
yield return Validation.Warning(ValidationMessages.JAW_BONE_IS_INCLUDED.Msg());
}
else
{
yield return Validation.Info("Animator OK");
}
}
}
}
2 changes: 2 additions & 0 deletions Assets/VRM/UniVRM/Editor/Format/VRMExportSettings.cs
Expand Up @@ -48,5 +48,7 @@ public class VRMExportSettings : ScriptableObject
UseSparseAccessorForMorphTarget = UseSparseAccessor,
ExportOnlyBlendShapePosition = OnlyBlendshapePosition,
};

public GameObject Root { get; set; }
}
}
46 changes: 37 additions & 9 deletions Assets/VRM/UniVRM/Editor/Format/VRMExportSettingsEditor.cs
Expand Up @@ -36,12 +36,6 @@ public void Draw()
}
}

/// <summary>
/// エクスポート時に強制的にT-Pose化する
/// </summary>
[Tooltip("Option")]
public bool ForceTPose = false;

/// <summary>
/// エクスポート時にヒエラルキーの正規化を実施する
/// </summary>
Expand Down Expand Up @@ -78,7 +72,6 @@ public void Draw()
[Tooltip("Remove blendShapeClip that preset is Unknown")]
public bool ReduceBlendshapeClip = false;

CheckBoxProp m_forceTPose;
CheckBoxProp m_poseFreeze;
CheckBoxProp m_useSparseAccessor;
CheckBoxProp m_onlyBlendShapePosition;
Expand Down Expand Up @@ -123,11 +116,22 @@ enum Options
[LangMsg(Languages.ja, "エクスポートに頂点カラーを含めない")]
[LangMsg(Languages.en, "Vertex color will not be exported")]
REMOVE_VERTEX_COLOR,

[LangMsg(Languages.ja, "このボタンで自動で T-Pose にできます。手動で T-Pose にしたり、ボタンの後で手直ししてもOKです。")]
[LangMsg(Languages.en, "You can automatically set the T pose with this button. You can change it manually to T-pose or after the button.")]
ENALBE_TPOSE_BUTTON,

[LangMsg(Languages.ja, "このボタンで自動で T-Pose にできます。prefab には実行できません。")]
[LangMsg(Languages.en, "You can set the T pose automatically with this button. It cannot be run on prefabs.")]
DISABLE_TPOSE_BUTTON,

[LangMsg(Languages.ja, "T-Pose にする")]
[LangMsg(Languages.en, "Make T-Pose")]
DO_TPOSE,
}

private void OnEnable()
{
m_forceTPose = new CheckBoxProp(serializedObject.FindProperty(nameof(ForceTPose)), Options.FORCE_T_POSE);
m_poseFreeze = new CheckBoxProp(serializedObject.FindProperty(nameof(PoseFreeze)), Options.NORMALIZE);
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);
Expand All @@ -137,9 +141,33 @@ private void OnEnable()

public override void OnInspectorGUI()
{
GUILayout.Space(20);
var settings = (VRMExportSettings)target;
var root = settings.Root;
var backup = GUI.enabled;
GUI.enabled = root.scene.IsValid();
if (GUI.enabled)
{
EditorGUILayout.HelpBox(Options.ENALBE_TPOSE_BUTTON.Msg(), MessageType.Info);
}
else
{
EditorGUILayout.HelpBox(Options.DISABLE_TPOSE_BUTTON.Msg(), MessageType.Warning);
}
if (GUILayout.Button(Options.DO_TPOSE.Msg()))
{
if (settings.Root)
{
VRMBoneNormalizer.EnforceTPose(settings.Root);
}
}
GUI.enabled = backup;
GUILayout.Space(20);

// ToDo: 任意の BlendShapeClip を適用する

EditorGUIUtility.labelWidth = 160;
serializedObject.Update();
m_forceTPose.Draw();
m_poseFreeze.Draw();
m_useSparseAccessor.Draw();
m_onlyBlendShapePosition.Draw();
Expand Down
62 changes: 58 additions & 4 deletions Assets/VRM/UniVRM/Editor/Format/VRMExporterWizard.cs
Expand Up @@ -23,6 +23,7 @@ enum Tabs
{
Meta,
Mesh,
BlendShape,
ExportSettings,
}
Tabs _tab;
Expand Down Expand Up @@ -301,18 +302,71 @@ bool DrawWizardGUI()
m_metaEditor.OnInspectorGUI();
break;

case Tabs.ExportSettings:
m_settingsInspector.OnInspectorGUI();
break;

case Tabs.Mesh:
m_meshesInspector.OnInspectorGUI();
break;

case Tabs.BlendShape:
if (m_state.ExportRoot)
{
OnBlendShapeGUI(m_state.ExportRoot.GetComponent<VRMBlendShapeProxy>());
}
break;

case Tabs.ExportSettings:
m_settings.Root = m_state.ExportRoot;
m_settingsInspector.OnInspectorGUI();
break;
}

return true;
}

BlendShapeMerger m_merger;

int m_selected = 0;
void OnBlendShapeGUI(VRMBlendShapeProxy proxy)
{
if (!m_state.ExportRoot.scene.IsValid())
{
EditorGUILayout.HelpBox("prefab は操作できません", MessageType.Warning);
return;
}

if (!proxy)
{
return;
}
var avatar = proxy.BlendShapeAvatar;
if (!avatar)
{
return;
}

m_merger = new BlendShapeMerger(avatar.Clips, proxy.transform);


GUILayout.Space(20);

EditorGUILayout.HelpBox("シーン上のExportRootにBlendShapeを適用します。Exportすると適用された状態がBakeされます。", MessageType.Info);

var options = avatar.Clips.Select(x => x.ToString()).ToArray();
m_selected = EditorGUILayout.Popup("select blendshape", m_selected, options);

if (GUILayout.Button("選択されたBlendShapeを適用する"))
{
m_merger.SetValues(avatar.Clips.Select((x, i) => new KeyValuePair<BlendShapeKey, float>(x.Key, i == m_selected ? 1 : 0)));
m_merger.Apply();
m_settings.PoseFreeze = true;
}

if (GUILayout.Button("BlendShapeをClearする"))
{
m_merger.SetValues(avatar.Clips.Select(x => new KeyValuePair<BlendShapeKey, float>(x.Key, 0)));
m_merger.Apply();
}
}

const string EXTENSION = ".vrm";
private static string m_lastExportDir;
static void OnExportClicked(GameObject root, VRMMetaObject meta, VRMExportSettings settings, VRMExportMeshes meshes)
Expand Down
2 changes: 1 addition & 1 deletion Assets/VRM/UniVRM/Scripts/BlendShape/BlendShapeMerger.cs
Expand Up @@ -11,7 +11,7 @@ namespace VRM
/// <summary>
/// ブレンドシェイプを蓄えてまとめて適用するクラス
/// </summary>
class BlendShapeMerger
public class BlendShapeMerger
{
/// <summary>
/// Key からBlendShapeClipを得る
Expand Down
Expand Up @@ -9,7 +9,7 @@ namespace VRM
{
public static class VRMBoneNormalizer
{
static void EnforceTPose(GameObject go)
public static void EnforceTPose(GameObject go)
{
var animator = go.GetComponent<Animator>();
if (animator == null)
Expand Down

0 comments on commit 82de5ea

Please sign in to comment.