From 8015a672712640c10150041f682b55eb48e4c2e7 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 2 Sep 2020 19:05:14 +0900 Subject: [PATCH] =?UTF-8?q?1.0=20=E3=81=8B=E3=82=89=E3=83=90=E3=83=83?= =?UTF-8?q?=E3=82=AF=E3=83=9D=E3=83=BC=E3=83=88=E3=80=82=E3=81=93=E3=81=A3?= =?UTF-8?q?=E3=81=A1=E3=81=A7=E7=AE=A1=E7=90=86=E3=81=99=E3=82=8B=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/MeshUtility/Editor/HumanoidEditor.cs | 324 +++++++++++++ .../MeshUtility/Editor/HumanoidEditor.cs.meta | 11 + Assets/MeshUtility/Runtime/Humanoid.cs | 441 ++++++++++++++++++ Assets/MeshUtility/Runtime/Humanoid.cs.meta | 11 + Assets/MeshUtility/Runtime/HumanoidLoader.cs | 60 +++ .../Runtime/HumanoidLoader.cs.meta | 11 + Assets/MeshUtility/Runtime/UnityPath.cs | 435 +++++++++++++++++ Assets/MeshUtility/Runtime/UnityPath.cs.meta | 12 + .../VRM/UniGLTF/Scripts/IO/UnityPath.cs.meta | 5 +- 9 files changed, 1307 insertions(+), 3 deletions(-) create mode 100644 Assets/MeshUtility/Editor/HumanoidEditor.cs create mode 100644 Assets/MeshUtility/Editor/HumanoidEditor.cs.meta create mode 100644 Assets/MeshUtility/Runtime/Humanoid.cs create mode 100644 Assets/MeshUtility/Runtime/Humanoid.cs.meta create mode 100644 Assets/MeshUtility/Runtime/HumanoidLoader.cs create mode 100644 Assets/MeshUtility/Runtime/HumanoidLoader.cs.meta create mode 100644 Assets/MeshUtility/Runtime/UnityPath.cs create mode 100644 Assets/MeshUtility/Runtime/UnityPath.cs.meta diff --git a/Assets/MeshUtility/Editor/HumanoidEditor.cs b/Assets/MeshUtility/Editor/HumanoidEditor.cs new file mode 100644 index 0000000000..dcdbbac630 --- /dev/null +++ b/Assets/MeshUtility/Editor/HumanoidEditor.cs @@ -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(); + if (animator == null) + { + animator = m_target.gameObject.AddComponent(); + } + 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); + } + } +} diff --git a/Assets/MeshUtility/Editor/HumanoidEditor.cs.meta b/Assets/MeshUtility/Editor/HumanoidEditor.cs.meta new file mode 100644 index 0000000000..dffaaa1862 --- /dev/null +++ b/Assets/MeshUtility/Editor/HumanoidEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 57cc7b16eb4146c4ab5631f538e2489f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MeshUtility/Runtime/Humanoid.cs b/Assets/MeshUtility/Runtime/Humanoid.cs new file mode 100644 index 0000000000..10db7335f1 --- /dev/null +++ b/Assets/MeshUtility/Runtime/Humanoid.cs @@ -0,0 +1,441 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace MeshUtility +{ + /// + /// Bone割り当てを保持する。 + /// ヒエラルキーのルート(おそらくHipsの親)にアタッチする + /// + [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 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 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); + // } + } + + /// + /// ボーン割り当てから UnityEngine.Avatar を生成する + /// + /// + 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 + } + } + + /// + /// nodes からボーンを割り当てる + /// + /// + 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 + } + } + } + + /// + /// Animator から Bone を割り当てる + /// + /// + public bool AssignBonesFromAnimator() + { + var animator = GetComponent(); + 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; + } + } +} diff --git a/Assets/MeshUtility/Runtime/Humanoid.cs.meta b/Assets/MeshUtility/Runtime/Humanoid.cs.meta new file mode 100644 index 0000000000..53fc0f6d8e --- /dev/null +++ b/Assets/MeshUtility/Runtime/Humanoid.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 889d98e41c0e8ff48bae50d1a729c2df +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MeshUtility/Runtime/HumanoidLoader.cs b/Assets/MeshUtility/Runtime/HumanoidLoader.cs new file mode 100644 index 0000000000..2a5d52521c --- /dev/null +++ b/Assets/MeshUtility/Runtime/HumanoidLoader.cs @@ -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() + .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 s_humanTranitBoneNameMap = + HumanTrait.BoneName.ToDictionary( + x => TraitToHumanBone(x), + x => x); + } +} diff --git a/Assets/MeshUtility/Runtime/HumanoidLoader.cs.meta b/Assets/MeshUtility/Runtime/HumanoidLoader.cs.meta new file mode 100644 index 0000000000..029655567a --- /dev/null +++ b/Assets/MeshUtility/Runtime/HumanoidLoader.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 12453a111483e4145852e3b057e065d9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MeshUtility/Runtime/UnityPath.cs b/Assets/MeshUtility/Runtime/UnityPath.cs new file mode 100644 index 0000000000..24404741b8 --- /dev/null +++ b/Assets/MeshUtility/Runtime/UnityPath.cs @@ -0,0 +1,435 @@ +using System; +using System.IO; +using UnityEngine; +using System.Collections.Generic; +#if UNITY_EDITOR +using UnityEditor; +#endif + + +namespace MeshUtility +{ + /// + /// relative path from Unity project root. + /// For AssetDatabase. + /// + 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; + } + } + + /// + /// Remove extension and add suffix + /// + /// + /// + /// + 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("\\", "/"); + } + + /// + /// + /// + /// Relative from unity current path. GetParent(Application.dataPath) + /// + 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); } + } + + /// + /// + /// + /// C:/path/to/file + /// + 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 TravserseDir() + { + return TraverseDir(); + } + + public IEnumerable TraverseDir() + { + if (IsDirectoryExists) + { + yield return this; + + foreach(var child in ChildDirs) + { + foreach(var x in child.TraverseDir()) + { + yield return x; + } + } + } + } + + public IEnumerable ChildDirs + { + get + { + foreach(var x in Directory.GetDirectories(FullPath)) + { + yield return UnityPath.FromFullpath(x); + } + } + } + + public IEnumerable ChildFiles + { + get + { + foreach (var x in Directory.GetFiles(FullPath)) + { + yield return UnityPath.FromFullpath(x); + } + } + } + +#if UNITY_EDITOR + public T GetImporter() 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() where T : UnityEngine.Object + { + if (!IsUnderAssetsFolder) + { + throw new NotImplementedException(); + } + + return AssetDatabase.LoadAssetAtPath(Value); + } + + public UnityPath GenerateUniqueAssetPath() + { + if (!IsUnderAssetsFolder) + { + throw new NotImplementedException(); + } + + return new UnityPath(AssetDatabase.GenerateUniqueAssetPath(Value)); + } + #endif + } +} diff --git a/Assets/MeshUtility/Runtime/UnityPath.cs.meta b/Assets/MeshUtility/Runtime/UnityPath.cs.meta new file mode 100644 index 0000000000..f64923d8bb --- /dev/null +++ b/Assets/MeshUtility/Runtime/UnityPath.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 7b7af908694806c469d62ce0b5b2f06a +timeCreated: 1532326996 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM/UniGLTF/Scripts/IO/UnityPath.cs.meta b/Assets/VRM/UniGLTF/Scripts/IO/UnityPath.cs.meta index f64923d8bb..1de43e29c5 100644 --- a/Assets/VRM/UniGLTF/Scripts/IO/UnityPath.cs.meta +++ b/Assets/VRM/UniGLTF/Scripts/IO/UnityPath.cs.meta @@ -1,8 +1,7 @@ fileFormatVersion: 2 -guid: 7b7af908694806c469d62ce0b5b2f06a -timeCreated: 1532326996 -licenseType: Free +guid: 3386db594e76066409ddf28bad123839 MonoImporter: + externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0