mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-05-12 05:24:14 -05:00
Merge pull request #541 from ousttrue/feature/backport_humanoid
1.0 からバックポート。こっちで管理する。
This commit is contained in:
commit
b0305b3644
324
Assets/MeshUtility/Editor/HumanoidEditor.cs
Normal file
324
Assets/MeshUtility/Editor/HumanoidEditor.cs
Normal file
|
|
@ -0,0 +1,324 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
namespace MeshUtility
|
||||
{
|
||||
[CustomEditor(typeof(Humanoid))]
|
||||
public class HumanoidEditor : Editor
|
||||
{
|
||||
const int LABEL_WIDTH = 100;
|
||||
|
||||
Humanoid m_target;
|
||||
|
||||
SerializedProperty m_Hips;
|
||||
#region leg
|
||||
SerializedProperty m_LeftUpperLeg;
|
||||
SerializedProperty m_RightUpperLeg;
|
||||
SerializedProperty m_LeftLowerLeg;
|
||||
SerializedProperty m_RightLowerLeg;
|
||||
SerializedProperty m_LeftFoot;
|
||||
SerializedProperty m_RightFoot;
|
||||
SerializedProperty m_LeftToes;
|
||||
SerializedProperty m_RightToes;
|
||||
|
||||
#endregion
|
||||
|
||||
#region spine
|
||||
SerializedProperty m_Spine;
|
||||
SerializedProperty m_Chest;
|
||||
SerializedProperty m_UpperChest;
|
||||
SerializedProperty m_Neck;
|
||||
SerializedProperty m_Head;
|
||||
SerializedProperty m_LeftEye;
|
||||
SerializedProperty m_RightEye;
|
||||
SerializedProperty m_Jaw;
|
||||
|
||||
#endregion
|
||||
|
||||
#region arm
|
||||
SerializedProperty m_LeftShoulder;
|
||||
SerializedProperty m_RightShoulder;
|
||||
SerializedProperty m_LeftUpperArm;
|
||||
SerializedProperty m_RightUpperArm;
|
||||
SerializedProperty m_LeftLowerArm;
|
||||
SerializedProperty m_RightLowerArm;
|
||||
SerializedProperty m_LeftHand;
|
||||
SerializedProperty m_RightHand;
|
||||
|
||||
#endregion
|
||||
|
||||
#region fingers
|
||||
SerializedProperty m_LeftThumbProximal;
|
||||
SerializedProperty m_LeftThumbIntermediate;
|
||||
SerializedProperty m_LeftThumbDistal;
|
||||
SerializedProperty m_LeftIndexProximal;
|
||||
SerializedProperty m_LeftIndexIntermediate;
|
||||
SerializedProperty m_LeftIndexDistal;
|
||||
SerializedProperty m_LeftMiddleProximal;
|
||||
SerializedProperty m_LeftMiddleIntermediate;
|
||||
SerializedProperty m_LeftMiddleDistal;
|
||||
SerializedProperty m_LeftRingProximal;
|
||||
SerializedProperty m_LeftRingIntermediate;
|
||||
SerializedProperty m_LeftRingDistal;
|
||||
SerializedProperty m_LeftLittleProximal;
|
||||
SerializedProperty m_LeftLittleIntermediate;
|
||||
SerializedProperty m_LeftLittleDistal;
|
||||
SerializedProperty m_RightThumbProximal;
|
||||
SerializedProperty m_RightThumbIntermediate;
|
||||
SerializedProperty m_RightThumbDistal;
|
||||
SerializedProperty m_RightIndexProximal;
|
||||
SerializedProperty m_RightIndexIntermediate;
|
||||
SerializedProperty m_RightIndexDistal;
|
||||
SerializedProperty m_RightMiddleProximal;
|
||||
SerializedProperty m_RightMiddleIntermediate;
|
||||
SerializedProperty m_RightMiddleDistal;
|
||||
SerializedProperty m_RightRingProximal;
|
||||
SerializedProperty m_RightRingIntermediate;
|
||||
SerializedProperty m_RightRingDistal;
|
||||
SerializedProperty m_RightLittleProximal;
|
||||
SerializedProperty m_RightLittleIntermediate;
|
||||
SerializedProperty m_RightLittleDistal;
|
||||
|
||||
#endregion
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
m_target = target as Humanoid;
|
||||
m_Hips = serializedObject.FindProperty($"m_{nameof(Humanoid.Hips)}");
|
||||
|
||||
#region legs
|
||||
m_LeftUpperLeg = serializedObject.FindProperty($"m_{nameof(Humanoid.LeftUpperLeg)}");
|
||||
m_RightUpperLeg = serializedObject.FindProperty($"m_{nameof(Humanoid.RightUpperLeg)}");
|
||||
m_LeftLowerLeg = serializedObject.FindProperty($"m_{nameof(Humanoid.LeftLowerLeg)}");
|
||||
m_RightLowerLeg = serializedObject.FindProperty($"m_{nameof(Humanoid.RightLowerLeg)}");
|
||||
m_LeftFoot = serializedObject.FindProperty($"m_{nameof(Humanoid.LeftFoot)}");
|
||||
m_RightFoot = serializedObject.FindProperty($"m_{nameof(Humanoid.RightFoot)}");
|
||||
m_LeftToes = serializedObject.FindProperty($"m_{nameof(Humanoid.LeftToes)}");
|
||||
m_RightToes = serializedObject.FindProperty($"m_{nameof(Humanoid.RightToes)}");
|
||||
#endregion
|
||||
|
||||
#region spine
|
||||
m_Spine = serializedObject.FindProperty($"m_{nameof(Humanoid.Spine)}");
|
||||
m_Chest = serializedObject.FindProperty($"m_{nameof(Humanoid.Chest)}");
|
||||
m_UpperChest = serializedObject.FindProperty($"m_{nameof(Humanoid.UpperChest)}");
|
||||
m_Neck = serializedObject.FindProperty($"m_{nameof(Humanoid.Neck)}");
|
||||
m_Head = serializedObject.FindProperty($"m_{nameof(Humanoid.Head)}");
|
||||
m_LeftEye = serializedObject.FindProperty($"m_{nameof(Humanoid.LeftEye)}");
|
||||
m_RightEye = serializedObject.FindProperty($"m_{nameof(Humanoid.RightEye)}");
|
||||
m_Jaw = serializedObject.FindProperty($"m_{nameof(Humanoid.Jaw)}");
|
||||
|
||||
#endregion
|
||||
|
||||
#region arm
|
||||
m_LeftShoulder = serializedObject.FindProperty($"m_{nameof(Humanoid.LeftShoulder)}");
|
||||
m_RightShoulder = serializedObject.FindProperty($"m_{nameof(Humanoid.RightShoulder)}");
|
||||
m_LeftUpperArm = serializedObject.FindProperty($"m_{nameof(Humanoid.LeftUpperArm)}");
|
||||
m_RightUpperArm = serializedObject.FindProperty($"m_{nameof(Humanoid.RightUpperArm)}");
|
||||
m_LeftLowerArm = serializedObject.FindProperty($"m_{nameof(Humanoid.LeftLowerArm)}");
|
||||
m_RightLowerArm = serializedObject.FindProperty($"m_{nameof(Humanoid.RightLowerArm)}");
|
||||
m_LeftHand = serializedObject.FindProperty($"m_{nameof(Humanoid.LeftHand)}");
|
||||
m_RightHand = serializedObject.FindProperty($"m_{nameof(Humanoid.RightHand)}");
|
||||
|
||||
#endregion
|
||||
|
||||
#region fingers
|
||||
m_LeftThumbProximal = serializedObject.FindProperty($"m_{nameof(Humanoid.LeftThumbProximal)}");
|
||||
m_LeftThumbIntermediate = serializedObject.FindProperty($"m_{nameof(Humanoid.LeftThumbIntermediate)}");
|
||||
m_LeftThumbDistal = serializedObject.FindProperty($"m_{nameof(Humanoid.LeftThumbDistal)}");
|
||||
m_LeftIndexProximal = serializedObject.FindProperty($"m_{nameof(Humanoid.LeftIndexProximal)}");
|
||||
m_LeftIndexIntermediate = serializedObject.FindProperty($"m_{nameof(Humanoid.LeftIndexIntermediate)}");
|
||||
m_LeftIndexDistal = serializedObject.FindProperty($"m_{nameof(Humanoid.LeftIndexDistal)}");
|
||||
m_LeftMiddleProximal = serializedObject.FindProperty($"m_{nameof(Humanoid.LeftMiddleProximal)}");
|
||||
m_LeftMiddleIntermediate = serializedObject.FindProperty($"m_{nameof(Humanoid.LeftMiddleIntermediate)}");
|
||||
m_LeftMiddleDistal = serializedObject.FindProperty($"m_{nameof(Humanoid.LeftMiddleDistal)}");
|
||||
m_LeftRingProximal = serializedObject.FindProperty($"m_{nameof(Humanoid.LeftRingProximal)}");
|
||||
m_LeftRingIntermediate = serializedObject.FindProperty($"m_{nameof(Humanoid.LeftRingIntermediate)}");
|
||||
m_LeftRingDistal = serializedObject.FindProperty($"m_{nameof(Humanoid.LeftRingDistal)}");
|
||||
m_LeftLittleProximal = serializedObject.FindProperty($"m_{nameof(Humanoid.LeftLittleProximal)}");
|
||||
m_LeftLittleIntermediate = serializedObject.FindProperty($"m_{nameof(Humanoid.LeftLittleIntermediate)}");
|
||||
m_LeftLittleDistal = serializedObject.FindProperty($"m_{nameof(Humanoid.LeftLittleDistal)}");
|
||||
m_RightThumbProximal = serializedObject.FindProperty($"m_{nameof(Humanoid.RightThumbProximal)}");
|
||||
m_RightThumbIntermediate = serializedObject.FindProperty($"m_{nameof(Humanoid.RightThumbIntermediate)}");
|
||||
m_RightThumbDistal = serializedObject.FindProperty($"m_{nameof(Humanoid.RightThumbDistal)}");
|
||||
m_RightIndexProximal = serializedObject.FindProperty($"m_{nameof(Humanoid.RightIndexProximal)}");
|
||||
m_RightIndexIntermediate = serializedObject.FindProperty($"m_{nameof(Humanoid.RightIndexIntermediate)}");
|
||||
m_RightIndexDistal = serializedObject.FindProperty($"m_{nameof(Humanoid.RightIndexDistal)}");
|
||||
m_RightMiddleProximal = serializedObject.FindProperty($"m_{nameof(Humanoid.RightMiddleProximal)}");
|
||||
m_RightMiddleIntermediate = serializedObject.FindProperty($"m_{nameof(Humanoid.RightMiddleIntermediate)}");
|
||||
m_RightMiddleDistal = serializedObject.FindProperty($"m_{nameof(Humanoid.RightMiddleDistal)}");
|
||||
m_RightRingProximal = serializedObject.FindProperty($"m_{nameof(Humanoid.RightRingProximal)}");
|
||||
m_RightRingIntermediate = serializedObject.FindProperty($"m_{nameof(Humanoid.RightRingIntermediate)}");
|
||||
m_RightRingDistal = serializedObject.FindProperty($"m_{nameof(Humanoid.RightRingDistal)}");
|
||||
m_RightLittleProximal = serializedObject.FindProperty($"m_{nameof(Humanoid.RightLittleProximal)}");
|
||||
m_RightLittleIntermediate = serializedObject.FindProperty($"m_{nameof(Humanoid.RightLittleIntermediate)}");
|
||||
m_RightLittleDistal = serializedObject.FindProperty($"m_{nameof(Humanoid.RightLittleDistal)}");
|
||||
#endregion
|
||||
}
|
||||
|
||||
struct Horizontal : IDisposable
|
||||
{
|
||||
public static Horizontal Using()
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
return default;
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
|
||||
static void HorizontalFields(string label, params SerializedProperty[] props)
|
||||
{
|
||||
try
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
GUILayout.Label(label, GUILayout.Width(LABEL_WIDTH));
|
||||
GUILayout.FlexibleSpace();
|
||||
|
||||
foreach (var prop in props)
|
||||
{
|
||||
EditorGUILayout.PropertyField(prop, GUIContent.none, true, GUILayout.MinWidth(100));
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
|
||||
static bool s_spineFold;
|
||||
static bool s_legFold;
|
||||
static bool s_armFold;
|
||||
static bool s_fingerFold;
|
||||
static string GetDialogDir(UnityEngine.Object obj)
|
||||
{
|
||||
var prefab = PrefabUtility.GetCorrespondingObjectFromSource(obj);
|
||||
if (prefab is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return UnityPath.FromAsset(prefab).FullPath;
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
foreach (var validation in m_target.Validate())
|
||||
{
|
||||
EditorGUILayout.HelpBox(validation.Message, validation.IsError ? MessageType.Error : MessageType.Warning);
|
||||
}
|
||||
|
||||
// prefer
|
||||
serializedObject.Update();
|
||||
|
||||
EditorGUILayout.PropertyField(m_Hips);
|
||||
|
||||
s_spineFold = EditorGUILayout.Foldout(s_spineFold, "Body");
|
||||
if (s_spineFold)
|
||||
{
|
||||
EditorGUILayout.PropertyField(m_Spine);
|
||||
EditorGUILayout.PropertyField(m_Chest);
|
||||
EditorGUILayout.PropertyField(m_UpperChest);
|
||||
EditorGUILayout.PropertyField(m_Neck);
|
||||
EditorGUILayout.PropertyField(m_Head);
|
||||
EditorGUILayout.PropertyField(m_Jaw);
|
||||
HorizontalFields("Eye", m_LeftEye, m_RightEye);
|
||||
}
|
||||
|
||||
s_legFold = EditorGUILayout.Foldout(s_legFold, "Leg");
|
||||
if (s_legFold)
|
||||
{
|
||||
HorizontalFields("UpperLeg", m_LeftUpperLeg, m_RightUpperLeg);
|
||||
HorizontalFields("LowerLeg", m_LeftLowerLeg, m_RightLowerLeg);
|
||||
HorizontalFields("Foot", m_LeftFoot, m_RightFoot);
|
||||
HorizontalFields("Toes", m_LeftToes, m_RightToes);
|
||||
}
|
||||
|
||||
s_armFold = EditorGUILayout.Foldout(s_armFold, "Arm");
|
||||
if (s_armFold)
|
||||
{
|
||||
HorizontalFields("Shoulder", m_LeftShoulder, m_RightShoulder);
|
||||
HorizontalFields("UpperArm", m_LeftUpperArm, m_RightUpperArm);
|
||||
HorizontalFields("LowerArm", m_LeftLowerArm, m_RightLowerArm);
|
||||
HorizontalFields("Hand", m_LeftHand, m_RightHand);
|
||||
}
|
||||
|
||||
s_fingerFold = EditorGUILayout.Foldout(s_fingerFold, "Finger");
|
||||
if (s_fingerFold)
|
||||
{
|
||||
HorizontalFields("LeftThumb", m_LeftThumbProximal, m_LeftThumbIntermediate, m_LeftThumbDistal);
|
||||
HorizontalFields("LeftIndex", m_LeftIndexProximal, m_LeftIndexIntermediate, m_LeftIndexDistal);
|
||||
HorizontalFields("LeftMiddle", m_LeftMiddleProximal, m_LeftMiddleIntermediate, m_LeftMiddleDistal);
|
||||
HorizontalFields("LeftRing", m_LeftRingProximal, m_LeftRingIntermediate, m_LeftRingDistal);
|
||||
HorizontalFields("LeftLittle", m_LeftLittleProximal, m_LeftLittleIntermediate, m_LeftLittleDistal);
|
||||
HorizontalFields("RightThumb", m_RightThumbProximal, m_RightThumbIntermediate, m_RightThumbDistal);
|
||||
HorizontalFields("RightIndex", m_RightIndexProximal, m_RightIndexIntermediate, m_RightIndexDistal);
|
||||
HorizontalFields("RightMiddle", m_RightMiddleProximal, m_RightMiddleIntermediate, m_RightMiddleDistal);
|
||||
HorizontalFields("RightRing", m_RightRingProximal, m_RightRingIntermediate, m_RightRingDistal);
|
||||
HorizontalFields("RightLittle", m_RightLittleProximal, m_RightLittleIntermediate, m_RightLittleDistal);
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
// create avatar
|
||||
if (GUILayout.Button("Create UnityEngine.Avatar"))
|
||||
{
|
||||
var path = EditorUtility.SaveFilePanel(
|
||||
"Save avatar",
|
||||
GetDialogDir(m_target),
|
||||
string.Format("{0}.avatar.asset", serializedObject.targetObject.name),
|
||||
"asset");
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
var avatar = m_target.CreateAvatar();
|
||||
if (avatar != null)
|
||||
{
|
||||
var unityPath = UnityPath.FromFullpath(path);
|
||||
avatar.name = "avatar";
|
||||
Debug.LogFormat("Create avatar {0}", unityPath);
|
||||
AssetDatabase.CreateAsset(avatar, unityPath.Value);
|
||||
AssetDatabase.ImportAsset(unityPath.Value);
|
||||
|
||||
// replace
|
||||
var animator = m_target.GetComponent<Animator>();
|
||||
if (animator == null)
|
||||
{
|
||||
animator = m_target.gameObject.AddComponent<Animator>();
|
||||
}
|
||||
animator.avatar = avatar;
|
||||
|
||||
Selection.activeObject = avatar;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnSceneGUI()
|
||||
{
|
||||
// var bones = m_target.Bones;
|
||||
// if (bones != null)
|
||||
// {
|
||||
// for (int i = 0; i < bones.Length; ++i)
|
||||
// {
|
||||
// DrawBone((HumanBodyBones)i, bones[i]);
|
||||
// }
|
||||
// foreach (var x in m_bones)
|
||||
// {
|
||||
// x.Draw();
|
||||
// }
|
||||
// }
|
||||
|
||||
var forward = m_target.GetForward();
|
||||
|
||||
var begin = m_target.transform.position;
|
||||
var end = begin + forward;
|
||||
Handles.DrawLine(begin, end);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/MeshUtility/Editor/HumanoidEditor.cs.meta
Normal file
11
Assets/MeshUtility/Editor/HumanoidEditor.cs.meta
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 57cc7b16eb4146c4ab5631f538e2489f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
441
Assets/MeshUtility/Runtime/Humanoid.cs
Normal file
441
Assets/MeshUtility/Runtime/Humanoid.cs
Normal file
|
|
@ -0,0 +1,441 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MeshUtility
|
||||
{
|
||||
/// <summary>
|
||||
/// Bone割り当てを保持する。
|
||||
/// ヒエラルキーのルート(おそらくHipsの親)にアタッチする
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
public class Humanoid : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Transform m_Hips; public Transform Hips => m_Hips;
|
||||
|
||||
#region leg
|
||||
[SerializeField] private Transform m_LeftUpperLeg; public Transform LeftUpperLeg => m_LeftUpperLeg;
|
||||
[SerializeField] private Transform m_RightUpperLeg; public Transform RightUpperLeg => m_RightUpperLeg;
|
||||
[SerializeField] private Transform m_LeftLowerLeg; public Transform LeftLowerLeg => m_LeftLowerLeg;
|
||||
[SerializeField] private Transform m_RightLowerLeg; public Transform RightLowerLeg => m_RightLowerLeg;
|
||||
[SerializeField] private Transform m_LeftFoot; public Transform LeftFoot => m_LeftFoot;
|
||||
[SerializeField] private Transform m_RightFoot; public Transform RightFoot => m_RightFoot;
|
||||
[SerializeField] private Transform m_LeftToes; public Transform LeftToes => m_LeftToes;
|
||||
[SerializeField] private Transform m_RightToes; public Transform RightToes => m_RightToes;
|
||||
#endregion
|
||||
|
||||
#region spine
|
||||
[SerializeField] private Transform m_Spine; public Transform Spine => m_Spine;
|
||||
[SerializeField] private Transform m_Chest; public Transform Chest => m_Chest;
|
||||
[SerializeField] private Transform m_UpperChest; public Transform UpperChest => m_UpperChest;
|
||||
[SerializeField] private Transform m_Neck; public Transform Neck => m_Neck;
|
||||
[SerializeField] private Transform m_Head; public Transform Head => m_Head;
|
||||
[SerializeField] private Transform m_LeftEye; public Transform LeftEye => m_LeftEye;
|
||||
[SerializeField] private Transform m_RightEye; public Transform RightEye => m_RightEye;
|
||||
[SerializeField] private Transform m_Jaw; public Transform Jaw => m_Jaw;
|
||||
#endregion
|
||||
|
||||
#region arm
|
||||
[SerializeField] private Transform m_LeftShoulder; public Transform LeftShoulder => m_LeftShoulder;
|
||||
[SerializeField] private Transform m_RightShoulder; public Transform RightShoulder => m_RightShoulder;
|
||||
[SerializeField] private Transform m_LeftUpperArm; public Transform LeftUpperArm => m_LeftUpperArm;
|
||||
[SerializeField] private Transform m_RightUpperArm; public Transform RightUpperArm => m_RightUpperArm;
|
||||
[SerializeField] private Transform m_LeftLowerArm; public Transform LeftLowerArm => m_LeftLowerArm;
|
||||
[SerializeField] private Transform m_RightLowerArm; public Transform RightLowerArm => m_RightLowerArm;
|
||||
[SerializeField] private Transform m_LeftHand; public Transform LeftHand => m_LeftHand;
|
||||
[SerializeField] private Transform m_RightHand; public Transform RightHand => m_RightHand;
|
||||
#endregion
|
||||
|
||||
#region fingers
|
||||
[SerializeField] private Transform m_LeftThumbProximal; public Transform LeftThumbProximal => m_LeftThumbProximal;
|
||||
[SerializeField] private Transform m_LeftThumbIntermediate; public Transform LeftThumbIntermediate => m_LeftThumbIntermediate;
|
||||
[SerializeField] private Transform m_LeftThumbDistal; public Transform LeftThumbDistal => m_LeftThumbDistal;
|
||||
[SerializeField] private Transform m_LeftIndexProximal; public Transform LeftIndexProximal => m_LeftIndexProximal;
|
||||
[SerializeField] private Transform m_LeftIndexIntermediate; public Transform LeftIndexIntermediate => m_LeftIndexIntermediate;
|
||||
[SerializeField] private Transform m_LeftIndexDistal; public Transform LeftIndexDistal => m_LeftIndexDistal;
|
||||
[SerializeField] private Transform m_LeftMiddleProximal; public Transform LeftMiddleProximal => m_LeftMiddleProximal;
|
||||
[SerializeField] private Transform m_LeftMiddleIntermediate; public Transform LeftMiddleIntermediate => m_LeftMiddleIntermediate;
|
||||
[SerializeField] private Transform m_LeftMiddleDistal; public Transform LeftMiddleDistal => m_LeftMiddleDistal;
|
||||
[SerializeField] private Transform m_LeftRingProximal; public Transform LeftRingProximal => m_LeftRingProximal;
|
||||
[SerializeField] private Transform m_LeftRingIntermediate; public Transform LeftRingIntermediate => m_LeftRingIntermediate;
|
||||
[SerializeField] private Transform m_LeftRingDistal; public Transform LeftRingDistal => m_LeftRingDistal;
|
||||
[SerializeField] private Transform m_LeftLittleProximal; public Transform LeftLittleProximal => m_LeftLittleProximal;
|
||||
[SerializeField] private Transform m_LeftLittleIntermediate; public Transform LeftLittleIntermediate => m_LeftLittleIntermediate;
|
||||
[SerializeField] private Transform m_LeftLittleDistal; public Transform LeftLittleDistal => m_LeftLittleDistal;
|
||||
[SerializeField] private Transform m_RightThumbProximal; public Transform RightThumbProximal => m_RightThumbProximal;
|
||||
[SerializeField] private Transform m_RightThumbIntermediate; public Transform RightThumbIntermediate => m_RightThumbIntermediate;
|
||||
[SerializeField] private Transform m_RightThumbDistal; public Transform RightThumbDistal => m_RightThumbDistal;
|
||||
[SerializeField] private Transform m_RightIndexProximal; public Transform RightIndexProximal => m_RightIndexProximal;
|
||||
[SerializeField] private Transform m_RightIndexIntermediate; public Transform RightIndexIntermediate => m_RightIndexIntermediate;
|
||||
[SerializeField] private Transform m_RightIndexDistal; public Transform RightIndexDistal => m_RightIndexDistal;
|
||||
[SerializeField] private Transform m_RightMiddleProximal; public Transform RightMiddleProximal => m_RightMiddleProximal;
|
||||
[SerializeField] private Transform m_RightMiddleIntermediate; public Transform RightMiddleIntermediate => m_RightMiddleIntermediate;
|
||||
[SerializeField] private Transform m_RightMiddleDistal; public Transform RightMiddleDistal => m_RightMiddleDistal;
|
||||
[SerializeField] private Transform m_RightRingProximal; public Transform RightRingProximal => m_RightRingProximal;
|
||||
[SerializeField] private Transform m_RightRingIntermediate; public Transform RightRingIntermediate => m_RightRingIntermediate;
|
||||
[SerializeField] private Transform m_RightRingDistal; public Transform RightRingDistal => m_RightRingDistal;
|
||||
[SerializeField] private Transform m_RightLittleProximal; public Transform RightLittleProximal => m_RightLittleProximal;
|
||||
[SerializeField] private Transform m_RightLittleIntermediate; public Transform RightLittleIntermediate => m_RightLittleIntermediate;
|
||||
[SerializeField] private Transform m_RightLittleDistal; public Transform RightLittleDistal => m_RightLittleDistal;
|
||||
#endregion
|
||||
|
||||
void Reset()
|
||||
{
|
||||
AssignBonesFromAnimator();
|
||||
}
|
||||
|
||||
public struct Validation
|
||||
{
|
||||
public readonly string Message;
|
||||
public readonly bool IsError;
|
||||
|
||||
public Validation(string message, bool isError)
|
||||
{
|
||||
Message = message;
|
||||
IsError = isError;
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerable<Validation> Required(params (string, Transform)[] props)
|
||||
{
|
||||
foreach (var prop in props)
|
||||
{
|
||||
if (prop.Item2 is null)
|
||||
{
|
||||
var name = prop.Item1;
|
||||
if (name.StartsWith("m_"))
|
||||
{
|
||||
name = name.Substring(2);
|
||||
}
|
||||
yield return new Validation($"{name} is Required", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Vector3 GetForward(Transform l, Transform r)
|
||||
{
|
||||
if (l == null || r == null)
|
||||
{
|
||||
return Vector3.zero;
|
||||
}
|
||||
var lr = (r.position - l.position).normalized;
|
||||
return Vector3.Cross(lr, Vector3.up);
|
||||
}
|
||||
|
||||
public Vector3 GetForward()
|
||||
{
|
||||
return GetForward(m_LeftUpperLeg, m_RightUpperLeg);
|
||||
}
|
||||
|
||||
public IEnumerable<Validation> Validate()
|
||||
{
|
||||
foreach (var validation in Required(
|
||||
(nameof(m_Hips), m_Hips), (nameof(m_Spine), m_Spine), (nameof(m_Head), m_Head),
|
||||
(nameof(m_LeftUpperLeg), m_LeftUpperLeg), (nameof(m_LeftLowerLeg), m_LeftLowerLeg), (nameof(m_LeftFoot), m_LeftFoot),
|
||||
(nameof(m_RightUpperLeg), m_RightUpperLeg), (nameof(m_RightLowerLeg), m_RightLowerLeg), (nameof(m_RightFoot), m_RightFoot),
|
||||
(nameof(m_LeftUpperArm), m_LeftUpperArm), (nameof(m_LeftLowerArm), m_LeftLowerArm), (nameof(m_LeftHand), m_LeftHand),
|
||||
(nameof(m_RightUpperArm), m_RightUpperArm), (nameof(m_RightLowerArm), m_RightLowerArm), (nameof(m_RightHand), m_RightHand)
|
||||
))
|
||||
{
|
||||
yield return validation;
|
||||
}
|
||||
|
||||
// var forward = GetForward();
|
||||
// if (Vector3.Dot(Vector3.forward, forward) < 0.5f)
|
||||
// {
|
||||
// yield return new Validation("Not facing the Z-axis positive direction", true);
|
||||
// }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ボーン割り当てから UnityEngine.Avatar を生成する
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Avatar CreateAvatar()
|
||||
{
|
||||
return HumanoidLoader.LoadHumanoidAvatar(transform, BoneMap);
|
||||
}
|
||||
|
||||
public Transform GetBoneTransform(HumanBodyBones bone)
|
||||
{
|
||||
switch (bone)
|
||||
{
|
||||
case HumanBodyBones.Hips: return Hips;
|
||||
|
||||
#region leg
|
||||
case HumanBodyBones.LeftUpperLeg: return LeftUpperLeg;
|
||||
case HumanBodyBones.RightUpperLeg: return RightUpperLeg;
|
||||
case HumanBodyBones.LeftLowerLeg: return LeftLowerLeg;
|
||||
case HumanBodyBones.RightLowerLeg: return RightLowerLeg;
|
||||
case HumanBodyBones.LeftFoot: return LeftFoot;
|
||||
case HumanBodyBones.RightFoot: return RightFoot;
|
||||
case HumanBodyBones.LeftToes: return LeftToes;
|
||||
case HumanBodyBones.RightToes: return RightToes;
|
||||
#endregion
|
||||
|
||||
#region spine
|
||||
case HumanBodyBones.Spine: return Spine;
|
||||
case HumanBodyBones.Chest: return Chest;
|
||||
case HumanBodyBones.UpperChest: return UpperChest;
|
||||
case HumanBodyBones.Neck: return Neck;
|
||||
case HumanBodyBones.Head: return Head;
|
||||
case HumanBodyBones.LeftEye: return LeftEye;
|
||||
case HumanBodyBones.RightEye: return RightEye;
|
||||
case HumanBodyBones.Jaw: return Jaw;
|
||||
#endregion
|
||||
|
||||
#region arm
|
||||
case HumanBodyBones.LeftShoulder: return LeftShoulder;
|
||||
case HumanBodyBones.RightShoulder: return RightShoulder;
|
||||
case HumanBodyBones.LeftUpperArm: return LeftUpperArm;
|
||||
case HumanBodyBones.RightUpperArm: return RightUpperArm;
|
||||
case HumanBodyBones.LeftLowerArm: return LeftLowerArm;
|
||||
case HumanBodyBones.RightLowerArm: return RightLowerArm;
|
||||
case HumanBodyBones.LeftHand: return LeftHand;
|
||||
case HumanBodyBones.RightHand: return RightHand;
|
||||
#endregion
|
||||
|
||||
#region fingers
|
||||
case HumanBodyBones.LeftThumbProximal: return LeftThumbProximal;
|
||||
case HumanBodyBones.LeftThumbIntermediate: return LeftThumbIntermediate;
|
||||
case HumanBodyBones.LeftThumbDistal: return LeftThumbDistal;
|
||||
case HumanBodyBones.LeftIndexProximal: return LeftIndexProximal;
|
||||
case HumanBodyBones.LeftIndexIntermediate: return LeftIndexIntermediate;
|
||||
case HumanBodyBones.LeftIndexDistal: return LeftIndexDistal;
|
||||
case HumanBodyBones.LeftMiddleProximal: return LeftMiddleProximal;
|
||||
case HumanBodyBones.LeftMiddleIntermediate: return LeftMiddleIntermediate;
|
||||
case HumanBodyBones.LeftMiddleDistal: return LeftMiddleDistal;
|
||||
case HumanBodyBones.LeftRingProximal: return LeftRingProximal;
|
||||
case HumanBodyBones.LeftRingIntermediate: return LeftRingIntermediate;
|
||||
case HumanBodyBones.LeftRingDistal: return LeftRingDistal;
|
||||
case HumanBodyBones.LeftLittleProximal: return LeftLittleProximal;
|
||||
case HumanBodyBones.LeftLittleIntermediate: return LeftLittleIntermediate;
|
||||
case HumanBodyBones.LeftLittleDistal: return LeftLittleDistal;
|
||||
case HumanBodyBones.RightThumbProximal: return RightThumbProximal;
|
||||
case HumanBodyBones.RightThumbIntermediate: return RightThumbIntermediate;
|
||||
case HumanBodyBones.RightThumbDistal: return RightThumbDistal;
|
||||
case HumanBodyBones.RightIndexProximal: return RightIndexProximal;
|
||||
case HumanBodyBones.RightIndexIntermediate: return RightIndexIntermediate;
|
||||
case HumanBodyBones.RightIndexDistal: return RightIndexDistal;
|
||||
case HumanBodyBones.RightMiddleProximal: return RightMiddleProximal;
|
||||
case HumanBodyBones.RightMiddleIntermediate: return RightMiddleIntermediate;
|
||||
case HumanBodyBones.RightMiddleDistal: return RightMiddleDistal;
|
||||
case HumanBodyBones.RightRingProximal: return RightRingProximal;
|
||||
case HumanBodyBones.RightRingIntermediate: return RightRingIntermediate;
|
||||
case HumanBodyBones.RightRingDistal: return RightRingDistal;
|
||||
case HumanBodyBones.RightLittleProximal: return RightLittleProximal;
|
||||
case HumanBodyBones.RightLittleIntermediate: return RightLittleIntermediate;
|
||||
case HumanBodyBones.RightLittleDistal: return RightLittleDistal;
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
IEnumerable<(Transform, HumanBodyBones)> BoneMap
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Hips != null) { yield return (Hips, HumanBodyBones.Hips); }
|
||||
|
||||
#region leg
|
||||
if (LeftUpperLeg != null) { yield return (LeftUpperLeg, HumanBodyBones.LeftUpperLeg); }
|
||||
if (RightUpperLeg != null) { yield return (RightUpperLeg, HumanBodyBones.RightUpperLeg); }
|
||||
if (LeftLowerLeg != null) { yield return (LeftLowerLeg, HumanBodyBones.LeftLowerLeg); }
|
||||
if (RightLowerLeg != null) { yield return (RightLowerLeg, HumanBodyBones.RightLowerLeg); }
|
||||
if (LeftFoot != null) { yield return (LeftFoot, HumanBodyBones.LeftFoot); }
|
||||
if (RightFoot != null) { yield return (RightFoot, HumanBodyBones.RightFoot); }
|
||||
if (LeftToes != null) { yield return (LeftToes, HumanBodyBones.LeftToes); }
|
||||
if (RightToes != null) { yield return (RightToes, HumanBodyBones.RightToes); }
|
||||
#endregion
|
||||
|
||||
#region spine
|
||||
if (Spine != null) { yield return (Spine, HumanBodyBones.Spine); }
|
||||
if (Chest != null) { yield return (Chest, HumanBodyBones.Chest); }
|
||||
if (UpperChest != null) { yield return (UpperChest, HumanBodyBones.UpperChest); }
|
||||
if (Neck != null) { yield return (Neck, HumanBodyBones.Neck); }
|
||||
if (Head != null) { yield return (Head, HumanBodyBones.Head); }
|
||||
if (LeftEye != null) { yield return (LeftEye, HumanBodyBones.LeftEye); }
|
||||
if (RightEye != null) { yield return (RightEye, HumanBodyBones.RightEye); }
|
||||
if (Jaw != null) { yield return (Jaw, HumanBodyBones.Jaw); }
|
||||
#endregion
|
||||
|
||||
#region arm
|
||||
if (LeftShoulder != null) { yield return (LeftShoulder, HumanBodyBones.LeftShoulder); }
|
||||
if (RightShoulder != null) { yield return (RightShoulder, HumanBodyBones.RightShoulder); }
|
||||
if (LeftUpperArm != null) { yield return (LeftUpperArm, HumanBodyBones.LeftUpperArm); }
|
||||
if (RightUpperArm != null) { yield return (RightUpperArm, HumanBodyBones.RightUpperArm); }
|
||||
if (LeftLowerArm != null) { yield return (LeftLowerArm, HumanBodyBones.LeftLowerArm); }
|
||||
if (RightLowerArm != null) { yield return (RightLowerArm, HumanBodyBones.RightLowerArm); }
|
||||
if (LeftHand != null) { yield return (LeftHand, HumanBodyBones.LeftHand); }
|
||||
if (RightHand != null) { yield return (RightHand, HumanBodyBones.RightHand); }
|
||||
#endregion
|
||||
|
||||
#region fingers
|
||||
if (LeftThumbProximal != null) { yield return (LeftThumbProximal, HumanBodyBones.LeftThumbProximal); }
|
||||
if (LeftThumbIntermediate != null) { yield return (LeftThumbIntermediate, HumanBodyBones.LeftThumbIntermediate); }
|
||||
if (LeftThumbDistal != null) { yield return (LeftThumbDistal, HumanBodyBones.LeftThumbDistal); }
|
||||
if (LeftIndexProximal != null) { yield return (LeftIndexProximal, HumanBodyBones.LeftIndexProximal); }
|
||||
if (LeftIndexIntermediate != null) { yield return (LeftIndexIntermediate, HumanBodyBones.LeftIndexIntermediate); }
|
||||
if (LeftIndexDistal != null) { yield return (LeftIndexDistal, HumanBodyBones.LeftIndexDistal); }
|
||||
if (LeftMiddleProximal != null) { yield return (LeftMiddleProximal, HumanBodyBones.LeftMiddleProximal); }
|
||||
if (LeftMiddleIntermediate != null) { yield return (LeftMiddleIntermediate, HumanBodyBones.LeftMiddleIntermediate); }
|
||||
if (LeftMiddleDistal != null) { yield return (LeftMiddleDistal, HumanBodyBones.LeftMiddleDistal); }
|
||||
if (LeftRingProximal != null) { yield return (LeftRingProximal, HumanBodyBones.LeftRingProximal); }
|
||||
if (LeftRingIntermediate != null) { yield return (LeftRingIntermediate, HumanBodyBones.LeftRingIntermediate); }
|
||||
if (LeftRingDistal != null) { yield return (LeftRingDistal, HumanBodyBones.LeftRingDistal); }
|
||||
if (LeftLittleProximal != null) { yield return (LeftLittleProximal, HumanBodyBones.LeftLittleProximal); }
|
||||
if (LeftLittleIntermediate != null) { yield return (LeftLittleIntermediate, HumanBodyBones.LeftLittleIntermediate); }
|
||||
if (LeftLittleDistal != null) { yield return (LeftLittleDistal, HumanBodyBones.LeftLittleDistal); }
|
||||
if (RightThumbProximal != null) { yield return (RightThumbProximal, HumanBodyBones.RightThumbProximal); }
|
||||
if (RightThumbIntermediate != null) { yield return (RightThumbIntermediate, HumanBodyBones.RightThumbIntermediate); }
|
||||
if (RightThumbDistal != null) { yield return (RightThumbDistal, HumanBodyBones.RightThumbDistal); }
|
||||
if (RightIndexProximal != null) { yield return (RightIndexProximal, HumanBodyBones.RightIndexProximal); }
|
||||
if (RightIndexIntermediate != null) { yield return (RightIndexIntermediate, HumanBodyBones.RightIndexIntermediate); }
|
||||
if (RightIndexDistal != null) { yield return (RightIndexDistal, HumanBodyBones.RightIndexDistal); }
|
||||
if (RightMiddleProximal != null) { yield return (RightMiddleProximal, HumanBodyBones.RightMiddleProximal); }
|
||||
if (RightMiddleIntermediate != null) { yield return (RightMiddleIntermediate, HumanBodyBones.RightMiddleIntermediate); }
|
||||
if (RightMiddleDistal != null) { yield return (RightMiddleDistal, HumanBodyBones.RightMiddleDistal); }
|
||||
if (RightRingProximal != null) { yield return (RightRingProximal, HumanBodyBones.RightRingProximal); }
|
||||
if (RightRingIntermediate != null) { yield return (RightRingIntermediate, HumanBodyBones.RightRingIntermediate); }
|
||||
if (RightRingDistal != null) { yield return (RightRingDistal, HumanBodyBones.RightRingDistal); }
|
||||
if (RightLittleProximal != null) { yield return (RightLittleProximal, HumanBodyBones.RightLittleProximal); }
|
||||
if (RightLittleIntermediate != null) { yield return (RightLittleIntermediate, HumanBodyBones.RightLittleIntermediate); }
|
||||
if (RightLittleDistal != null) { yield return (RightLittleDistal, HumanBodyBones.RightLittleDistal); }
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// nodes からボーンを割り当てる
|
||||
/// </summary>
|
||||
/// <param name="nodes"></param>
|
||||
public void AssignBones(IEnumerable<(HumanBodyBones, Transform)> nodes)
|
||||
{
|
||||
foreach (var (key, value) in nodes)
|
||||
{
|
||||
if (key == HumanBodyBones.LastBone)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (value is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case HumanBodyBones.Hips: m_Hips = value; break;
|
||||
|
||||
#region leg
|
||||
case HumanBodyBones.LeftUpperLeg: m_LeftUpperLeg = value; break;
|
||||
case HumanBodyBones.RightUpperLeg: m_RightUpperLeg = value; break;
|
||||
case HumanBodyBones.LeftLowerLeg: m_LeftLowerLeg = value; break;
|
||||
case HumanBodyBones.RightLowerLeg: m_RightLowerLeg = value; break;
|
||||
case HumanBodyBones.LeftFoot: m_LeftFoot = value; break;
|
||||
case HumanBodyBones.RightFoot: m_RightFoot = value; break;
|
||||
case HumanBodyBones.LeftToes: m_LeftToes = value; break;
|
||||
case HumanBodyBones.RightToes: m_RightToes = value; break;
|
||||
#endregion
|
||||
|
||||
#region spine
|
||||
case HumanBodyBones.Spine: m_Spine = value; break;
|
||||
case HumanBodyBones.Chest: m_Chest = value; break;
|
||||
case HumanBodyBones.UpperChest: m_UpperChest = value; break;
|
||||
case HumanBodyBones.Neck: m_Neck = value; break;
|
||||
case HumanBodyBones.Head: m_Head = value; break;
|
||||
case HumanBodyBones.LeftEye: m_LeftEye = value; break;
|
||||
case HumanBodyBones.RightEye: m_RightEye = value; break;
|
||||
case HumanBodyBones.Jaw: m_Jaw = value; break;
|
||||
#endregion
|
||||
|
||||
#region arm
|
||||
case HumanBodyBones.LeftShoulder: m_LeftShoulder = value; break;
|
||||
case HumanBodyBones.RightShoulder: m_RightShoulder = value; break;
|
||||
case HumanBodyBones.LeftUpperArm: m_LeftUpperArm = value; break;
|
||||
case HumanBodyBones.RightUpperArm: m_RightUpperArm = value; break;
|
||||
case HumanBodyBones.LeftLowerArm: m_LeftLowerArm = value; break;
|
||||
case HumanBodyBones.RightLowerArm: m_RightLowerArm = value; break;
|
||||
case HumanBodyBones.LeftHand: m_LeftHand = value; break;
|
||||
case HumanBodyBones.RightHand: m_RightHand = value; break;
|
||||
#endregion
|
||||
|
||||
#region fingers
|
||||
case HumanBodyBones.LeftThumbProximal: m_LeftThumbProximal = value; break;
|
||||
case HumanBodyBones.LeftThumbIntermediate: m_LeftThumbIntermediate = value; break;
|
||||
case HumanBodyBones.LeftThumbDistal: m_LeftThumbDistal = value; break;
|
||||
case HumanBodyBones.LeftIndexProximal: m_LeftIndexProximal = value; break;
|
||||
case HumanBodyBones.LeftIndexIntermediate: m_LeftIndexIntermediate = value; break;
|
||||
case HumanBodyBones.LeftIndexDistal: m_LeftIndexDistal = value; break;
|
||||
case HumanBodyBones.LeftMiddleProximal: m_LeftMiddleProximal = value; break;
|
||||
case HumanBodyBones.LeftMiddleIntermediate: m_LeftMiddleIntermediate = value; break;
|
||||
case HumanBodyBones.LeftMiddleDistal: m_LeftMiddleDistal = value; break;
|
||||
case HumanBodyBones.LeftRingProximal: m_LeftRingProximal = value; break;
|
||||
case HumanBodyBones.LeftRingIntermediate: m_LeftRingIntermediate = value; break;
|
||||
case HumanBodyBones.LeftRingDistal: m_LeftRingDistal = value; break;
|
||||
case HumanBodyBones.LeftLittleProximal: m_LeftLittleProximal = value; break;
|
||||
case HumanBodyBones.LeftLittleIntermediate: m_LeftLittleIntermediate = value; break;
|
||||
case HumanBodyBones.LeftLittleDistal: m_LeftLittleDistal = value; break;
|
||||
case HumanBodyBones.RightThumbProximal: m_RightThumbProximal = value; break;
|
||||
case HumanBodyBones.RightThumbIntermediate: m_RightThumbIntermediate = value; break;
|
||||
case HumanBodyBones.RightThumbDistal: m_RightThumbDistal = value; break;
|
||||
case HumanBodyBones.RightIndexProximal: m_RightIndexProximal = value; break;
|
||||
case HumanBodyBones.RightIndexIntermediate: m_RightIndexIntermediate = value; break;
|
||||
case HumanBodyBones.RightIndexDistal: m_RightIndexDistal = value; break;
|
||||
case HumanBodyBones.RightMiddleProximal: m_RightMiddleProximal = value; break;
|
||||
case HumanBodyBones.RightMiddleIntermediate: m_RightMiddleIntermediate = value; break;
|
||||
case HumanBodyBones.RightMiddleDistal: m_RightMiddleDistal = value; break;
|
||||
case HumanBodyBones.RightRingProximal: m_RightRingProximal = value; break;
|
||||
case HumanBodyBones.RightRingIntermediate: m_RightRingIntermediate = value; break;
|
||||
case HumanBodyBones.RightRingDistal: m_RightRingDistal = value; break;
|
||||
case HumanBodyBones.RightLittleProximal: m_RightLittleProximal = value; break;
|
||||
case HumanBodyBones.RightLittleIntermediate: m_RightLittleIntermediate = value; break;
|
||||
case HumanBodyBones.RightLittleDistal: m_RightLittleDistal = value; break;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Animator から Bone を割り当てる
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool AssignBonesFromAnimator()
|
||||
{
|
||||
var animator = GetComponent<Animator>();
|
||||
if (animator is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var avatar = animator.avatar;
|
||||
if (avatar is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!avatar.isValid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!avatar.isHuman)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var keys = (UnityEngine.HumanBodyBones[])Enum.GetValues(typeof(UnityEngine.HumanBodyBones));
|
||||
|
||||
AssignBones(keys.Select(x =>
|
||||
{
|
||||
if (x == HumanBodyBones.LastBone)
|
||||
{
|
||||
return (HumanBodyBones.LastBone, null);
|
||||
}
|
||||
return ((HumanBodyBones)Enum.Parse(typeof(HumanBodyBones), x.ToString(), true), animator.GetBoneTransform(x));
|
||||
}));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/MeshUtility/Runtime/Humanoid.cs.meta
Normal file
11
Assets/MeshUtility/Runtime/Humanoid.cs.meta
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 889d98e41c0e8ff48bae50d1a729c2df
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
60
Assets/MeshUtility/Runtime/HumanoidLoader.cs
Normal file
60
Assets/MeshUtility/Runtime/HumanoidLoader.cs
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MeshUtility
|
||||
{
|
||||
public static class HumanoidLoader
|
||||
{
|
||||
public static Avatar LoadHumanoidAvatar(Transform root, IEnumerable<(Transform, HumanBodyBones)> boneMap)
|
||||
{
|
||||
var description = new HumanDescription
|
||||
{
|
||||
skeleton = root.GetComponentsInChildren<Transform>()
|
||||
.Select(x => x.ToSkeletonBone()).ToArray(),
|
||||
human = boneMap
|
||||
.Select(x => new HumanBone
|
||||
{
|
||||
boneName = x.Item1.name,
|
||||
humanName = s_humanTranitBoneNameMap[x.Item2],
|
||||
limit = new HumanLimit
|
||||
{
|
||||
useDefaultValues = true,
|
||||
}
|
||||
}).ToArray(),
|
||||
|
||||
armStretch = 0.05f,
|
||||
legStretch = 0.05f,
|
||||
upperArmTwist = 0.5f,
|
||||
lowerArmTwist = 0.5f,
|
||||
upperLegTwist = 0.5f,
|
||||
lowerLegTwist = 0.5f,
|
||||
feetSpacing = 0,
|
||||
hasTranslationDoF = false,
|
||||
};
|
||||
|
||||
return AvatarBuilder.BuildHumanAvatar(root.gameObject, description);
|
||||
}
|
||||
|
||||
static SkeletonBone ToSkeletonBone(this Transform t)
|
||||
{
|
||||
var sb = new SkeletonBone();
|
||||
sb.name = t.name;
|
||||
sb.position = t.localPosition;
|
||||
sb.rotation = t.localRotation;
|
||||
sb.scale = t.localScale;
|
||||
return sb;
|
||||
}
|
||||
|
||||
static HumanBodyBones TraitToHumanBone(string x)
|
||||
{
|
||||
return (HumanBodyBones)Enum.Parse(typeof(HumanBodyBones), x.Replace(" ", ""), true);
|
||||
}
|
||||
|
||||
static readonly Dictionary<HumanBodyBones, string> s_humanTranitBoneNameMap =
|
||||
HumanTrait.BoneName.ToDictionary(
|
||||
x => TraitToHumanBone(x),
|
||||
x => x);
|
||||
}
|
||||
}
|
||||
11
Assets/MeshUtility/Runtime/HumanoidLoader.cs.meta
Normal file
11
Assets/MeshUtility/Runtime/HumanoidLoader.cs.meta
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 12453a111483e4145852e3b057e065d9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
435
Assets/MeshUtility/Runtime/UnityPath.cs
Normal file
435
Assets/MeshUtility/Runtime/UnityPath.cs
Normal file
|
|
@ -0,0 +1,435 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
|
||||
namespace MeshUtility
|
||||
{
|
||||
/// <summary>
|
||||
/// relative path from Unity project root.
|
||||
/// For AssetDatabase.
|
||||
/// </summary>
|
||||
public struct UnityPath
|
||||
{
|
||||
#region UnityPath
|
||||
public string Value
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("unity://{0}", Value);
|
||||
}
|
||||
|
||||
public bool IsNull
|
||||
{
|
||||
get { return Value == null; }
|
||||
}
|
||||
|
||||
public bool IsUnderAssetsFolder
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsNull)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Value == "Assets" || Value.StartsWith("Assets/");
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsStreamingAsset
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsNull)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return FullPath.StartsWith(Application.streamingAssetsPath + "/");
|
||||
}
|
||||
}
|
||||
|
||||
public string FileName
|
||||
{
|
||||
get { return Path.GetFileName(Value); }
|
||||
}
|
||||
|
||||
public string FileNameWithoutExtension
|
||||
{
|
||||
get { return Path.GetFileNameWithoutExtension(Value); }
|
||||
}
|
||||
|
||||
public string Extension
|
||||
{
|
||||
get { return Path.GetExtension(Value); }
|
||||
}
|
||||
|
||||
public UnityPath Parent
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsNull)
|
||||
{
|
||||
return default(UnityPath);
|
||||
}
|
||||
|
||||
return new UnityPath(Path.GetDirectoryName(Value));
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasParent
|
||||
{
|
||||
get
|
||||
{
|
||||
return !string.IsNullOrEmpty(Value);
|
||||
}
|
||||
}
|
||||
|
||||
static readonly char[] EscapeChars = new char[]
|
||||
{
|
||||
'\\',
|
||||
'/',
|
||||
':',
|
||||
'*',
|
||||
'?',
|
||||
'"',
|
||||
'<',
|
||||
'>',
|
||||
'|',
|
||||
};
|
||||
|
||||
static string EscapeFilePath(string path)
|
||||
{
|
||||
foreach (var x in EscapeChars)
|
||||
{
|
||||
path = path.Replace(x, '+');
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
public UnityPath Child(string name)
|
||||
{
|
||||
if (IsNull)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
else if (Value == "")
|
||||
{
|
||||
return new UnityPath(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new UnityPath(Value + "/" + name);
|
||||
}
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
if (IsNull)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return Value.GetHashCode();
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if(obj is UnityPath)
|
||||
{
|
||||
var rhs = (UnityPath)obj;
|
||||
if(Value==null && rhs.Value == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (Value == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (rhs.Value == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Value == rhs.Value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove extension and add suffix
|
||||
/// </summary>
|
||||
/// <param name="prefabPath"></param>
|
||||
/// <param name="suffix"></param>
|
||||
/// <returns></returns>
|
||||
public UnityPath GetAssetFolder(string suffix)
|
||||
{
|
||||
if (!IsUnderAssetsFolder)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
return new UnityPath(
|
||||
string.Format("{0}/{1}{2}",
|
||||
Parent.Value,
|
||||
FileNameWithoutExtension,
|
||||
suffix
|
||||
));
|
||||
}
|
||||
|
||||
UnityPath(string value) : this()
|
||||
{
|
||||
Value = value.Replace("\\", "/");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="unityPath">Relative from unity current path. GetParent(Application.dataPath)</param>
|
||||
/// <returns></returns>
|
||||
public static UnityPath FromUnityPath(string unityPath)
|
||||
{
|
||||
if (String.IsNullOrEmpty(unityPath))
|
||||
{
|
||||
return new UnityPath
|
||||
{
|
||||
Value=""
|
||||
};
|
||||
}
|
||||
return FromFullpath(Path.GetFullPath(unityPath));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region FullPath
|
||||
static string s_basePath;
|
||||
static string BaseFullPath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(s_basePath))
|
||||
{
|
||||
s_basePath = Path.GetFullPath(Application.dataPath + "/..").Replace("\\", "/");
|
||||
}
|
||||
return s_basePath;
|
||||
}
|
||||
}
|
||||
|
||||
static string AssetFullPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return BaseFullPath + "/Assets";
|
||||
}
|
||||
}
|
||||
|
||||
public string FullPath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsNull)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
return Path.Combine(BaseFullPath, Value).Replace("\\", "/");
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsFileExists
|
||||
{
|
||||
get { return File.Exists(FullPath); }
|
||||
}
|
||||
|
||||
public bool IsDirectoryExists
|
||||
{
|
||||
get { return Directory.Exists(FullPath); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="fullPath">C:/path/to/file</param>
|
||||
/// <returns></returns>
|
||||
public static UnityPath FromFullpath(string fullPath)
|
||||
{
|
||||
if(fullPath == null)
|
||||
{
|
||||
fullPath = "";
|
||||
}
|
||||
fullPath = fullPath.Replace("\\", "/");
|
||||
|
||||
if (fullPath == BaseFullPath) {
|
||||
return new UnityPath
|
||||
{
|
||||
Value=""
|
||||
};
|
||||
}
|
||||
else if(fullPath.StartsWith(BaseFullPath + "/"))
|
||||
{
|
||||
return new UnityPath(fullPath.Substring(BaseFullPath.Length + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
return default(UnityPath);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsUnderAssetFolder(string fullPath)
|
||||
{
|
||||
return fullPath.Replace("\\", "/").StartsWith(AssetFullPath);
|
||||
}
|
||||
#endregion
|
||||
|
||||
[Obsolete("Use TraverseDir()")]
|
||||
public IEnumerable<UnityPath> TravserseDir()
|
||||
{
|
||||
return TraverseDir();
|
||||
}
|
||||
|
||||
public IEnumerable<UnityPath> TraverseDir()
|
||||
{
|
||||
if (IsDirectoryExists)
|
||||
{
|
||||
yield return this;
|
||||
|
||||
foreach(var child in ChildDirs)
|
||||
{
|
||||
foreach(var x in child.TraverseDir())
|
||||
{
|
||||
yield return x;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<UnityPath> ChildDirs
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach(var x in Directory.GetDirectories(FullPath))
|
||||
{
|
||||
yield return UnityPath.FromFullpath(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<UnityPath> ChildFiles
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var x in Directory.GetFiles(FullPath))
|
||||
{
|
||||
yield return UnityPath.FromFullpath(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public T GetImporter<T>() where T : AssetImporter
|
||||
{
|
||||
return AssetImporter.GetAtPath(Value) as T;
|
||||
}
|
||||
|
||||
public static UnityPath FromAsset(UnityEngine.Object asset)
|
||||
{
|
||||
return new UnityPath(AssetDatabase.GetAssetPath(asset));
|
||||
}
|
||||
|
||||
public void ImportAsset()
|
||||
{
|
||||
if (!IsUnderAssetsFolder)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
AssetDatabase.ImportAsset(Value);
|
||||
}
|
||||
|
||||
public void EnsureFolder()
|
||||
{
|
||||
if (IsNull)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
if (HasParent)
|
||||
{
|
||||
Parent.EnsureFolder();
|
||||
}
|
||||
|
||||
if (!IsDirectoryExists)
|
||||
{
|
||||
var parent = Parent;
|
||||
// ensure parent
|
||||
parent.ImportAsset();
|
||||
// create
|
||||
AssetDatabase.CreateFolder(
|
||||
parent.Value,
|
||||
Path.GetFileName(Value)
|
||||
);
|
||||
ImportAsset();
|
||||
}
|
||||
}
|
||||
|
||||
public UnityEngine.Object[] GetSubAssets()
|
||||
{
|
||||
if (!IsUnderAssetsFolder)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
return AssetDatabase.LoadAllAssetsAtPath(Value);
|
||||
}
|
||||
|
||||
public void CreateAsset(UnityEngine.Object o)
|
||||
{
|
||||
if (!IsUnderAssetsFolder)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
AssetDatabase.CreateAsset(o, Value);
|
||||
}
|
||||
|
||||
public void AddObjectToAsset(UnityEngine.Object o)
|
||||
{
|
||||
if (!IsUnderAssetsFolder)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
AssetDatabase.AddObjectToAsset(o, Value);
|
||||
}
|
||||
|
||||
public T LoadAsset<T>() where T : UnityEngine.Object
|
||||
{
|
||||
if (!IsUnderAssetsFolder)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
return AssetDatabase.LoadAssetAtPath<T>(Value);
|
||||
}
|
||||
|
||||
public UnityPath GenerateUniqueAssetPath()
|
||||
{
|
||||
if (!IsUnderAssetsFolder)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
return new UnityPath(AssetDatabase.GenerateUniqueAssetPath(Value));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
12
Assets/MeshUtility/Runtime/UnityPath.cs.meta
Normal file
12
Assets/MeshUtility/Runtime/UnityPath.cs.meta
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7b7af908694806c469d62ce0b5b2f06a
|
||||
timeCreated: 1532326996
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7b7af908694806c469d62ce0b5b2f06a
|
||||
timeCreated: 1532326996
|
||||
licenseType: Free
|
||||
guid: 3386db594e76066409ddf28bad123839
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user