using System.Collections; using System.Collections.Generic; using UnityEditor; using UnityEngine; namespace BNG { [CustomEditor(typeof(HandPoser))] [CanEditMultipleObjects] public class HandPoserEditor : Editor { SerializedProperty currentPose; SerializedProperty animationSpeed; SerializedProperty updateJointRotations; SerializedProperty updateJointPositions; SerializedProperty updateWristPosition; // Auto Pose properties SerializedProperty openHandPose; SerializedProperty closedHandPose; SerializedProperty autoUpdateAutoPose; SerializedProperty fingerTipRadius; SerializedProperty fingerTipOffsets; SerializedProperty WristJoint; SerializedProperty ThumbJoints; SerializedProperty IndexJoints; SerializedProperty MiddleJoints; SerializedProperty RingJoints; SerializedProperty PinkyJoints; SerializedProperty OtherJoints; HandPoser poser; void OnEnable() { currentPose = serializedObject.FindProperty("CurrentPose"); animationSpeed = serializedObject.FindProperty("AnimationSpeed"); updateJointRotations = serializedObject.FindProperty("UpdateJointRotations"); updateJointPositions = serializedObject.FindProperty("UpdateJointPositions"); updateWristPosition = serializedObject.FindProperty("UpdateWristPosition"); openHandPose = serializedObject.FindProperty("OpenHandPose"); closedHandPose = serializedObject.FindProperty("ClosedHandPose"); autoUpdateAutoPose = serializedObject.FindProperty("UpdateContinuously"); fingerTipRadius = serializedObject.FindProperty("FingerTipRadius"); fingerTipOffsets = serializedObject.FindProperty("FingerTipOffsets"); WristJoint = serializedObject.FindProperty("WristJoint"); ThumbJoints = serializedObject.FindProperty("ThumbJoints"); IndexJoints = serializedObject.FindProperty("IndexJoints"); MiddleJoints = serializedObject.FindProperty("MiddleJoints"); RingJoints = serializedObject.FindProperty("RingJoints"); PinkyJoints = serializedObject.FindProperty("PinkyJoints"); OtherJoints = serializedObject.FindProperty("OtherJoints"); } bool showTransformProps, showAnimationProps; public override void OnInspectorGUI() { poser = (HandPoser)target; serializedObject.Update(); GUILayout.Label("Hand Pose", EditorStyles.boldLabel); EditorGUILayout.PropertyField(currentPose); // Show option to auto assign if nothing has been set yet bool notYetSpecified = (poser.ThumbJoints == null || poser.ThumbJoints != null && poser.ThumbJoints.Count == 0) && (poser.IndexJoints == null || poser.IndexJoints != null && poser.IndexJoints.Count == 0) && (poser.MiddleJoints == null || poser.MiddleJoints != null && poser.MiddleJoints.Count == 0) && (poser.RingJoints == null || poser.RingJoints != null && poser.RingJoints.Count == 0) && (poser.PinkyJoints == null || poser.PinkyJoints != null && poser.PinkyJoints.Count == 0) && (poser.OtherJoints == null || poser.OtherJoints != null && poser.OtherJoints.Count == 0); if (notYetSpecified ) { EditorGUILayout.HelpBox("No Bone Transforms have been assigned, would you like to auto assign them now?", MessageType.Warning); if (GUILayout.Button("Auto Assign")) { AutoAssignBones(); // Toggle props showTransformProps = true; } } // Show Transform Properties showTransformProps = EditorGUILayout.Foldout(showTransformProps, "Transform Definitions (" + poser.GetTotalJointsCount() + ")"); if (showTransformProps) { EditorGUILayout.Separator(); EditorGUI.indentLevel++; if (GUILayout.Button("Auto Assign")) { AutoAssignBones(); } EditorGUI.indentLevel++; EditorGUILayout.PropertyField(ThumbJoints); EditorGUILayout.PropertyField(IndexJoints); EditorGUILayout.PropertyField(MiddleJoints); EditorGUILayout.PropertyField(RingJoints); EditorGUILayout.PropertyField(PinkyJoints); EditorGUILayout.PropertyField(OtherJoints); EditorGUILayout.PropertyField(WristJoint); EditorGUI.indentLevel--; } EditorGUILayout.Separator(); EditorGUILayout.PropertyField(animationSpeed); showAnimationProps = EditorGUILayout.Foldout(showAnimationProps, "Update Options"); if (showAnimationProps) { EditorGUILayout.PropertyField(updateJointRotations); EditorGUILayout.PropertyField(updateJointPositions); EditorGUILayout.PropertyField(updateWristPosition); } EditorGUILayout.Separator(); GUILayout.Label("Save Pose", EditorStyles.boldLabel); GUILayout.BeginHorizontal(); var initialColor = GUI.backgroundColor; //GUI.backgroundColor = Color.green; if (GUILayout.Button("Save Pose...")) { SaveHandPoseAs(poser); } // Reset color GUI.backgroundColor = initialColor; GUILayout.EndHorizontal(); EditorGUILayout.Separator(); // Gizmos serializedObject.ApplyModifiedProperties(); } public void AutoAssignBones() { // Reset bones poser.WristJoint = null; poser.ThumbJoints = new List(); poser.IndexJoints = new List(); poser.MiddleJoints = new List(); poser.RingJoints= new List(); poser.PinkyJoints = new List(); poser.OtherJoints = new List(); bool wristFound = false; Transform[] children = poser.GetComponentsInChildren(); int childCount = children.Length; for (int x = 0; x < childCount; x++) { Transform child = children[x]; if(child == null || child.name == null || child == poser.transform) { continue; } // Ignore this bone if(ShouldIgnoreJoint(child)) { continue; } string formattedName = child.name.ToLower(); // Assign Bones to appropriate containers if (formattedName.Contains("thumb")) { poser.ThumbJoints.Add(child); } else if (formattedName.Contains("index")) { poser.IndexJoints.Add(child); } else if (formattedName.Contains("middle")) { poser.MiddleJoints.Add(child); } else if (formattedName.Contains("ring")) { poser.RingJoints.Add(child); } else if (formattedName.Contains("pinky")) { poser.PinkyJoints.Add(child); } else if(wristFound == false && formattedName.Contains("wrist") || (formattedName.EndsWith("hand") && child.childCount > 3)) { poser.WristJoint = child; wristFound = true; } else { poser.OtherJoints.Add(child); } } } public virtual bool ShouldIgnoreJoint(Transform theJoint) { if(!theJoint.gameObject.activeSelf) { return true; ; } // Don't store the handsmodel location. This is only for rendering string loweredName = theJoint.name.ToLower(); if (loweredName == "handsmodel" || loweredName == "lhand" || loweredName == "rhand" || loweredName.StartsWith("tip_collider") || loweredName.StartsWith("hands_col")) { return true; } return false; } public void SaveHandPoseAs(HandPoser poser) { // Open Window HandPoseSaveAs window = (HandPoseSaveAs)EditorWindow.GetWindow(typeof(HandPoseSaveAs)); window.ShowWindow(poser); } //public void LoadHandPose(string poseName) { // var pose = Resources.Load(poseName); // if (pose != null) { // // Update position / rotations // foreach (var f in pose.Joints.OtherJoints) { // Transform thisT = FindChildTransformByName(f.TransformName); // if (thisT) { // thisT.localPosition = f.LocalPosition; // thisT.localRotation = f.LocalRotation; // } // } // poser.CurrentPose = pose; // poser.PoseName = poseName; // } //} public Transform FindChildTransformByName(string transformName) { Transform[] children = poser.GetComponentsInChildren(); int childCount = children.Length; for (int x = 0; x < childCount; x++) { Transform child = children[x]; if (child != null && child.name == transformName) { return child; } } return poser.transform.Find(transformName); } } }