using System.Collections; using System.Collections.Generic; using Unity.VisualScripting; using UnityEditor; using UnityEngine; namespace UDE_HAND_INTERACTION { [CustomEditor(typeof(HandStaticPose))] public class HandStaticPoseEditor : Editor { private HandStaticPose _handStaticPose; private VirtualHand virtualHand; private Handedness _lastHandedness; private const float GIZMO_SCALE = 0.007f; SerializedProperty _virtualHand; private void OnEnable() { _handStaticPose = target as HandStaticPose; _virtualHand = serializedObject.FindProperty("_virtualHand"); AssignMissingGhostProvider(); } private void OnDisable() { DestroyGhost(); } public override void OnInspectorGUI() { base.OnInspectorGUI(); GUILayout.Space(10); if (GUILayout.Button("Create Visual Pose Model")) { _handStaticPose.CreateVisualModel(); } if(_handStaticPose._virtualHand != null) { EditorGUILayout.PropertyField(_virtualHand); } DrawGhostMenu(_handStaticPose.HandPose); serializedObject.ApplyModifiedProperties(); } public void OnSceneGUI() { if (SceneView.currentDrawingSceneView == null) { return; } if (virtualHand == null) { return; } EditFingers(); } private void DestroyGhost() { if (virtualHand == null) { return; } DestroyImmediate(virtualHand.gameObject); } private void DrawGhostMenu(HandPose handPose) { if (virtualHand == null || _lastHandedness != handPose.Handedness) { RegenerateGhost(); } _lastHandedness = handPose.Handedness; } private void EditFingers() { DollHand puppet = virtualHand.GetComponent(); if (puppet != null && puppet.JointSets != null) { DrawBonesRotator(puppet.JointSets); } } private void DrawBonesRotator(List bones) { bool anyChanged = false; for (int i = 0; i < FingersData.HAND_JOINT_IDS.Length; i++) { bool changed = false; HandJointId joint = FingersData.HAND_JOINT_IDS[i]; HandFinger finger = FingersData.JOINT_TO_FINGER[(int)joint]; if (_handStaticPose.HandPose.FingersFreedom[(int)finger] == JointFreedom.Free) { continue; } HandJointsSet jointSet = bones.Find(b => b.id == joint); if (jointSet == null) { continue; } Transform transform = jointSet.transform; transform.localRotation = jointSet.RotationOffset * _handStaticPose.HandPose.JointRotations[i]; float scale = GIZMO_SCALE * _handStaticPose.transform.lossyScale.x; Handles.color = EditorConstants.PRIMARY_COLOR; Quaternion entryRotation = transform.rotation; Quaternion rotation = Handles.Disc(entryRotation, transform.position, transform.forward, scale, false, 0); if (rotation != entryRotation) { changed = true; } if (FingersData.HAND_JOINT_CAN_SPREAD[i]) { Handles.color = EditorConstants.SECONDARY_COLOR; Quaternion curlRotation = rotation; rotation = Handles.Disc(curlRotation, transform.position, transform.up, scale, false, 0); if (rotation != curlRotation) { changed = true; } } if (!changed) { continue; } transform.rotation = rotation; Undo.RecordObject(_handStaticPose, "Bone Rotation"); _handStaticPose.HandPose.JointRotations[i] = jointSet.TrackedRotation; anyChanged = true; } if (anyChanged) { EditorUtility.SetDirty(_handStaticPose); } } private void RegenerateGhost() { DestroyGhost(); CreateGhost(); } private void CreateGhost() { if (_handStaticPose._HPResource == null || PrefabUtility.IsPartOfPrefabAsset(_handStaticPose)) { return; } Transform relativeTo = _handStaticPose.transform; VirtualHand ghostPrototype = _handStaticPose._HPResource.GetHand(_handStaticPose.HandPose.Handedness); virtualHand = Instantiate(ghostPrototype, relativeTo); virtualHand.gameObject.hideFlags = HideFlags.HideAndDontSave; Pose relativePose = _handStaticPose.transform.GetPose(Space.World); Pose pose = PoseManager.GlobalPoseScaled(relativeTo, relativePose); virtualHand.SetPose(_handStaticPose.HandPose, relativePose); } void AssignMissingGhostProvider() { if (_handStaticPose._HPResource != null) { return; } TryGetDefaultResProvider(out _handStaticPose._HPResource); } bool TryGetDefaultResProvider(out HandPerfabResource provider) { provider = null; HandPerfabResource[] providers = Resources.FindObjectsOfTypeAll(); if (providers != null && providers.Length > 0) { provider = providers[0]; return true; } string[] assets = AssetDatabase.FindAssets($"t:{nameof(HandPerfabResource)}"); if (assets != null && assets.Length > 0) { string pathPath = AssetDatabase.GUIDToAssetPath(assets[0]); provider = AssetDatabase.LoadAssetAtPath(pathPath); } return provider != null; } } }