InternalTPose.cs

This commit is contained in:
ousttrue 2021-04-12 21:49:49 +09:00
parent 78cda85380
commit 59eb769cd6
3 changed files with 121 additions and 21 deletions

View File

@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using UniGLTF;
using UnityEngine;
namespace VRM
{
public static class InternalTPose
{
struct TRS
{
public Vector3 T;
public Quaternion R;
public Vector3 S;
public void Apply(Transform t)
{
t.localPosition = T;
t.localRotation = R;
t.localScale = S;
}
public static TRS From(Transform t)
{
return new TRS
{
T = t.localPosition,
R = t.localRotation,
S = t.localScale,
};
}
}
static void BuildMap(Transform t, Dictionary<string, TRS> map, Transform root = null)
{
if (root == null)
{
root = t;
}
map.Add(t.RelativePathFrom(root), TRS.From(t));
foreach (Transform child in t)
{
BuildMap(child, map, root);
}
}
static void ApplyMap(Transform t, Dictionary<string, TRS> map, Transform root = null)
{
if (root == null)
{
root = t;
}
map[t.RelativePathFrom(root)].Apply(t);
foreach (Transform child in t)
{
ApplyMap(child, map, root);
}
}
public static bool TrySampleBindPose(GameObject go)
{
// https://forum.unity.com/threads/mesh-bindposes.383752/
var type = Type.GetType("UnityEditor.AvatarSetupTool, UnityEditor");
if (type != null)
{
var info = type.GetMethod("SampleBindPose", BindingFlags.Static | BindingFlags.Public);
if (info != null)
{
// prefab cause error message. create copy
var clone = GameObject.Instantiate(go);
try
{
info.Invoke(null, new object[] { clone });
var map = new Dictionary<string, TRS>();
BuildMap(clone.transform, map);
ApplyMap(go.transform, map);
}
finally
{
GameObject.DestroyImmediate(clone);
}
return true;
}
}
return false;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 42e52c1a93301da4eb0435ed00bdf8c4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -4,6 +4,9 @@ using UnityEditor;
using UnityEngine;
using MeshUtility.M17N;
using System.Reflection;
using System.Linq;
using System.Collections.Generic;
using UniGLTF;
namespace VRM
{
@ -49,7 +52,7 @@ namespace VRM
return MeshUtility.M17N.Getter.Msg(key);
}
enum Options
public 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")]
@ -110,23 +113,6 @@ namespace VRM
m_divideVertexBuffer = new CheckBoxProp(serializedObject.FindProperty(nameof(VRMExportSettings.DivideVertexBuffer)), Options.DIVIDE_VERTEX_BUFFER);
}
static bool TrySampleBindPose(GameObject go)
{
// https://forum.unity.com/threads/mesh-bindposes.383752/
var type = Type.GetType("UnityEditor.AvatarSetupTool, UnityEditor");
if (type != null)
{
var info = type.GetMethod("SampleBindPose", BindingFlags.Static | BindingFlags.Public);
if (info != null)
{
var clone = GameObject.Instantiate(go);
info.Invoke(null, new object[] { clone });
return true;
}
}
return false;
}
public override void OnInspectorGUI()
{
@ -143,19 +129,26 @@ namespace VRM
{
EditorGUILayout.HelpBox(Options.DISABLE_TPOSE_BUTTON.Msg(), MessageType.Warning);
}
if (GUILayout.Button(Options.DO_TPOSE.Msg()))
//
// T-Pose
//
if (GUILayout.Button(VRMExportSettingsEditor.Options.DO_TPOSE.Msg()))
{
if (settings.Root != null)
{
// fallback
Undo.RecordObjects(settings.Root.GetComponentsInChildren<Transform>(), "tpose");
VRMBoneNormalizer.EnforceTPose(settings.Root);
}
}
if (GUILayout.Button(Options.DO_TPOSE.Msg() + "(internal)"))
if (GUILayout.Button(VRMExportSettingsEditor.Options.DO_TPOSE.Msg() + "(internal)"))
{
if (settings.Root != null)
{
if (TrySampleBindPose(settings.Root))
Undo.RecordObjects(settings.Root.GetComponentsInChildren<Transform>(), "tpose.internal");
if (InternalTPose.TrySampleBindPose(settings.Root))
{
// done
}
@ -165,6 +158,7 @@ namespace VRM
}
}
}
GUI.enabled = backup;
GUILayout.Space(20);