diff --git a/ml_lme/LeapHand.cs b/ml_lme/LeapHand.cs new file mode 100644 index 0000000..23f15b1 --- /dev/null +++ b/ml_lme/LeapHand.cs @@ -0,0 +1,129 @@ +using UnityEngine; + +namespace ml_lme +{ + class LeapHand + { + public enum FingerBone + { + ThumbMetacarpal = 0, + ThumbProximal, + ThumbIntermediate, + ThumbDistal, + IndexMetacarpal, + IndexProximal, + IndexIntermediate, + IndexDistal, + MiddleMetacarpal, + MiddleProximal, + MiddleIntermediate, + MiddleDistal, + RingMetacarpal, + RingProximal, + RingIntermediate, + RingDistal, + PinkyMetacarpal, + PinkyProximal, + PinkyIntermediate, + PinkyDistal + }; + + readonly Transform m_root = null; + readonly Transform m_wrist = null; + readonly GameObject m_mesh = null; + readonly Transform[] m_fingersBones = null; + readonly Quaternion[] m_initialRotations = null; + + public LeapHand(Transform p_root, bool p_left) + { + m_fingersBones = new Transform[20]; + m_initialRotations = new Quaternion[20]; + + m_root = p_root; + if(m_root != null) + { + m_mesh = m_root.Find(p_left ? "GenericHandL" : "GenericHandR")?.gameObject; + m_wrist = m_root.Find(p_left ? "LeftHand/Wrist" : "RightHand/Wrist"); + if(m_wrist != null) + { + m_fingersBones[0] = null; // Actual thumb-meta, look at Leap Motion docs, dummy, it's zero point + m_fingersBones[1] = m_wrist.Find("thumb_meta"); + m_fingersBones[2] = m_wrist.Find("thumb_meta/thumb_a"); + m_fingersBones[3] = m_wrist.Find("thumb_meta/thumb_a/thumb_b"); + + m_fingersBones[4] = m_wrist.Find("index_meta"); + m_fingersBones[5] = m_wrist.Find("index_meta/index_a"); + m_fingersBones[6] = m_wrist.Find("index_meta/index_a/index_b"); + m_fingersBones[7] = m_wrist.Find("index_meta/index_a/index_b/index_c"); + + m_fingersBones[8] = m_wrist.Find("middle_meta"); + m_fingersBones[9] = m_wrist.Find("middle_meta/middle_a"); + m_fingersBones[10] = m_wrist.Find("middle_meta/middle_a/middle_b"); + m_fingersBones[11] = m_wrist.Find("middle_meta/middle_a/middle_b/middle_c"); + + m_fingersBones[12] = m_wrist.Find("ring_meta"); + m_fingersBones[13] = m_wrist.Find("ring_meta/ring_a"); + m_fingersBones[14] = m_wrist.Find("ring_meta/ring_a/ring_b"); + m_fingersBones[15] = m_wrist.Find("ring_meta/ring_a/ring_b/ring_c"); + + m_fingersBones[16] = m_wrist.Find("pinky_meta"); + m_fingersBones[17] = m_wrist.Find("pinky_meta/pinky_a"); + m_fingersBones[18] = m_wrist.Find("pinky_meta/pinky_a/pinky_b"); + m_fingersBones[19] = m_wrist.Find("pinky_meta/pinky_a/pinky_b/pinky_c"); + } + } + + for(int i = 0; i < 20; i++) + { + if(m_fingersBones[i] != null) + m_initialRotations[i] = m_fingersBones[i].localRotation; + } + } + + public void Update(LeapParser.HandData p_data) + { + if(m_wrist != null) + { + m_wrist.position = p_data.m_position; + m_wrist.rotation = p_data.m_rotation; + + for(int i = 0; i < 20; i++) + { + if(m_fingersBones[i] != null) + { + //m_fingers[i].position = p_data.m_fingerPosition[i]; + m_fingersBones[i].rotation = p_data.m_fingerRotation[i]; + } + } + + m_wrist.localPosition = Vector3.zero; + m_wrist.localRotation = Quaternion.identity; + } + } + + public void Reset() + { + if(m_wrist != null) + { + m_wrist.localPosition = Vector3.zero; + m_wrist.localRotation = Quaternion.identity; + } + + for(int i = 0; i < 20; i++) + { + if(m_fingersBones[i] != null) + m_fingersBones[i].localRotation = m_initialRotations[i]; + } + } + + public Transform GetRoot() => m_root; + public Transform GetWrist() => m_wrist; + public Transform GetFingersBone(FingerBone p_bone) => m_fingersBones[(int)p_bone]; + + public void SetMeshActive(bool p_state) + { + if(m_mesh != null) + m_mesh.SetActive(p_state); + } + } +} diff --git a/ml_lme/LeapInput.cs b/ml_lme/LeapInput.cs index fafbb50..8a31b3b 100644 --- a/ml_lme/LeapInput.cs +++ b/ml_lme/LeapInput.cs @@ -34,7 +34,7 @@ namespace ml_lme m_inVR = Utils.IsInVR(); - m_handRayLeft = LeapTracking.Instance.GetLeftHand().gameObject.AddComponent(); + m_handRayLeft = LeapTracking.Instance.GetLeftHand().GetRoot().gameObject.AddComponent(); m_handRayLeft.hand = true; m_handRayLeft.generalMask = -269; m_handRayLeft.isInteractionRay = true; @@ -56,7 +56,7 @@ namespace ml_lme m_lineLeft.receiveShadows = false; m_handRayLeft.lineRenderer = m_lineLeft; - m_handRayRight = LeapTracking.Instance.GetRightHand().gameObject.AddComponent(); + m_handRayRight = LeapTracking.Instance.GetRightHand().GetRoot().gameObject.AddComponent(); m_handRayRight.hand = false; m_handRayRight.generalMask = -269; m_handRayRight.isInteractionRay = true; @@ -176,36 +176,36 @@ namespace ml_lme base._inputManager.gestureLeftRaw = 0f; // Finger Point & Finger Gun - if((base._inputManager.fingerCurlLeftIndex < 0.2f) && (base._inputManager.fingerCurlLeftMiddle > 0.75f) && - (base._inputManager.fingerCurlLeftRing > 0.75f) && (base._inputManager.fingerCurlLeftPinky > 0.75f)) + if((base._inputManager.fingerFullCurlNormalizedLeftIndex < 0.2f) && (base._inputManager.fingerFullCurlNormalizedLeftMiddle > 0.75f) && + (base._inputManager.fingerFullCurlNormalizedLeftRing > 0.75f) && (base._inputManager.fingerFullCurlNormalizedLeftPinky > 0.75f)) { - base._inputManager.gestureLeftRaw = (base._inputManager.fingerCurlLeftThumb >= 0.5f) ? 4f : 3f; + base._inputManager.gestureLeftRaw = (base._inputManager.fingerFullCurlNormalizedLeftThumb >= 0.5f) ? 4f : 3f; } // Peace Sign - if((base._inputManager.fingerCurlLeftIndex < 0.2f) && (base._inputManager.fingerCurlLeftMiddle < 0.2f) && - (base._inputManager.fingerCurlLeftRing > 0.75f) && (base._inputManager.fingerCurlLeftPinky > 0.75f)) + if((base._inputManager.fingerFullCurlNormalizedLeftIndex < 0.2f) && (base._inputManager.fingerFullCurlNormalizedLeftMiddle < 0.2f) && + (base._inputManager.fingerFullCurlNormalizedLeftRing > 0.75f) && (base._inputManager.fingerFullCurlNormalizedLeftPinky > 0.75f)) { base._inputManager.gestureLeftRaw = 5f; } // Rock and Roll - if((base._inputManager.fingerCurlLeftIndex < 0.2f) && (base._inputManager.fingerCurlLeftMiddle > 0.75f) && - (base._inputManager.fingerCurlLeftRing > 0.75f) && (base._inputManager.fingerCurlLeftPinky < 0.5f)) + if((base._inputManager.fingerFullCurlNormalizedLeftIndex < 0.2f) && (base._inputManager.fingerFullCurlNormalizedLeftMiddle > 0.75f) && + (base._inputManager.fingerFullCurlNormalizedLeftRing > 0.75f) && (base._inputManager.fingerFullCurlNormalizedLeftPinky < 0.5f)) { base._inputManager.gestureLeftRaw = 6f; } // Fist & Thumbs Up - if((base._inputManager.fingerCurlLeftIndex > 0.5f) && (base._inputManager.fingerCurlLeftMiddle > 0.5f) && - (base._inputManager.fingerCurlLeftRing > 0.5f) && (base._inputManager.fingerCurlLeftPinky > 0.5f)) + if((base._inputManager.fingerFullCurlNormalizedLeftIndex > 0.5f) && (base._inputManager.fingerFullCurlNormalizedLeftMiddle > 0.5f) && + (base._inputManager.fingerFullCurlNormalizedLeftRing > 0.5f) && (base._inputManager.fingerFullCurlNormalizedLeftPinky > 0.5f)) { - base._inputManager.gestureLeftRaw = (base._inputManager.fingerCurlLeftThumb >= 0.5f) ? ((l_data.m_leftHand.m_grabStrength - 0.5f) * 2f) : 2f; + base._inputManager.gestureLeftRaw = (base._inputManager.fingerFullCurlNormalizedLeftThumb >= 0.5f) ? ((l_data.m_leftHand.m_grabStrength - 0.5f) * 2f) : 2f; } // Open Hand - if((base._inputManager.fingerCurlLeftIndex < 0.2f) && (base._inputManager.fingerCurlLeftMiddle < 0.2f) && - (base._inputManager.fingerCurlLeftRing < 0.2f) && (base._inputManager.fingerCurlLeftPinky < 0.2f)) + if((base._inputManager.fingerFullCurlNormalizedLeftIndex < 0.2f) && (base._inputManager.fingerFullCurlNormalizedLeftMiddle < 0.2f) && + (base._inputManager.fingerFullCurlNormalizedLeftRing < 0.2f) && (base._inputManager.fingerFullCurlNormalizedLeftPinky < 0.2f)) { base._inputManager.gestureLeftRaw = -1f; } @@ -236,36 +236,36 @@ namespace ml_lme base._inputManager.gestureRightRaw = 0f; // Finger Point & Finger Gun - if((base._inputManager.fingerCurlRightIndex < 0.2f) && (base._inputManager.fingerCurlRightMiddle > 0.75f) && - (base._inputManager.fingerCurlRightRing > 0.75f) && (base._inputManager.fingerCurlRightPinky > 0.75f)) + if((base._inputManager.fingerFullCurlNormalizedRightIndex < 0.2f) && (base._inputManager.fingerFullCurlNormalizedRightMiddle > 0.75f) && + (base._inputManager.fingerFullCurlNormalizedRightRing > 0.75f) && (base._inputManager.fingerFullCurlNormalizedRightPinky > 0.75f)) { - base._inputManager.gestureRightRaw = (base._inputManager.fingerCurlRightThumb >= 0.5f) ? 4f : 3f; + base._inputManager.gestureRightRaw = (base._inputManager.fingerFullCurlNormalizedRightThumb >= 0.5f) ? 4f : 3f; } // Peace Sign - if((base._inputManager.fingerCurlRightIndex < 0.2f) && (base._inputManager.fingerCurlRightMiddle < 0.2f) && - (base._inputManager.fingerCurlRightRing > 0.75f) && (base._inputManager.fingerCurlRightPinky > 0.75f)) + if((base._inputManager.fingerFullCurlNormalizedRightIndex < 0.2f) && (base._inputManager.fingerFullCurlNormalizedRightMiddle < 0.2f) && + (base._inputManager.fingerFullCurlNormalizedRightRing > 0.75f) && (base._inputManager.fingerFullCurlNormalizedRightPinky > 0.75f)) { base._inputManager.gestureRightRaw = 5f; } // Rock and Roll - if((base._inputManager.fingerCurlRightIndex < 0.2f) && (base._inputManager.fingerCurlRightMiddle > 0.75f) && - (base._inputManager.fingerCurlRightRing > 0.75f) && (base._inputManager.fingerCurlRightPinky < 0.5f)) + if((base._inputManager.fingerFullCurlNormalizedRightIndex < 0.2f) && (base._inputManager.fingerFullCurlNormalizedRightMiddle > 0.75f) && + (base._inputManager.fingerFullCurlNormalizedRightRing > 0.75f) && (base._inputManager.fingerFullCurlNormalizedRightPinky < 0.5f)) { base._inputManager.gestureRightRaw = 6f; } // Fist & Thumbs Up - if((base._inputManager.fingerCurlRightIndex > 0.5f) && (base._inputManager.fingerCurlRightMiddle > 0.5f) && - (base._inputManager.fingerCurlRightRing > 0.5f) && (base._inputManager.fingerCurlRightPinky > 0.5f)) + if((base._inputManager.fingerFullCurlNormalizedRightIndex > 0.5f) && (base._inputManager.fingerFullCurlNormalizedRightMiddle > 0.5f) && + (base._inputManager.fingerFullCurlNormalizedRightRing > 0.5f) && (base._inputManager.fingerFullCurlNormalizedRightPinky > 0.5f)) { - base._inputManager.gestureRightRaw = (base._inputManager.fingerCurlRightThumb >= 0.5f) ? ((l_data.m_rightHand.m_grabStrength - 0.5f) * 2f) : 2f; + base._inputManager.gestureRightRaw = (base._inputManager.fingerFullCurlNormalizedRightThumb >= 0.5f) ? ((l_data.m_rightHand.m_grabStrength - 0.5f) * 2f) : 2f; } // Open Hand - if((base._inputManager.fingerCurlRightIndex < 0.2f) && (base._inputManager.fingerCurlRightMiddle < 0.2f) && - (base._inputManager.fingerCurlRightRing < 0.2f) && (base._inputManager.fingerCurlRightPinky < 0.2f)) + if((base._inputManager.fingerFullCurlNormalizedRightIndex < 0.2f) && (base._inputManager.fingerFullCurlNormalizedRightMiddle < 0.2f) && + (base._inputManager.fingerFullCurlNormalizedRightRing < 0.2f) && (base._inputManager.fingerFullCurlNormalizedRightPinky < 0.2f)) { base._inputManager.gestureRightRaw = -1f; } @@ -466,33 +466,71 @@ namespace ml_lme // Arbitrary void SetFingersInput(LeapParser.HandData p_hand, bool p_left) { - // Game has spreads in range of [0;1], but mod now operates in range of [-1;1] - // So spreads will be normalized towards game's range if(p_left) { - base._inputManager.fingerCurlLeftThumb = p_hand.m_bends[0]; - base._inputManager.fingerCurlLeftIndex = p_hand.m_bends[1]; - base._inputManager.fingerCurlLeftMiddle = p_hand.m_bends[2]; - base._inputManager.fingerCurlLeftRing = p_hand.m_bends[3]; - base._inputManager.fingerCurlLeftPinky = p_hand.m_bends[4]; - base._inputManager.fingerSpreadLeftThumb = 1f - (p_hand.m_spreads[0] * 0.5f + 0.5f); - base._inputManager.fingerSpreadLeftIndex = 1f - (p_hand.m_spreads[1] * 0.5f + 0.5f); - base._inputManager.fingerSpreadLeftMiddle = 1f - (p_hand.m_spreads[2] * 0.5f + 0.5f); - base._inputManager.fingerSpreadLeftRing = 1f - (p_hand.m_spreads[3] * 0.5f + 0.5f); - base._inputManager.fingerSpreadLeftPinky = 1f - (p_hand.m_spreads[4] * 0.5f + 0.5f); + base._inputManager.finger1StretchedLeftThumb = LeapTracked.ms_lastLeftFingerBones[0]; + base._inputManager.finger2StretchedLeftThumb = LeapTracked.ms_lastLeftFingerBones[1]; + base._inputManager.finger3StretchedLeftThumb = LeapTracked.ms_lastLeftFingerBones[2]; + base._inputManager.fingerSpreadLeftThumb = LeapTracked.ms_lastLeftFingerBones[3]; + + base._inputManager.finger1StretchedLeftIndex = LeapTracked.ms_lastLeftFingerBones[4]; + base._inputManager.finger2StretchedLeftIndex = LeapTracked.ms_lastLeftFingerBones[5]; + base._inputManager.finger3StretchedLeftIndex = LeapTracked.ms_lastLeftFingerBones[6]; + base._inputManager.fingerSpreadLeftIndex = LeapTracked.ms_lastLeftFingerBones[7]; + + base._inputManager.finger1StretchedLeftMiddle = LeapTracked.ms_lastLeftFingerBones[8]; + base._inputManager.finger2StretchedLeftMiddle = LeapTracked.ms_lastLeftFingerBones[9]; + base._inputManager.finger3StretchedLeftMiddle = LeapTracked.ms_lastLeftFingerBones[10]; + base._inputManager.fingerSpreadLeftMiddle = LeapTracked.ms_lastLeftFingerBones[11]; + + base._inputManager.finger1StretchedLeftRing = LeapTracked.ms_lastLeftFingerBones[12]; + base._inputManager.finger2StretchedLeftRing = LeapTracked.ms_lastLeftFingerBones[13]; + base._inputManager.finger3StretchedLeftRing = LeapTracked.ms_lastLeftFingerBones[14]; + base._inputManager.fingerSpreadLeftRing = LeapTracked.ms_lastLeftFingerBones[15]; + + base._inputManager.finger1StretchedLeftPinky = LeapTracked.ms_lastLeftFingerBones[16]; + base._inputManager.finger2StretchedLeftPinky = LeapTracked.ms_lastLeftFingerBones[17]; + base._inputManager.finger3StretchedLeftPinky = LeapTracked.ms_lastLeftFingerBones[18]; + base._inputManager.fingerSpreadLeftPinky = LeapTracked.ms_lastLeftFingerBones[19]; + + base._inputManager.fingerFullCurlNormalizedLeftThumb = p_hand.m_bends[0]; + base._inputManager.fingerFullCurlNormalizedLeftIndex = p_hand.m_bends[1]; + base._inputManager.fingerFullCurlNormalizedLeftMiddle = p_hand.m_bends[2]; + base._inputManager.fingerFullCurlNormalizedLeftRing = p_hand.m_bends[3]; + base._inputManager.fingerFullCurlNormalizedLeftPinky = p_hand.m_bends[4]; } else { - base._inputManager.fingerCurlRightThumb = p_hand.m_bends[0]; - base._inputManager.fingerCurlRightIndex = p_hand.m_bends[1]; - base._inputManager.fingerCurlRightMiddle = p_hand.m_bends[2]; - base._inputManager.fingerCurlRightRing = p_hand.m_bends[3]; - base._inputManager.fingerCurlRightPinky = p_hand.m_bends[4]; - base._inputManager.fingerSpreadRightThumb = 1f - (p_hand.m_spreads[0] * 0.5f + 0.5f); - base._inputManager.fingerSpreadRightIndex = 1f - (p_hand.m_spreads[1] * 0.5f + 0.5f); - base._inputManager.fingerSpreadRightMiddle = 1f - (p_hand.m_spreads[2] * 0.5f + 0.5f); - base._inputManager.fingerSpreadRightRing = 1f - (p_hand.m_spreads[3] * 0.5f + 0.5f); - base._inputManager.fingerSpreadRightPinky = 1f - (p_hand.m_spreads[4] * 0.5f + 0.5f); + base._inputManager.finger1StretchedRightThumb = LeapTracked.ms_lastRightFingerBones[0]; + base._inputManager.finger2StretchedRightThumb = LeapTracked.ms_lastRightFingerBones[1]; + base._inputManager.finger3StretchedRightThumb = LeapTracked.ms_lastRightFingerBones[2]; + base._inputManager.fingerSpreadRightThumb = LeapTracked.ms_lastRightFingerBones[3]; + + base._inputManager.finger1StretchedRightIndex = LeapTracked.ms_lastRightFingerBones[4]; + base._inputManager.finger2StretchedRightIndex = LeapTracked.ms_lastRightFingerBones[5]; + base._inputManager.finger3StretchedRightIndex = LeapTracked.ms_lastRightFingerBones[6]; + base._inputManager.fingerSpreadRightIndex = LeapTracked.ms_lastRightFingerBones[7]; + + base._inputManager.finger1StretchedRightMiddle = LeapTracked.ms_lastRightFingerBones[8]; + base._inputManager.finger2StretchedRightMiddle = LeapTracked.ms_lastRightFingerBones[9]; + base._inputManager.finger3StretchedRightMiddle = LeapTracked.ms_lastRightFingerBones[10]; + base._inputManager.fingerSpreadRightMiddle = LeapTracked.ms_lastRightFingerBones[11]; + + base._inputManager.finger1StretchedRightRing = LeapTracked.ms_lastRightFingerBones[12]; + base._inputManager.finger2StretchedRightRing = LeapTracked.ms_lastRightFingerBones[13]; + base._inputManager.finger3StretchedRightRing = LeapTracked.ms_lastRightFingerBones[14]; + base._inputManager.fingerSpreadRightRing = LeapTracked.ms_lastRightFingerBones[15]; + + base._inputManager.finger1StretchedRightPinky = LeapTracked.ms_lastRightFingerBones[16]; + base._inputManager.finger2StretchedRightPinky = LeapTracked.ms_lastRightFingerBones[17]; + base._inputManager.finger3StretchedRightPinky = LeapTracked.ms_lastRightFingerBones[18]; + base._inputManager.fingerSpreadRightPinky = LeapTracked.ms_lastRightFingerBones[19]; + + base._inputManager.fingerFullCurlNormalizedRightThumb = p_hand.m_bends[0]; + base._inputManager.fingerFullCurlNormalizedRightIndex = p_hand.m_bends[1]; + base._inputManager.fingerFullCurlNormalizedRightMiddle = p_hand.m_bends[2]; + base._inputManager.fingerFullCurlNormalizedRightRing = p_hand.m_bends[3]; + base._inputManager.fingerFullCurlNormalizedRightPinky = p_hand.m_bends[4]; } } @@ -500,29 +538,69 @@ namespace ml_lme { if(p_left) { - base._inputManager.fingerCurlLeftThumb = 0f; - base._inputManager.fingerCurlLeftIndex = 0f; - base._inputManager.fingerCurlLeftMiddle = 0f; - base._inputManager.fingerCurlLeftRing = 0f; - base._inputManager.fingerCurlLeftPinky = 0f; - base._inputManager.fingerSpreadLeftThumb = 0.5f; - base._inputManager.fingerSpreadLeftIndex = 0.5f; - base._inputManager.fingerSpreadLeftMiddle = 0.5f; - base._inputManager.fingerSpreadLeftRing = 0.5f; - base._inputManager.fingerSpreadLeftPinky = 0.5f; + base._inputManager.finger1StretchedLeftThumb = -0.5f; + base._inputManager.finger2StretchedLeftThumb = 0.7f; + base._inputManager.finger3StretchedLeftThumb = 0.7f; + base._inputManager.fingerSpreadLeftThumb = 0f; + + base._inputManager.finger1StretchedLeftIndex = 0.5f; + base._inputManager.finger2StretchedLeftIndex = 0.7f; + base._inputManager.finger3StretchedLeftIndex = 0.7f; + base._inputManager.fingerSpreadLeftIndex = 0f; + + base._inputManager.finger1StretchedLeftMiddle = 0.5f; + base._inputManager.finger2StretchedLeftMiddle = 0.7f; + base._inputManager.finger3StretchedLeftMiddle = 0.7f; + base._inputManager.fingerSpreadLeftMiddle = 0f; + + base._inputManager.finger1StretchedLeftRing = 0.5f; + base._inputManager.finger2StretchedLeftRing = 0.7f; + base._inputManager.finger3StretchedLeftRing = 0.7f; + base._inputManager.fingerSpreadLeftRing = 0f; + + base._inputManager.finger1StretchedLeftPinky = 0.5f; + base._inputManager.finger2StretchedLeftPinky = 0.7f; + base._inputManager.finger3StretchedLeftPinky = 0.7f; + base._inputManager.fingerSpreadLeftPinky = 0f; + + base._inputManager.fingerFullCurlNormalizedLeftThumb = 0f; + base._inputManager.fingerFullCurlNormalizedLeftIndex = 0f; + base._inputManager.fingerFullCurlNormalizedLeftMiddle = 0f; + base._inputManager.fingerFullCurlNormalizedLeftRing = 0f; + base._inputManager.fingerFullCurlNormalizedLeftPinky = 0f; } else { - base._inputManager.fingerCurlRightThumb = 0f; - base._inputManager.fingerCurlRightIndex = 0f; - base._inputManager.fingerCurlRightMiddle = 0f; - base._inputManager.fingerCurlRightRing = 0f; - base._inputManager.fingerCurlRightPinky = 0f; - base._inputManager.fingerSpreadRightThumb = 0.5f; - base._inputManager.fingerSpreadRightIndex = 0.5f; - base._inputManager.fingerSpreadRightMiddle = 0.5f; - base._inputManager.fingerSpreadRightRing = 0.5f; - base._inputManager.fingerSpreadRightPinky = 0.5f; + base._inputManager.finger1StretchedRightThumb = -0.5f; + base._inputManager.finger2StretchedRightThumb = 0.7f; + base._inputManager.finger3StretchedRightThumb = 0.7f; + base._inputManager.fingerSpreadRightThumb = 0f; + + base._inputManager.finger1StretchedRightIndex = 0.5f; + base._inputManager.finger2StretchedRightIndex = 0.7f; + base._inputManager.finger3StretchedRightIndex = 0.7f; + base._inputManager.fingerSpreadRightIndex = 0f; + + base._inputManager.finger1StretchedRightMiddle = 0.5f; + base._inputManager.finger2StretchedRightMiddle = 0.7f; + base._inputManager.finger3StretchedRightMiddle = 0.7f; + base._inputManager.fingerSpreadRightMiddle = 0f; + + base._inputManager.finger1StretchedRightRing = 0.5f; + base._inputManager.finger2StretchedRightRing = 0.7f; + base._inputManager.finger3StretchedRightRing = 0.7f; + base._inputManager.fingerSpreadRightRing = 0f; + + base._inputManager.finger1StretchedRightPinky = 0.5f; + base._inputManager.finger2StretchedRightPinky = 0.7f; + base._inputManager.finger3StretchedRightPinky = 0.7f; + base._inputManager.fingerSpreadRightPinky = 0f; + + base._inputManager.fingerFullCurlNormalizedRightThumb = 0f; + base._inputManager.fingerFullCurlNormalizedRightIndex = 0f; + base._inputManager.fingerFullCurlNormalizedRightMiddle = 0f; + base._inputManager.fingerFullCurlNormalizedRightRing = 0f; + base._inputManager.fingerFullCurlNormalizedRightPinky = 0f; } } diff --git a/ml_lme/LeapManager.cs b/ml_lme/LeapManager.cs index f9fd020..e6a3eab 100644 --- a/ml_lme/LeapManager.cs +++ b/ml_lme/LeapManager.cs @@ -1,226 +1,226 @@ -using ABI.CCK.Components; -using ABI_RC.Core.Player; -using ABI_RC.Systems.InputManagement; -using System.Collections; -using UnityEngine; - -namespace ml_lme -{ - [DisallowMultipleComponent] - class LeapManager : MonoBehaviour - { - public static LeapManager Instance { get; private set; } = null; - - Leap.Controller m_leapController = null; - LeapParser.LeapData m_leapData = null; - - LeapTracking m_leapTracking = null; - LeapTracked m_leapTracked = null; - LeapInput m_leapInput = null; - - void Awake() - { - if(Instance == null) - Instance = this; - - m_leapController = new Leap.Controller(); - m_leapData = new LeapParser.LeapData(); - - DontDestroyOnLoad(this); - - m_leapController.Device += this.OnLeapDeviceInitialized; - m_leapController.DeviceFailure += this.OnLeapDeviceFailure; - m_leapController.DeviceLost += this.OnLeapDeviceLost; - m_leapController.Connect += this.OnLeapServiceConnect; - m_leapController.Disconnect += this.OnLeapServiceDisconnect; - - Settings.EnabledChange += this.OnEnableChange; - Settings.TrackingModeChange += this.OnTrackingModeChange; - - m_leapTracking = new GameObject("[LeapTrackingRoot]").AddComponent(); - m_leapTracking.transform.parent = this.transform; - - OnEnableChange(Settings.Enabled); - OnTrackingModeChange(Settings.TrackingMode); - - MelonLoader.MelonCoroutines.Start(WaitForObjects()); - } - - void OnDestroy() - { - if(Instance == this) - Instance = null; - - m_leapController.StopConnection(); - m_leapController.Device -= this.OnLeapDeviceInitialized; - m_leapController.DeviceFailure -= this.OnLeapDeviceFailure; - m_leapController.DeviceLost -= this.OnLeapDeviceLost; - m_leapController.Connect -= this.OnLeapServiceConnect; - m_leapController.Disconnect -= this.OnLeapServiceDisconnect; - m_leapController.Dispose(); - m_leapController = null; - - if(m_leapTracking != null) - Object.Destroy(m_leapTracking); - m_leapTracking = null; - - if(m_leapTracked != null) - Object.Destroy(m_leapTracked); - m_leapTracked = null; - - if(m_leapInput != null) - { - if(CVRInputManager.Instance != null) - CVRInputManager.Instance.DestroyInputModule(m_leapInput); - else - m_leapInput.ModuleDestroyed(); - } - m_leapInput = null; - - Settings.EnabledChange -= this.OnEnableChange; - Settings.TrackingModeChange -= this.OnTrackingModeChange; - } - - IEnumerator WaitForObjects() - { - while(CVRInputManager.Instance == null) - yield return null; - - while(PlayerSetup.Instance == null) - yield return null; - - while(LeapTracking.Instance == null) - yield return null; - - m_leapInput = new LeapInput(); - CVRInputManager.Instance.AddInputModule(m_leapInput); - - m_leapTracked = PlayerSetup.Instance.gameObject.AddComponent(); - } - - void Update() - { - if(Settings.Enabled) - { - m_leapData.Reset(); - - if(m_leapController.IsConnected) - { - Leap.Frame l_frame = m_leapController.Frame(); - LeapParser.ParseFrame(l_frame, m_leapData); - } - } - } - - public LeapParser.LeapData GetLatestData() => m_leapData; - - // Device events - void OnLeapDeviceInitialized(object p_sender, Leap.DeviceEventArgs p_args) - { - if(Settings.Enabled) - { - m_leapController.SubscribeToDeviceEvents(p_args.Device); - UpdateDeviceTrackingMode(); - } - - Utils.ShowHUDNotification("Leap Motion Extension", "Device initialized"); - } - - void OnLeapDeviceFailure(object p_sender, Leap.DeviceFailureEventArgs p_args) - { - Utils.ShowHUDNotification("Leap Motion Extension", "Device failure", "Code " + p_args.ErrorCode + ": " + p_args.ErrorMessage); - } - - void OnLeapDeviceLost(object p_sender, Leap.DeviceEventArgs p_args) - { - m_leapController.UnsubscribeFromDeviceEvents(p_args.Device); - - Utils.ShowHUDNotification("Leap Motion Extension", "Device lost"); - } - - void OnLeapServiceConnect(object p_sender, Leap.ConnectionEventArgs p_args) - { - Utils.ShowHUDNotification("Leap Motion Extension", "Service connected"); - } - - void OnLeapServiceDisconnect(object p_sender, Leap.ConnectionLostEventArgs p_args) - { - Utils.ShowHUDNotification("Leap Motion Extension", "Service disconnected"); - } - - // Settings - void OnEnableChange(bool p_state) - { - if(p_state) - { - m_leapController.StartConnection(); - UpdateDeviceTrackingMode(); - } - else - m_leapController.StopConnection(); - } - - void OnTrackingModeChange(Settings.LeapTrackingMode p_mode) - { - if(Settings.Enabled) - UpdateDeviceTrackingMode(); - } - - // Game events - internal void OnAvatarClear() - { - if(m_leapTracking != null) - m_leapTracking.OnAvatarClear(); - if(m_leapTracked != null) - m_leapTracked.OnAvatarClear(); - } - - internal void OnAvatarSetup() - { - if(m_leapTracking != null) - m_leapTracking.OnAvatarSetup(); - - if(m_leapTracked != null) - m_leapTracked.OnAvatarSetup(); - } - - internal void OnAvatarReinitialize() - { - if(m_leapTracked != null) - m_leapTracked.OnAvatarReinitialize(); - } - - internal void OnRayScale(float p_scale) - { - m_leapInput?.OnRayScale(p_scale); - } - - internal void OnPlayspaceScale(float p_relation) - { - if(m_leapTracking != null) - m_leapTracking.OnPlayspaceScale(p_relation); - } - - internal void OnPickupGrab(CVRPickupObject p_pickup) - { - m_leapInput?.OnPickupGrab(p_pickup); - } - - // Arbitrary - void UpdateDeviceTrackingMode() - { - m_leapController.ClearPolicy(Leap.Controller.PolicyFlag.POLICY_OPTIMIZE_SCREENTOP, null); - m_leapController.ClearPolicy(Leap.Controller.PolicyFlag.POLICY_OPTIMIZE_HMD, null); - - switch(Settings.TrackingMode) - { - case Settings.LeapTrackingMode.Screentop: - m_leapController.SetPolicy(Leap.Controller.PolicyFlag.POLICY_OPTIMIZE_SCREENTOP, null); - break; - case Settings.LeapTrackingMode.HMD: - m_leapController.SetPolicy(Leap.Controller.PolicyFlag.POLICY_OPTIMIZE_HMD, null); - break; - } - } - } -} +using ABI.CCK.Components; +using ABI_RC.Core.Player; +using ABI_RC.Systems.InputManagement; +using System.Collections; +using UnityEngine; + +namespace ml_lme +{ + [DisallowMultipleComponent] + class LeapManager : MonoBehaviour + { + public static LeapManager Instance { get; private set; } = null; + + Leap.Controller m_leapController = null; + LeapParser.LeapData m_leapData = null; + + LeapTracking m_leapTracking = null; + LeapTracked m_leapTracked = null; + LeapInput m_leapInput = null; + + void Awake() + { + if(Instance == null) + Instance = this; + + m_leapController = new Leap.Controller(); + m_leapData = new LeapParser.LeapData(); + + DontDestroyOnLoad(this); + + m_leapController.Device += this.OnLeapDeviceInitialized; + m_leapController.DeviceFailure += this.OnLeapDeviceFailure; + m_leapController.DeviceLost += this.OnLeapDeviceLost; + m_leapController.Connect += this.OnLeapServiceConnect; + m_leapController.Disconnect += this.OnLeapServiceDisconnect; + + Settings.EnabledChange += this.OnEnableChange; + Settings.TrackingModeChange += this.OnTrackingModeChange; + + m_leapTracking = new GameObject("[LeapTrackingRoot]").AddComponent(); + m_leapTracking.transform.parent = this.transform; + + OnEnableChange(Settings.Enabled); + OnTrackingModeChange(Settings.TrackingMode); + + MelonLoader.MelonCoroutines.Start(WaitForObjects()); + } + + void OnDestroy() + { + if(Instance == this) + Instance = null; + + m_leapController.StopConnection(); + m_leapController.Device -= this.OnLeapDeviceInitialized; + m_leapController.DeviceFailure -= this.OnLeapDeviceFailure; + m_leapController.DeviceLost -= this.OnLeapDeviceLost; + m_leapController.Connect -= this.OnLeapServiceConnect; + m_leapController.Disconnect -= this.OnLeapServiceDisconnect; + m_leapController.Dispose(); + m_leapController = null; + + if(m_leapTracking != null) + Object.Destroy(m_leapTracking); + m_leapTracking = null; + + if(m_leapTracked != null) + Object.Destroy(m_leapTracked); + m_leapTracked = null; + + if(m_leapInput != null) + { + if(CVRInputManager.Instance != null) + CVRInputManager.Instance.DestroyInputModule(m_leapInput); + else + m_leapInput.ModuleDestroyed(); + } + m_leapInput = null; + + Settings.EnabledChange -= this.OnEnableChange; + Settings.TrackingModeChange -= this.OnTrackingModeChange; + } + + IEnumerator WaitForObjects() + { + while(CVRInputManager.Instance == null) + yield return null; + + while(PlayerSetup.Instance == null) + yield return null; + + while(LeapTracking.Instance == null) + yield return null; + + m_leapInput = new LeapInput(); + CVRInputManager.Instance.AddInputModule(m_leapInput); + + m_leapTracked = PlayerSetup.Instance.gameObject.AddComponent(); + } + + void Update() + { + if(Settings.Enabled) + { + m_leapData.Reset(); + + if(m_leapController.IsConnected) + { + Leap.Frame l_frame = m_leapController.Frame(); + LeapParser.ParseFrame(l_frame, m_leapData); + } + } + } + + public LeapParser.LeapData GetLatestData() => m_leapData; + + // Device events + void OnLeapDeviceInitialized(object p_sender, Leap.DeviceEventArgs p_args) + { + if(Settings.Enabled) + { + m_leapController.SubscribeToDeviceEvents(p_args.Device); + UpdateDeviceTrackingMode(); + } + + Utils.ShowHUDNotification("Leap Motion Extension", "Device initialized"); + } + + void OnLeapDeviceFailure(object p_sender, Leap.DeviceFailureEventArgs p_args) + { + Utils.ShowHUDNotification("Leap Motion Extension", "Device failure", "Code " + p_args.ErrorCode + ": " + p_args.ErrorMessage); + } + + void OnLeapDeviceLost(object p_sender, Leap.DeviceEventArgs p_args) + { + m_leapController.UnsubscribeFromDeviceEvents(p_args.Device); + + Utils.ShowHUDNotification("Leap Motion Extension", "Device lost"); + } + + void OnLeapServiceConnect(object p_sender, Leap.ConnectionEventArgs p_args) + { + Utils.ShowHUDNotification("Leap Motion Extension", "Service connected"); + } + + void OnLeapServiceDisconnect(object p_sender, Leap.ConnectionLostEventArgs p_args) + { + Utils.ShowHUDNotification("Leap Motion Extension", "Service disconnected"); + } + + // Settings + void OnEnableChange(bool p_state) + { + if(p_state) + { + m_leapController.StartConnection(); + UpdateDeviceTrackingMode(); + } + else + m_leapController.StopConnection(); + } + + void OnTrackingModeChange(Settings.LeapTrackingMode p_mode) + { + if(Settings.Enabled) + UpdateDeviceTrackingMode(); + } + + // Game events + internal void OnAvatarClear() + { + if(m_leapTracking != null) + m_leapTracking.OnAvatarClear(); + if(m_leapTracked != null) + m_leapTracked.OnAvatarClear(); + } + + internal void OnAvatarSetup() + { + if(m_leapTracking != null) + m_leapTracking.OnAvatarSetup(); + + if(m_leapTracked != null) + m_leapTracked.OnAvatarSetup(); + } + + internal void OnAvatarReinitialize() + { + if(m_leapTracked != null) + m_leapTracked.OnAvatarReinitialize(); + } + + internal void OnRayScale(float p_scale) + { + m_leapInput?.OnRayScale(p_scale); + } + + internal void OnPlayspaceScale(float p_relation) + { + if(m_leapTracking != null) + m_leapTracking.OnPlayspaceScale(p_relation); + } + + internal void OnPickupGrab(CVRPickupObject p_pickup) + { + m_leapInput?.OnPickupGrab(p_pickup); + } + + // Arbitrary + void UpdateDeviceTrackingMode() + { + m_leapController.ClearPolicy(Leap.Controller.PolicyFlag.POLICY_OPTIMIZE_SCREENTOP, null); + m_leapController.ClearPolicy(Leap.Controller.PolicyFlag.POLICY_OPTIMIZE_HMD, null); + + switch(Settings.TrackingMode) + { + case Settings.LeapTrackingMode.Screentop: + m_leapController.SetPolicy(Leap.Controller.PolicyFlag.POLICY_OPTIMIZE_SCREENTOP, null); + break; + case Settings.LeapTrackingMode.HMD: + m_leapController.SetPolicy(Leap.Controller.PolicyFlag.POLICY_OPTIMIZE_HMD, null); + break; + } + } + } +} diff --git a/ml_lme/LeapTracked.cs b/ml_lme/LeapTracked.cs index b7936f4..9d73b23 100644 --- a/ml_lme/LeapTracked.cs +++ b/ml_lme/LeapTracked.cs @@ -1,11 +1,14 @@ using ABI_RC.Core.Player; using ABI_RC.Systems.IK; using RootMotion.FinalIK; +using System.Collections; +using System.Collections.Generic; using UnityEngine; namespace ml_lme { [DisallowMultipleComponent] + [DefaultExecutionOrder(999999)] class LeapTracked : MonoBehaviour { struct IKInfo @@ -18,17 +21,64 @@ namespace ml_lme public Transform m_rightElbowTarget; } + struct FingerBoneInfo + { + public LeapHand.FingerBone m_bone; + public Transform m_targetBone; + public Transform m_sourceBone; + public Quaternion m_offset; + } + static readonly Quaternion ms_offsetLeft = Quaternion.Euler(0f, 90f, 0f); static readonly Quaternion ms_offsetRight = Quaternion.Euler(0f, 270f, 0f); + static readonly (HumanBodyBones, LeapHand.FingerBone, bool)[] ms_fingerBonesLinks = + { + (HumanBodyBones.LeftThumbProximal, LeapHand.FingerBone.ThumbProximal, true), + (HumanBodyBones.LeftThumbIntermediate, LeapHand.FingerBone.ThumbIntermediate, true), + (HumanBodyBones.LeftThumbDistal, LeapHand.FingerBone.ThumbDistal, true), + (HumanBodyBones.LeftIndexProximal, LeapHand.FingerBone.IndexProximal, true), + (HumanBodyBones.LeftIndexIntermediate, LeapHand.FingerBone.IndexIntermediate, true), + (HumanBodyBones.LeftIndexDistal, LeapHand.FingerBone.IndexDistal, true), + (HumanBodyBones.LeftMiddleProximal, LeapHand.FingerBone.MiddleProximal, true), + (HumanBodyBones.LeftMiddleIntermediate, LeapHand.FingerBone.MiddleIntermediate, true), + (HumanBodyBones.LeftMiddleDistal, LeapHand.FingerBone.MiddleDistal, true), + (HumanBodyBones.LeftRingProximal, LeapHand.FingerBone.RingProximal, true), + (HumanBodyBones.LeftRingIntermediate, LeapHand.FingerBone.RingIntermediate, true), + (HumanBodyBones.LeftRingDistal, LeapHand.FingerBone.RingDistal, true), + (HumanBodyBones.LeftLittleProximal, LeapHand.FingerBone.PinkyProximal, true), + (HumanBodyBones.LeftLittleIntermediate, LeapHand.FingerBone.PinkyIntermediate, true), + (HumanBodyBones.LeftLittleDistal, LeapHand.FingerBone.PinkyDistal, true), + + (HumanBodyBones.RightThumbProximal, LeapHand.FingerBone.ThumbProximal, false), + (HumanBodyBones.RightThumbIntermediate, LeapHand.FingerBone.ThumbIntermediate, false), + (HumanBodyBones.RightThumbDistal, LeapHand.FingerBone.ThumbDistal, false), + (HumanBodyBones.RightIndexProximal, LeapHand.FingerBone.IndexProximal, false), + (HumanBodyBones.RightIndexIntermediate, LeapHand.FingerBone.IndexIntermediate, false), + (HumanBodyBones.RightIndexDistal, LeapHand.FingerBone.IndexDistal, false), + (HumanBodyBones.RightMiddleProximal, LeapHand.FingerBone.MiddleProximal, false), + (HumanBodyBones.RightMiddleIntermediate, LeapHand.FingerBone.MiddleIntermediate, false), + (HumanBodyBones.RightMiddleDistal, LeapHand.FingerBone.MiddleDistal, false), + (HumanBodyBones.RightRingProximal, LeapHand.FingerBone.RingProximal, false), + (HumanBodyBones.RightRingIntermediate, LeapHand.FingerBone.RingIntermediate, false), + (HumanBodyBones.RightRingDistal, LeapHand.FingerBone.RingDistal, false), + (HumanBodyBones.RightLittleProximal, LeapHand.FingerBone.PinkyProximal, false), + (HumanBodyBones.RightLittleIntermediate, LeapHand.FingerBone.PinkyIntermediate, false), + (HumanBodyBones.RightLittleDistal, LeapHand.FingerBone.PinkyDistal, false), + }; + + public static readonly float[] ms_lastLeftFingerBones = new float[20]; + public static readonly float[] ms_lastRightFingerBones = new float[20]; + bool m_inVR = false; VRIK m_vrIK = null; - Transform m_hips = null; bool m_enabled = true; bool m_fingersOnly = false; bool m_trackElbows = true; + Transform m_leftHand = null; + Transform m_rightHand = null; IKInfo m_vrIKInfo; ArmIK m_leftArmIK = null; ArmIK m_rightArmIK = null; @@ -39,18 +89,30 @@ namespace ml_lme bool m_leftTargetActive = false; // VRIK only bool m_rightTargetActive = false; // VRIK only + readonly List m_leftFingerBones = null; + readonly List m_rightFingerBones = null; + + Quaternion m_leftWristOffset; + Quaternion m_rightWristOffset; + + internal LeapTracked() + { + m_leftFingerBones = new List(); + m_rightFingerBones = new List(); + } + // Unity events void Start() { m_inVR = Utils.IsInVR(); m_leftHandTarget = new GameObject("RotationTarget").transform; - m_leftHandTarget.parent = LeapTracking.Instance.GetLeftHand(); + m_leftHandTarget.parent = LeapTracking.Instance.GetLeftHand().GetRoot(); m_leftHandTarget.localPosition = Vector3.zero; m_leftHandTarget.localRotation = Quaternion.identity; m_rightHandTarget = new GameObject("RotationTarget").transform; - m_rightHandTarget.parent = LeapTracking.Instance.GetRightHand(); + m_rightHandTarget.parent = LeapTracking.Instance.GetRightHand().GetRoot(); m_rightHandTarget.localPosition = Vector3.zero; m_rightHandTarget.localRotation = Quaternion.identity; @@ -114,19 +176,47 @@ namespace ml_lme void LateUpdate() { - if(m_enabled && (m_vrIK == null) && (m_poseHandler != null)) + if(m_enabled && (m_poseHandler != null)) { LeapParser.LeapData l_data = LeapManager.Instance.GetLatestData(); - - Vector3 l_hipsLocalPos = m_hips.localPosition; - Quaternion l_hipsLocalRot = m_hips.localRotation; + if(l_data.m_leftHand.m_present) + { + Transform l_leapWrist = LeapTracking.Instance.GetLeftHand().GetWrist(); + Quaternion l_turnBack = (m_leftHand.rotation * m_leftWristOffset) * Quaternion.Inverse(l_leapWrist.rotation); + foreach(var l_info in m_leftFingerBones) + l_info.m_targetBone.rotation = l_turnBack * (l_info.m_sourceBone.rotation * l_info.m_offset); + } + if(l_data.m_rightHand.m_present) + { + Transform l_leapWrist = LeapTracking.Instance.GetRightHand().GetWrist(); + Quaternion l_turnBack = (m_rightHand.rotation * m_rightWristOffset) * Quaternion.Inverse(l_leapWrist.rotation); + foreach(var l_info in m_rightFingerBones) + l_info.m_targetBone.rotation = l_turnBack * (l_info.m_sourceBone.rotation * l_info.m_offset); + } m_poseHandler.GetHumanPose(ref m_pose); - UpdateFingers(l_data); - m_poseHandler.SetHumanPose(ref m_pose); - - m_hips.localPosition = l_hipsLocalPos; - m_hips.localRotation = l_hipsLocalRot; + if(l_data.m_leftHand.m_present) + { + for(int i = 0; i < 5; i++) + { + int l_offset = i * 4; + ms_lastLeftFingerBones[l_offset] = m_pose.muscles[(int)MuscleIndex.LeftThumb1Stretched + l_offset]; + ms_lastLeftFingerBones[l_offset + 1] = m_pose.muscles[(int)MuscleIndex.LeftThumb2Stretched + l_offset]; + ms_lastLeftFingerBones[l_offset + 2] = m_pose.muscles[(int)MuscleIndex.LeftThumb3Stretched + l_offset]; + ms_lastLeftFingerBones[l_offset + 3] = m_pose.muscles[(int)MuscleIndex.LeftThumbSpread + l_offset]; + } + } + if(l_data.m_rightHand.m_present) + { + for(int i = 0; i < 5; i++) + { + int l_offset = i * 4; + ms_lastRightFingerBones[l_offset] = m_pose.muscles[(int)MuscleIndex.RightThumb1Stretched + l_offset]; + ms_lastRightFingerBones[l_offset + 1] = m_pose.muscles[(int)MuscleIndex.RightThumb2Stretched + l_offset]; + ms_lastRightFingerBones[l_offset + 2] = m_pose.muscles[(int)MuscleIndex.RightThumb3Stretched + l_offset]; + ms_lastRightFingerBones[l_offset + 3] = m_pose.muscles[(int)MuscleIndex.RightThumbSpread + l_offset]; + } + } } } @@ -134,7 +224,6 @@ namespace ml_lme internal void OnAvatarClear() { m_vrIK = null; - m_hips = null; m_leftArmIK = null; m_rightArmIK = null; m_leftTargetActive = false; @@ -147,6 +236,14 @@ namespace ml_lme m_leftHandTarget.localRotation = Quaternion.identity; m_rightHandTarget.localPosition = Vector3.zero; m_rightHandTarget.localRotation = Quaternion.identity; + + m_leftFingerBones.Clear(); + m_rightFingerBones.Clear(); + + m_leftHand = null; + m_rightHand = null; + m_leftWristOffset = Quaternion.identity; + m_rightWristOffset = Quaternion.identity; } internal void OnAvatarSetup() @@ -156,27 +253,31 @@ namespace ml_lme if(PlayerSetup.Instance._animator.isHuman) { - m_hips = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Hips); m_poseHandler = new HumanPoseHandler(PlayerSetup.Instance._animator.avatar, PlayerSetup.Instance._animator.transform); m_poseHandler.GetHumanPose(ref m_pose); - if(!m_inVR) + if(m_inVR) + { + PlayerSetup.Instance._avatar.transform.localPosition = Vector3.zero; + PlayerSetup.Instance._avatar.transform.localRotation = Quaternion.identity; + } + else PoseHelper.ForceTPose(PlayerSetup.Instance._animator); - Transform l_hand = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftHand); - if(l_hand != null) - m_leftHandTarget.localRotation = ms_offsetLeft * (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_hand.GetMatrix()).rotation; + m_leftHand = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftHand); + m_leftHandTarget.localRotation = ms_offsetLeft * (Quaternion.Inverse(PlayerSetup.Instance._avatar.transform.rotation) * m_leftHand.rotation); - l_hand = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightHand); - if(l_hand != null) - m_rightHandTarget.localRotation = ms_offsetRight * (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_hand.GetMatrix()).rotation; + m_rightHand = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightHand); + m_rightHandTarget.localRotation = ms_offsetRight * (Quaternion.Inverse(PlayerSetup.Instance._avatar.transform.rotation) * m_rightHand.rotation); + + ParseFingersBones(); if(m_vrIK != null) { m_vrIK.onPreSolverUpdate.AddListener(this.OnIKPreUpdate); m_vrIK.onPostSolverUpdate.AddListener(this.OnIKPostUpdate); } - else if(!m_inVR) + else SetupArmIK(); } } @@ -195,7 +296,7 @@ namespace ml_lme m_vrIK.onPreSolverUpdate.AddListener(this.OnIKPreUpdate); m_vrIK.onPostSolverUpdate.AddListener(this.OnIKPostUpdate); } - else if(!m_inVR) + else { PoseHelper.ForceTPose(PlayerSetup.Instance._animator); SetupArmIK(); @@ -350,69 +451,33 @@ namespace ml_lme } } - void UpdateFingers(LeapParser.LeapData p_data) + void ParseFingersBones() { - if(p_data.m_leftHand.m_present) + LeapTracking.Instance.GetLeftHand().Reset(); + LeapTracking.Instance.GetLeftHand().GetWrist().rotation = PlayerSetup.Instance.transform.rotation * ms_offsetRight; // Weird, but that's how it works + m_leftWristOffset = Quaternion.Inverse(m_leftHand.rotation) * LeapTracking.Instance.GetLeftHand().GetWrist().rotation; + + LeapTracking.Instance.GetRightHand().Reset(); + LeapTracking.Instance.GetRightHand().GetWrist().rotation = PlayerSetup.Instance.transform.rotation * ms_offsetLeft; // Weird, but that's how it works + m_rightWristOffset = Quaternion.Inverse(m_rightHand.rotation) * LeapTracking.Instance.GetRightHand().GetWrist().rotation; + + foreach(var l_link in ms_fingerBonesLinks) { - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftThumb1Stretched, -0.5f - p_data.m_leftHand.m_bends[0]); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftThumb2Stretched, 0.7f - p_data.m_leftHand.m_bends[0] * 2f); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftThumb3Stretched, 0.7f - p_data.m_leftHand.m_bends[0] * 2f); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftThumbSpread, -p_data.m_leftHand.m_spreads[0]); + Transform l_transform = PlayerSetup.Instance._animator.GetBoneTransform(l_link.Item1); + if(l_transform != null) + { + FingerBoneInfo l_info = new FingerBoneInfo(); + l_info.m_bone = l_link.Item2; + l_info.m_targetBone = l_transform; + l_info.m_sourceBone = (l_link.Item3 ? LeapTracking.Instance.GetLeftHand().GetFingersBone(l_link.Item2) : LeapTracking.Instance.GetRightHand().GetFingersBone(l_link.Item2)); + l_info.m_offset = Quaternion.Inverse(l_info.m_sourceBone.rotation) * l_info.m_targetBone.rotation; - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftIndex1Stretched, 0.5f - p_data.m_leftHand.m_bends[1]); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftIndex2Stretched, 0.7f - p_data.m_leftHand.m_bends[1] * 2f); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftIndex3Stretched, 0.7f - p_data.m_leftHand.m_bends[1] * 2f); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftIndexSpread, p_data.m_leftHand.m_spreads[1]); - - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftMiddle1Stretched, 0.5f - p_data.m_leftHand.m_bends[2]); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftMiddle2Stretched, 0.7f - p_data.m_leftHand.m_bends[2] * 2f); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftMiddle3Stretched, 0.7f - p_data.m_leftHand.m_bends[2] * 2f); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftMiddleSpread, p_data.m_leftHand.m_spreads[2]); - - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftRing1Stretched, 0.5f - p_data.m_leftHand.m_bends[3]); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftRing2Stretched, 0.7f - p_data.m_leftHand.m_bends[3] * 2f); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftRing3Stretched, 0.7f - p_data.m_leftHand.m_bends[3] * 2f); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftRingSpread, -p_data.m_leftHand.m_spreads[3]); - - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftLittle1Stretched, 0.5f - p_data.m_leftHand.m_bends[4]); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftLittle2Stretched, 0.7f - p_data.m_leftHand.m_bends[4] * 2f); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftLittle3Stretched, 0.7f - p_data.m_leftHand.m_bends[4] * 2f); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.LeftLittleSpread, -p_data.m_leftHand.m_spreads[4]); + if(l_link.Item3) + m_leftFingerBones.Add(l_info); + else + m_rightFingerBones.Add(l_info); + } } - - if(p_data.m_rightHand.m_present) - { - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightThumb1Stretched, -0.5f - p_data.m_rightHand.m_bends[0]); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightThumb2Stretched, 0.7f - p_data.m_rightHand.m_bends[0] * 2f); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightThumb3Stretched, 0.7f - p_data.m_rightHand.m_bends[0] * 2f); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightThumbSpread, -p_data.m_rightHand.m_spreads[0]); - - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightIndex1Stretched, 0.5f - p_data.m_rightHand.m_bends[1]); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightIndex2Stretched, 0.7f - p_data.m_rightHand.m_bends[1] * 2f); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightIndex3Stretched, 0.7f - p_data.m_rightHand.m_bends[1] * 2f); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightIndexSpread, p_data.m_rightHand.m_spreads[1]); - - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightMiddle1Stretched, 0.5f - p_data.m_rightHand.m_bends[2]); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightMiddle2Stretched, 0.7f - p_data.m_rightHand.m_bends[2] * 2f); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightMiddle3Stretched, 0.7f - p_data.m_rightHand.m_bends[2] * 2f); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightMiddleSpread, p_data.m_rightHand.m_spreads[2]); - - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightRing1Stretched, 0.5f - p_data.m_rightHand.m_bends[3]); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightRing2Stretched, 0.7f - p_data.m_rightHand.m_bends[3] * 2f); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightRing3Stretched, 0.7f - p_data.m_rightHand.m_bends[3] * 2f); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightRingSpread, -p_data.m_rightHand.m_spreads[3]); - - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightLittle1Stretched, 0.5f - p_data.m_rightHand.m_bends[4]); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightLittle2Stretched, 0.7f - p_data.m_rightHand.m_bends[4] * 2f); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightLittle3Stretched, 0.7f - p_data.m_rightHand.m_bends[4] * 2f); - UpdatePoseMuscle(ref m_pose, (int)MuscleIndex.RightLittleSpread, -p_data.m_rightHand.m_spreads[4]); - } - } - - static void UpdatePoseMuscle(ref HumanPose p_pose, int p_index, float p_value) - { - if(p_pose.muscles.Length > p_index) - p_pose.muscles[p_index] = p_value; } } } diff --git a/ml_lme/LeapTracking.cs b/ml_lme/LeapTracking.cs index 1cd411c..535805d 100644 --- a/ml_lme/LeapTracking.cs +++ b/ml_lme/LeapTracking.cs @@ -1,302 +1,280 @@ -using ABI_RC.Core.Player; -using ABI_RC.Systems.VRModeSwitch; -using System.Collections; -using UnityEngine; - -namespace ml_lme -{ - [DisallowMultipleComponent] - class LeapTracking : MonoBehaviour - { - public static LeapTracking Instance { get; private set; } = null; - static Quaternion ms_dummyRotation = Quaternion.identity; - static readonly Quaternion ms_hmdRotation = new Quaternion(0f, 0.7071068f, 0.7071068f, 0f); - static readonly Quaternion ms_screentopRotation = new Quaternion(0f, 0f, -1f, 0f); - - bool m_inVR = false; - - GameObject m_leapHandLeft = null; - GameObject m_leapHandRight = null; - GameObject m_leapElbowLeft = null; - GameObject m_leapElbowRight = null; - GameObject m_leapControllerModel = null; - GameObject m_visualHands = null; - VisualHand m_visualHandLeft = null; - VisualHand m_visualHandRight = null; - - float m_scaleRelation = 1f; - - void Start() - { - if(Instance == null) - Instance = this; - - m_inVR = Utils.IsInVR(); - - m_leapHandLeft = new GameObject("LeapHandLeft"); - m_leapHandLeft.transform.parent = this.transform; - m_leapHandLeft.transform.localPosition = Vector3.zero; - m_leapHandLeft.transform.localRotation = Quaternion.identity; - - m_leapHandRight = new GameObject("LeapHandRight"); - m_leapHandRight.transform.parent = this.transform; - m_leapHandRight.transform.localPosition = Vector3.zero; - m_leapHandRight.transform.localRotation = Quaternion.identity; - - m_leapElbowLeft = new GameObject("LeapElbowLeft"); - m_leapElbowLeft.transform.parent = this.transform; - m_leapElbowLeft.transform.localPosition = Vector3.zero; - m_leapElbowLeft.transform.localRotation = Quaternion.identity; - - m_leapElbowRight = new GameObject("LeapElbowRight"); - m_leapElbowRight.transform.parent = this.transform; - m_leapElbowRight.transform.localPosition = Vector3.zero; - m_leapElbowRight.transform.localRotation = Quaternion.identity; - - m_leapControllerModel = AssetsHandler.GetAsset("assets/models/leapmotion/leap_motion_1_0.obj"); - if(m_leapControllerModel != null) - { - m_leapControllerModel.name = "LeapModel"; - m_leapControllerModel.transform.parent = this.transform; - m_leapControllerModel.transform.localPosition = Vector3.zero; - m_leapControllerModel.transform.localRotation = Quaternion.identity; - } - - m_visualHands = AssetsHandler.GetAsset("assets/models/hands/leaphands.prefab"); - if(m_visualHands != null) - { - m_visualHands.name = "VisualHands"; - m_visualHands.transform.parent = this.transform; - m_visualHands.transform.localPosition = Vector3.zero; - m_visualHands.transform.localRotation = Quaternion.identity; - - m_visualHandLeft = new VisualHand(m_visualHands.transform.Find("HandL"), true); - m_visualHandRight = new VisualHand(m_visualHands.transform.Find("HandR"), false); - } - - Settings.DesktopOffsetChange += this.OnDesktopOffsetChange; - Settings.ModelVisibilityChange += this.OnModelVisibilityChange; - Settings.VisualHandsChange += this.OnVisualHandsChange; - Settings.TrackingModeChange += this.OnTrackingModeChange; - Settings.RootAngleChange += this.OnRootAngleChange; - Settings.HeadAttachChange += this.OnHeadAttachChange; - Settings.HeadOffsetChange += this.OnHeadOffsetChange; - - MelonLoader.MelonCoroutines.Start(WaitForLocalPlayer()); - - OnModelVisibilityChange(Settings.ModelVisibility); - OnVisualHandsChange(Settings.VisualHands); - OnTrackingModeChange(Settings.TrackingMode); - OnRootAngleChange(Settings.RootAngle); - - VRModeSwitchEvents.OnInitializeXR.AddListener(this.OnModeSwitch); - VRModeSwitchEvents.OnDeinitializeXR.AddListener(this.OnModeSwitch); - } - - IEnumerator WaitForLocalPlayer() - { - while(PlayerSetup.Instance == null) - yield return null; - - OnHeadAttachChange(Settings.HeadAttach); - } - - void OnDestroy() - { - if(Instance == this) - Instance = null; - - if(m_leapHandLeft != null) - Object.Destroy(m_leapHandLeft); - m_leapHandLeft = null; - - if(m_leapHandRight != null) - Object.Destroy(m_leapHandRight); - m_leapHandRight = null; - - if(m_leapElbowLeft != null) - Object.Destroy(m_leapElbowLeft); - m_leapElbowLeft = null; - - if(m_leapElbowRight != null) - Object.Destroy(m_leapElbowRight); - m_leapElbowRight = null; - - if(m_leapControllerModel != null) - Object.Destroy(m_leapControllerModel); - m_leapControllerModel = null; - - if(m_visualHands != null) - Object.Destroy(m_visualHands); - m_visualHands = null; - - m_visualHandLeft = null; - m_visualHandRight = null; - - Settings.DesktopOffsetChange -= this.OnDesktopOffsetChange; - Settings.ModelVisibilityChange -= this.OnModelVisibilityChange; - Settings.VisualHandsChange -= this.OnVisualHandsChange; - Settings.TrackingModeChange -= this.OnTrackingModeChange; - Settings.RootAngleChange -= this.OnRootAngleChange; - Settings.HeadAttachChange -= this.OnHeadAttachChange; - Settings.HeadOffsetChange -= this.OnHeadOffsetChange; - - VRModeSwitchEvents.OnInitializeXR.RemoveListener(this.OnModeSwitch); - VRModeSwitchEvents.OnDeinitializeXR.RemoveListener(this.OnModeSwitch); - } - - void Update() - { - if(Settings.Enabled) - { - LeapParser.LeapData l_data = LeapManager.Instance.GetLatestData(); - - if(l_data.m_leftHand.m_present) - { - OrientationAdjustment(ref l_data.m_leftHand.m_position, ref l_data.m_leftHand.m_rotation, Settings.TrackingMode); - for(int i = 0; i < 20; i++) - OrientationAdjustment(ref l_data.m_leftHand.m_fingerPosition[i], ref l_data.m_leftHand.m_fingerRotation[i], Settings.TrackingMode); - - m_leapHandLeft.transform.localPosition = l_data.m_leftHand.m_position; - m_leapHandLeft.transform.localRotation = l_data.m_leftHand.m_rotation; - - OrientationAdjustment(ref l_data.m_leftHand.m_elbowPosition, ref ms_dummyRotation, Settings.TrackingMode); - m_leapElbowLeft.transform.localPosition = l_data.m_leftHand.m_elbowPosition; - - if(Settings.VisualHands) - m_visualHandLeft?.Update(l_data.m_leftHand); - } - - if(l_data.m_rightHand.m_present) - { - OrientationAdjustment(ref l_data.m_rightHand.m_position, ref l_data.m_rightHand.m_rotation, Settings.TrackingMode); - for(int i = 0; i < 20; i++) - OrientationAdjustment(ref l_data.m_rightHand.m_fingerPosition[i], ref l_data.m_rightHand.m_fingerRotation[i], Settings.TrackingMode); - - m_leapHandRight.transform.localPosition = l_data.m_rightHand.m_position; - m_leapHandRight.transform.localRotation = l_data.m_rightHand.m_rotation; - - OrientationAdjustment(ref l_data.m_rightHand.m_elbowPosition, ref ms_dummyRotation, Settings.TrackingMode); - m_leapElbowRight.transform.localPosition = l_data.m_rightHand.m_elbowPosition; - - if(Settings.VisualHands) - m_visualHandRight?.Update(l_data.m_rightHand); - } - } - } - - public Transform GetLeftHand() => m_leapHandLeft.transform; - public Transform GetRightHand() => m_leapHandRight.transform; - public Transform GetLeftElbow() => m_leapElbowLeft.transform; - public Transform GetRightElbow() => m_leapElbowRight.transform; - - // Settings - void OnDesktopOffsetChange(Vector3 p_offset) - { - if(!Settings.HeadAttach) - this.transform.localPosition = p_offset * (!m_inVR ? m_scaleRelation : 1f); - } - - void OnModelVisibilityChange(bool p_state) - { - m_leapControllerModel.SetActive(p_state); - } - - void OnVisualHandsChange(bool p_state) - { - m_visualHands.SetActive(p_state); - } - - void OnTrackingModeChange(Settings.LeapTrackingMode p_mode) - { - switch(p_mode) - { - case Settings.LeapTrackingMode.Screentop: - m_leapControllerModel.transform.localRotation = Quaternion.Euler(0f, 0f, 180f); - break; - case Settings.LeapTrackingMode.Desktop: - m_leapControllerModel.transform.localRotation = Quaternion.identity; - break; - case Settings.LeapTrackingMode.HMD: - m_leapControllerModel.transform.localRotation = Quaternion.Euler(270f, 180f, 0f); - break; - } - } - - void OnRootAngleChange(Vector3 p_angle) - { - this.transform.localRotation = Quaternion.Euler(p_angle); - } - - void OnHeadAttachChange(bool p_state) - { - if(!m_inVR) - { - this.transform.parent = (p_state ? PlayerSetup.Instance.desktopCamera.transform : PlayerSetup.Instance.desktopCameraRig.transform); - this.transform.localPosition = (p_state ? Settings.HeadOffset : Settings.DesktopOffset) * m_scaleRelation; - } - else - { - this.transform.parent = (p_state ? PlayerSetup.Instance.vrCamera.transform : PlayerSetup.Instance.vrCameraRig.transform); - this.transform.localPosition = (p_state ? Settings.HeadOffset : Settings.DesktopOffset); - } - - this.transform.localScale = Vector3.one * (!m_inVR ? m_scaleRelation : 1f); - this.transform.localRotation = Quaternion.Euler(Settings.RootAngle); - } - - void OnHeadOffsetChange(Vector3 p_offset) - { - if(Settings.HeadAttach) - this.transform.localPosition = p_offset * (!m_inVR ? m_scaleRelation : 1f); - } - - // Game events - internal void OnAvatarClear() - { - m_scaleRelation = 1f; - OnHeadAttachChange(Settings.HeadAttach); - } - - internal void OnAvatarSetup() - { - m_inVR = Utils.IsInVR(); - OnHeadAttachChange(Settings.HeadAttach); - } - - internal void OnPlayspaceScale(float p_relation) - { - m_scaleRelation = p_relation; - OnHeadAttachChange(Settings.HeadAttach); - } - - void OnModeSwitch() - { - m_inVR = Utils.IsInVR(); - OnHeadAttachChange(Settings.HeadAttach); - } - - // Utils - static void OrientationAdjustment(ref Vector3 p_pos, ref Quaternion p_rot, Settings.LeapTrackingMode p_mode) - { - switch(p_mode) - { - case Settings.LeapTrackingMode.Screentop: - { - p_pos.x *= -1f; - p_pos.y *= -1f; - p_rot = (ms_screentopRotation * p_rot); - } - break; - - case Settings.LeapTrackingMode.HMD: - { - p_pos.x *= -1f; - Utils.Swap(ref p_pos.y, ref p_pos.z); - p_rot = (ms_hmdRotation * p_rot); - } - break; - } - } - } -} +using ABI_RC.Core.Player; +using ABI_RC.Systems.VRModeSwitch; +using System.Collections; +using UnityEngine; + +namespace ml_lme +{ + [DisallowMultipleComponent] + class LeapTracking : MonoBehaviour + { + public static LeapTracking Instance { get; private set; } = null; + static Quaternion ms_dummyRotation = Quaternion.identity; + static readonly Quaternion ms_hmdRotation = new Quaternion(0f, 0.7071068f, 0.7071068f, 0f); + static readonly Quaternion ms_screentopRotation = new Quaternion(0f, 0f, -1f, 0f); + + bool m_inVR = false; + + GameObject m_leapHands = null; + LeapHand m_leapHandLeft = null; + LeapHand m_leapHandRight = null; + GameObject m_leapElbowLeft = null; + GameObject m_leapElbowRight = null; + GameObject m_leapControllerModel = null; + + float m_scaleRelation = 1f; + + void Start() + { + if(Instance == null) + Instance = this; + + m_inVR = Utils.IsInVR(); + + m_leapElbowLeft = new GameObject("LeapElbowLeft"); + m_leapElbowLeft.transform.parent = this.transform; + m_leapElbowLeft.transform.localPosition = Vector3.zero; + m_leapElbowLeft.transform.localRotation = Quaternion.identity; + + m_leapElbowRight = new GameObject("LeapElbowRight"); + m_leapElbowRight.transform.parent = this.transform; + m_leapElbowRight.transform.localPosition = Vector3.zero; + m_leapElbowRight.transform.localRotation = Quaternion.identity; + + m_leapControllerModel = AssetsHandler.GetAsset("assets/models/leapmotion/leap_motion_1_0.obj"); + if(m_leapControllerModel != null) + { + m_leapControllerModel.name = "LeapModel"; + m_leapControllerModel.transform.parent = this.transform; + m_leapControllerModel.transform.localPosition = Vector3.zero; + m_leapControllerModel.transform.localRotation = Quaternion.identity; + } + + m_leapHands = AssetsHandler.GetAsset("assets/models/leaphands/leaphands.prefab"); + if(m_leapHands != null) + { + m_leapHands.name = "LeapHands"; + m_leapHands.transform.parent = this.transform; + m_leapHands.transform.localPosition = Vector3.zero; + m_leapHands.transform.localRotation = Quaternion.identity; + + m_leapHandLeft = new LeapHand(m_leapHands.transform.Find("HandL"), true); + m_leapHandRight = new LeapHand(m_leapHands.transform.Find("HandR"), false); + } + + Settings.DesktopOffsetChange += this.OnDesktopOffsetChange; + Settings.ModelVisibilityChange += this.OnModelVisibilityChange; + Settings.VisualHandsChange += this.OnVisualHandsChange; + Settings.TrackingModeChange += this.OnTrackingModeChange; + Settings.RootAngleChange += this.OnRootAngleChange; + Settings.HeadAttachChange += this.OnHeadAttachChange; + Settings.HeadOffsetChange += this.OnHeadOffsetChange; + + MelonLoader.MelonCoroutines.Start(WaitForLocalPlayer()); + + OnModelVisibilityChange(Settings.ModelVisibility); + OnVisualHandsChange(Settings.VisualHands); + OnTrackingModeChange(Settings.TrackingMode); + OnRootAngleChange(Settings.RootAngle); + + VRModeSwitchEvents.OnInitializeXR.AddListener(this.OnModeSwitch); + VRModeSwitchEvents.OnDeinitializeXR.AddListener(this.OnModeSwitch); + } + + IEnumerator WaitForLocalPlayer() + { + while(PlayerSetup.Instance == null) + yield return null; + + OnHeadAttachChange(Settings.HeadAttach); + } + + void OnDestroy() + { + if(Instance == this) + Instance = null; + + if(m_leapHands != null) + Object.Destroy(m_leapHands); + m_leapHands = null; + m_leapHandLeft = null; + m_leapHandRight = null; + + if(m_leapElbowLeft != null) + Object.Destroy(m_leapElbowLeft); + m_leapElbowLeft = null; + + if(m_leapElbowRight != null) + Object.Destroy(m_leapElbowRight); + m_leapElbowRight = null; + + if(m_leapControllerModel != null) + Object.Destroy(m_leapControllerModel); + m_leapControllerModel = null; + + Settings.DesktopOffsetChange -= this.OnDesktopOffsetChange; + Settings.ModelVisibilityChange -= this.OnModelVisibilityChange; + Settings.VisualHandsChange -= this.OnVisualHandsChange; + Settings.TrackingModeChange -= this.OnTrackingModeChange; + Settings.RootAngleChange -= this.OnRootAngleChange; + Settings.HeadAttachChange -= this.OnHeadAttachChange; + Settings.HeadOffsetChange -= this.OnHeadOffsetChange; + + VRModeSwitchEvents.OnInitializeXR.RemoveListener(this.OnModeSwitch); + VRModeSwitchEvents.OnDeinitializeXR.RemoveListener(this.OnModeSwitch); + } + + void Update() + { + if(Settings.Enabled) + { + LeapParser.LeapData l_data = LeapManager.Instance.GetLatestData(); + + if(l_data.m_leftHand.m_present) + { + OrientationAdjustment(ref l_data.m_leftHand.m_position, ref l_data.m_leftHand.m_rotation, Settings.TrackingMode); + for(int i = 0; i < 20; i++) + OrientationAdjustment(ref l_data.m_leftHand.m_fingerPosition[i], ref l_data.m_leftHand.m_fingerRotation[i], Settings.TrackingMode); + + m_leapHandLeft.GetRoot().localPosition = l_data.m_leftHand.m_position; + m_leapHandLeft.GetRoot().localRotation = l_data.m_leftHand.m_rotation; + + OrientationAdjustment(ref l_data.m_leftHand.m_elbowPosition, ref ms_dummyRotation, Settings.TrackingMode); + m_leapElbowLeft.transform.localPosition = l_data.m_leftHand.m_elbowPosition; + + m_leapHandLeft?.Update(l_data.m_leftHand); + } + + if(l_data.m_rightHand.m_present) + { + OrientationAdjustment(ref l_data.m_rightHand.m_position, ref l_data.m_rightHand.m_rotation, Settings.TrackingMode); + for(int i = 0; i < 20; i++) + OrientationAdjustment(ref l_data.m_rightHand.m_fingerPosition[i], ref l_data.m_rightHand.m_fingerRotation[i], Settings.TrackingMode); + + m_leapHandRight.GetRoot().localPosition = l_data.m_rightHand.m_position; + m_leapHandRight.GetRoot().localRotation = l_data.m_rightHand.m_rotation; + + OrientationAdjustment(ref l_data.m_rightHand.m_elbowPosition, ref ms_dummyRotation, Settings.TrackingMode); + m_leapElbowRight.transform.localPosition = l_data.m_rightHand.m_elbowPosition; + + m_leapHandRight?.Update(l_data.m_rightHand); + } + } + } + + public LeapHand GetLeftHand() => m_leapHandLeft; + public LeapHand GetRightHand() => m_leapHandRight; + public Transform GetLeftElbow() => m_leapElbowLeft.transform; + public Transform GetRightElbow() => m_leapElbowRight.transform; + + // Settings + void OnDesktopOffsetChange(Vector3 p_offset) + { + if(!Settings.HeadAttach) + this.transform.localPosition = p_offset * (!m_inVR ? m_scaleRelation : 1f); + } + + void OnModelVisibilityChange(bool p_state) + { + m_leapControllerModel.SetActive(p_state); + } + + void OnVisualHandsChange(bool p_state) + { + m_leapHandLeft?.SetMeshActive(p_state); + m_leapHandRight?.SetMeshActive(p_state); + } + + void OnTrackingModeChange(Settings.LeapTrackingMode p_mode) + { + switch(p_mode) + { + case Settings.LeapTrackingMode.Screentop: + m_leapControllerModel.transform.localRotation = Quaternion.Euler(0f, 0f, 180f); + break; + case Settings.LeapTrackingMode.Desktop: + m_leapControllerModel.transform.localRotation = Quaternion.identity; + break; + case Settings.LeapTrackingMode.HMD: + m_leapControllerModel.transform.localRotation = Quaternion.Euler(270f, 180f, 0f); + break; + } + } + + void OnRootAngleChange(Vector3 p_angle) + { + this.transform.localRotation = Quaternion.Euler(p_angle); + } + + void OnHeadAttachChange(bool p_state) + { + if(!m_inVR) + { + this.transform.parent = (p_state ? PlayerSetup.Instance.desktopCamera.transform : PlayerSetup.Instance.desktopCameraRig.transform); + this.transform.localPosition = (p_state ? Settings.HeadOffset : Settings.DesktopOffset) * m_scaleRelation; + } + else + { + this.transform.parent = (p_state ? PlayerSetup.Instance.vrCamera.transform : PlayerSetup.Instance.vrCameraRig.transform); + this.transform.localPosition = (p_state ? Settings.HeadOffset : Settings.DesktopOffset); + } + + this.transform.localScale = Vector3.one * (!m_inVR ? m_scaleRelation : 1f); + this.transform.localRotation = Quaternion.Euler(Settings.RootAngle); + } + + void OnHeadOffsetChange(Vector3 p_offset) + { + if(Settings.HeadAttach) + this.transform.localPosition = p_offset * (!m_inVR ? m_scaleRelation : 1f); + } + + // Game events + internal void OnAvatarClear() + { + m_scaleRelation = 1f; + OnHeadAttachChange(Settings.HeadAttach); + } + + internal void OnAvatarSetup() + { + m_inVR = Utils.IsInVR(); + OnHeadAttachChange(Settings.HeadAttach); + } + + internal void OnPlayspaceScale(float p_relation) + { + m_scaleRelation = p_relation; + OnHeadAttachChange(Settings.HeadAttach); + } + + void OnModeSwitch() + { + m_inVR = Utils.IsInVR(); + OnHeadAttachChange(Settings.HeadAttach); + } + + // Utils + static void OrientationAdjustment(ref Vector3 p_pos, ref Quaternion p_rot, Settings.LeapTrackingMode p_mode) + { + switch(p_mode) + { + case Settings.LeapTrackingMode.Screentop: + { + p_pos.x *= -1f; + p_pos.y *= -1f; + p_rot = (ms_screentopRotation * p_rot); + } + break; + + case Settings.LeapTrackingMode.HMD: + { + p_pos.x *= -1f; + Utils.Swap(ref p_pos.y, ref p_pos.z); + p_rot = (ms_hmdRotation * p_rot); + } + break; + } + } + } +} diff --git a/ml_lme/Settings.cs b/ml_lme/Settings.cs index 5c6b94c..e93faf5 100644 --- a/ml_lme/Settings.cs +++ b/ml_lme/Settings.cs @@ -1,346 +1,346 @@ -using ABI_RC.Core.InteractionSystem; -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace ml_lme -{ - static class Settings - { - public enum LeapTrackingMode - { - Screentop = 0, - Desktop, - HMD - } - - enum ModSetting - { - Enabled, - DesktopX, - DesktopY, - DesktopZ, - FingersOnly, - Model, - Mode, - AngleX, - AngleY, - AngleZ, - Head, - HeadX, - HeadY, - HeadZ, - TrackElbows, - Interaction, - Gestures, - InteractThreadhold, - GripThreadhold, - VisualHands - }; - - public static bool Enabled { get; private set; } = false; - public static Vector3 DesktopOffset { get; private set; } = new Vector3(0f, -0.45f, 0.3f); - public static bool FingersOnly { get; private set; } = false; - public static bool ModelVisibility { get; private set; } = false; - public static LeapTrackingMode TrackingMode { get; private set; } = LeapTrackingMode.Desktop; - public static Vector3 RootAngle { get; private set; } = Vector3.zero; - public static bool HeadAttach { get; private set; } = false; - public static Vector3 HeadOffset { get; private set; } = new Vector3(0f, -0.3f, 0.15f); - public static bool TrackElbows { get; private set; } = true; - public static bool Interaction { get; private set; } = true; - public static bool Gestures { get; private set; } = false; - public static float InteractThreadhold { get; private set; } = 0.8f; - public static float GripThreadhold { get; private set; } = 0.4f; - public static bool VisualHands { get; private set; } = false; - - static MelonLoader.MelonPreferences_Category ms_category = null; - static List ms_entries = null; - - static public event Action EnabledChange; - static public event Action DesktopOffsetChange; - static public event Action FingersOnlyChange; - static public event Action ModelVisibilityChange; - static public event Action TrackingModeChange; - static public event Action RootAngleChange; - static public event Action HeadAttachChange; - static public event Action HeadOffsetChange; - static public event Action TrackElbowsChange; - static public event Action InteractionChange; - static public event Action GesturesChange; - static public event Action InteractThreadholdChange; - static public event Action GripThreadholdChange; - static public event Action VisualHandsChange; - - internal static void Init() - { - ms_category = MelonLoader.MelonPreferences.CreateCategory("LME", null, true); - - ms_entries = new List() - { - ms_category.CreateEntry(ModSetting.Enabled.ToString(), Enabled), - ms_category.CreateEntry(ModSetting.DesktopX.ToString(), (int)(DesktopOffset.x * 100f)), - ms_category.CreateEntry(ModSetting.DesktopY.ToString(), (int)(DesktopOffset.y * 100f)), - ms_category.CreateEntry(ModSetting.DesktopZ.ToString(), (int)(DesktopOffset.z * 100f)), - ms_category.CreateEntry(ModSetting.FingersOnly.ToString(), FingersOnly), - ms_category.CreateEntry(ModSetting.Model.ToString(), ModelVisibility), - ms_category.CreateEntry(ModSetting.Mode.ToString(), (int)TrackingMode), - ms_category.CreateEntry(ModSetting.AngleX.ToString(), (int)(RootAngle.x * 100f)), - ms_category.CreateEntry(ModSetting.AngleY.ToString(), (int)(RootAngle.y * 100f)), - ms_category.CreateEntry(ModSetting.AngleZ.ToString(), (int)(RootAngle.z * 100f)), - ms_category.CreateEntry(ModSetting.Head.ToString(), HeadAttach), - ms_category.CreateEntry(ModSetting.HeadX.ToString(), (int)(HeadOffset.x * 100f)), - ms_category.CreateEntry(ModSetting.HeadY.ToString(), (int)(HeadOffset.y * 100f)), - ms_category.CreateEntry(ModSetting.HeadZ.ToString(), (int)(HeadOffset.z * 100f)), - ms_category.CreateEntry(ModSetting.TrackElbows.ToString(), TrackElbows), - ms_category.CreateEntry(ModSetting.Interaction.ToString(), Interaction), - ms_category.CreateEntry(ModSetting.Gestures.ToString(), Gestures), - ms_category.CreateEntry(ModSetting.InteractThreadhold.ToString(), (int)(InteractThreadhold * 100f)), - ms_category.CreateEntry(ModSetting.GripThreadhold.ToString(), (int)(GripThreadhold * 100f)), - ms_category.CreateEntry(ModSetting.VisualHands.ToString(), VisualHands) - }; - - Load(); - - MelonLoader.MelonCoroutines.Start(WaitMainMenuUi()); - } - - static System.Collections.IEnumerator WaitMainMenuUi() - { - while(ViewManager.Instance == null) - yield return null; - while(ViewManager.Instance.gameMenuView == null) - yield return null; - while(ViewManager.Instance.gameMenuView.Listener == null) - yield return null; - - ViewManager.Instance.gameMenuView.Listener.ReadyForBindings += () => - { - ViewManager.Instance.gameMenuView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action(OnToggleUpdate)); - ViewManager.Instance.gameMenuView.View.BindCall("OnSliderUpdate_" + ms_category.Identifier, new Action(OnSliderUpdate)); - ViewManager.Instance.gameMenuView.View.BindCall("OnDropdownUpdate_" + ms_category.Identifier, new Action(OnDropdownUpdate)); - }; - ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) => - { - ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js")); - ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js")); - foreach(var l_entry in ms_entries) - ViewManager.Instance.gameMenuView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString()); - }; - } - - static void Load() - { - Enabled = (bool)ms_entries[(int)ModSetting.Enabled].BoxedValue; - DesktopOffset = new Vector3( - (int)ms_entries[(int)ModSetting.DesktopX].BoxedValue, - (int)ms_entries[(int)ModSetting.DesktopY].BoxedValue, - (int)ms_entries[(int)ModSetting.DesktopZ].BoxedValue - ) * 0.01f; - FingersOnly = (bool)ms_entries[(int)ModSetting.FingersOnly].BoxedValue; - ModelVisibility = (bool)ms_entries[(int)ModSetting.Model].BoxedValue; - TrackingMode = (LeapTrackingMode)(int)ms_entries[(int)ModSetting.Mode].BoxedValue; - RootAngle = new Vector3( - (int)ms_entries[(int)ModSetting.AngleX].BoxedValue, - (int)ms_entries[(int)ModSetting.AngleY].BoxedValue, - (int)ms_entries[(int)ModSetting.AngleZ].BoxedValue - ); - HeadAttach = (bool)ms_entries[(int)ModSetting.Head].BoxedValue; - HeadOffset = new Vector3( - (int)ms_entries[(int)ModSetting.HeadX].BoxedValue, - (int)ms_entries[(int)ModSetting.HeadY].BoxedValue, - (int)ms_entries[(int)ModSetting.HeadZ].BoxedValue - ) * 0.01f; - TrackElbows = (bool)ms_entries[(int)ModSetting.TrackElbows].BoxedValue; - Interaction = (bool)ms_entries[(int)ModSetting.Interaction].BoxedValue; - Gestures = (bool)ms_entries[(int)ModSetting.Gestures].BoxedValue; - InteractThreadhold = (int)ms_entries[(int)ModSetting.InteractThreadhold].BoxedValue * 0.01f; - GripThreadhold = (int)ms_entries[(int)ModSetting.GripThreadhold].BoxedValue * 0.01f; - VisualHands = (bool)ms_entries[(int)ModSetting.VisualHands].BoxedValue; - } - - static void OnToggleUpdate(string p_name, string p_value) - { - if(Enum.TryParse(p_name, out ModSetting l_setting)) - { - switch(l_setting) - { - case ModSetting.Enabled: - { - Enabled = bool.Parse(p_value); - EnabledChange?.Invoke(Enabled); - } - break; - - case ModSetting.FingersOnly: - { - FingersOnly = bool.Parse(p_value); - FingersOnlyChange?.Invoke(FingersOnly); - } - break; - - case ModSetting.Model: - { - ModelVisibility = bool.Parse(p_value); - ModelVisibilityChange?.Invoke(ModelVisibility); - } - break; - - case ModSetting.Head: - { - HeadAttach = bool.Parse(p_value); - HeadAttachChange?.Invoke(HeadAttach); - } - break; - - case ModSetting.TrackElbows: - { - TrackElbows = bool.Parse(p_value); - TrackElbowsChange?.Invoke(TrackElbows); - } - break; - - case ModSetting.Interaction: - { - Interaction = bool.Parse(p_value); - InteractionChange?.Invoke(Interaction); - } - break; - - case ModSetting.Gestures: - { - Gestures = bool.Parse(p_value); - GesturesChange?.Invoke(Gestures); - } - break; - - case ModSetting.VisualHands: - { - VisualHands = bool.Parse(p_value); - VisualHandsChange?.Invoke(VisualHands); - } - break; - } - - ms_entries[(int)l_setting].BoxedValue = bool.Parse(p_value); - } - } - - static void OnSliderUpdate(string p_name, string p_value) - { - if(Enum.TryParse(p_name, out ModSetting l_setting)) - { - switch(l_setting) - { - case ModSetting.DesktopX: - { - Vector3 l_current = DesktopOffset; - l_current.x = int.Parse(p_value) * 0.01f; - DesktopOffset = l_current; - DesktopOffsetChange?.Invoke(l_current); - } - break; - case ModSetting.DesktopY: - { - Vector3 l_current = DesktopOffset; - l_current.y = int.Parse(p_value) * 0.01f; - DesktopOffset = l_current; - DesktopOffsetChange?.Invoke(l_current); - } - break; - case ModSetting.DesktopZ: - { - Vector3 l_current = DesktopOffset; - l_current.z = int.Parse(p_value) * 0.01f; - DesktopOffset = l_current; - DesktopOffsetChange?.Invoke(l_current); - } - break; - - case ModSetting.AngleX: - { - Vector3 l_current = RootAngle; - l_current.x = int.Parse(p_value); - RootAngle = l_current; - RootAngleChange?.Invoke(l_current); - } - break; - - case ModSetting.AngleY: - { - Vector3 l_current = RootAngle; - l_current.y = int.Parse(p_value); - RootAngle = l_current; - RootAngleChange?.Invoke(l_current); - } - break; - - case ModSetting.AngleZ: - { - Vector3 l_current = RootAngle; - l_current.z = int.Parse(p_value); - RootAngle = l_current; - RootAngleChange?.Invoke(l_current); - } - break; - - case ModSetting.HeadX: - { - Vector3 l_current = HeadOffset; - l_current.x = int.Parse(p_value) * 0.01f; - HeadOffset = l_current; - HeadOffsetChange?.Invoke(l_current); - } - break; - case ModSetting.HeadY: - { - Vector3 l_current = HeadOffset; - l_current.y = int.Parse(p_value) * 0.01f; - HeadOffset = l_current; - HeadOffsetChange?.Invoke(l_current); - } - break; - case ModSetting.HeadZ: - { - Vector3 l_current = HeadOffset; - l_current.z = int.Parse(p_value) * 0.01f; - HeadOffset = l_current; - HeadOffsetChange?.Invoke(l_current); - } - break; - case ModSetting.InteractThreadhold: - { - InteractThreadhold = int.Parse(p_value) * 0.01f; - InteractThreadholdChange?.Invoke(InteractThreadhold); - } - break; - case ModSetting.GripThreadhold: - { - GripThreadhold = int.Parse(p_value) * 0.01f; - GripThreadholdChange?.Invoke(GripThreadhold); - } - break; - } - - ms_entries[(int)l_setting].BoxedValue = int.Parse(p_value); - } - } - - static void OnDropdownUpdate(string p_name, string p_value) - { - if(Enum.TryParse(p_name, out ModSetting l_setting)) - { - switch(l_setting) - { - case ModSetting.Mode: - { - TrackingMode = (LeapTrackingMode)int.Parse(p_value); - TrackingModeChange?.Invoke(TrackingMode); - } - break; - } - - ms_entries[(int)l_setting].BoxedValue = int.Parse(p_value); - } - } - } -} +using ABI_RC.Core.InteractionSystem; +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace ml_lme +{ + static class Settings + { + public enum LeapTrackingMode + { + Screentop = 0, + Desktop, + HMD + } + + enum ModSetting + { + Enabled, + DesktopX, + DesktopY, + DesktopZ, + FingersOnly, + Model, + Mode, + AngleX, + AngleY, + AngleZ, + Head, + HeadX, + HeadY, + HeadZ, + TrackElbows, + Interaction, + Gestures, + InteractThreadhold, + GripThreadhold, + VisualHands + }; + + public static bool Enabled { get; private set; } = false; + public static Vector3 DesktopOffset { get; private set; } = new Vector3(0f, -0.45f, 0.3f); + public static bool FingersOnly { get; private set; } = false; + public static bool ModelVisibility { get; private set; } = false; + public static LeapTrackingMode TrackingMode { get; private set; } = LeapTrackingMode.Desktop; + public static Vector3 RootAngle { get; private set; } = Vector3.zero; + public static bool HeadAttach { get; private set; } = false; + public static Vector3 HeadOffset { get; private set; } = new Vector3(0f, -0.3f, 0.15f); + public static bool TrackElbows { get; private set; } = true; + public static bool Interaction { get; private set; } = true; + public static bool Gestures { get; private set; } = false; + public static float InteractThreadhold { get; private set; } = 0.8f; + public static float GripThreadhold { get; private set; } = 0.4f; + public static bool VisualHands { get; private set; } = false; + + static MelonLoader.MelonPreferences_Category ms_category = null; + static List ms_entries = null; + + static public event Action EnabledChange; + static public event Action DesktopOffsetChange; + static public event Action FingersOnlyChange; + static public event Action ModelVisibilityChange; + static public event Action TrackingModeChange; + static public event Action RootAngleChange; + static public event Action HeadAttachChange; + static public event Action HeadOffsetChange; + static public event Action TrackElbowsChange; + static public event Action InteractionChange; + static public event Action GesturesChange; + static public event Action InteractThreadholdChange; + static public event Action GripThreadholdChange; + static public event Action VisualHandsChange; + + internal static void Init() + { + ms_category = MelonLoader.MelonPreferences.CreateCategory("LME", null, true); + + ms_entries = new List() + { + ms_category.CreateEntry(ModSetting.Enabled.ToString(), Enabled), + ms_category.CreateEntry(ModSetting.DesktopX.ToString(), (int)(DesktopOffset.x * 100f)), + ms_category.CreateEntry(ModSetting.DesktopY.ToString(), (int)(DesktopOffset.y * 100f)), + ms_category.CreateEntry(ModSetting.DesktopZ.ToString(), (int)(DesktopOffset.z * 100f)), + ms_category.CreateEntry(ModSetting.FingersOnly.ToString(), FingersOnly), + ms_category.CreateEntry(ModSetting.Model.ToString(), ModelVisibility), + ms_category.CreateEntry(ModSetting.Mode.ToString(), (int)TrackingMode), + ms_category.CreateEntry(ModSetting.AngleX.ToString(), (int)(RootAngle.x * 100f)), + ms_category.CreateEntry(ModSetting.AngleY.ToString(), (int)(RootAngle.y * 100f)), + ms_category.CreateEntry(ModSetting.AngleZ.ToString(), (int)(RootAngle.z * 100f)), + ms_category.CreateEntry(ModSetting.Head.ToString(), HeadAttach), + ms_category.CreateEntry(ModSetting.HeadX.ToString(), (int)(HeadOffset.x * 100f)), + ms_category.CreateEntry(ModSetting.HeadY.ToString(), (int)(HeadOffset.y * 100f)), + ms_category.CreateEntry(ModSetting.HeadZ.ToString(), (int)(HeadOffset.z * 100f)), + ms_category.CreateEntry(ModSetting.TrackElbows.ToString(), TrackElbows), + ms_category.CreateEntry(ModSetting.Interaction.ToString(), Interaction), + ms_category.CreateEntry(ModSetting.Gestures.ToString(), Gestures), + ms_category.CreateEntry(ModSetting.InteractThreadhold.ToString(), (int)(InteractThreadhold * 100f)), + ms_category.CreateEntry(ModSetting.GripThreadhold.ToString(), (int)(GripThreadhold * 100f)), + ms_category.CreateEntry(ModSetting.VisualHands.ToString(), VisualHands) + }; + + Load(); + + MelonLoader.MelonCoroutines.Start(WaitMainMenuUi()); + } + + static System.Collections.IEnumerator WaitMainMenuUi() + { + while(ViewManager.Instance == null) + yield return null; + while(ViewManager.Instance.gameMenuView == null) + yield return null; + while(ViewManager.Instance.gameMenuView.Listener == null) + yield return null; + + ViewManager.Instance.gameMenuView.Listener.ReadyForBindings += () => + { + ViewManager.Instance.gameMenuView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action(OnToggleUpdate)); + ViewManager.Instance.gameMenuView.View.BindCall("OnSliderUpdate_" + ms_category.Identifier, new Action(OnSliderUpdate)); + ViewManager.Instance.gameMenuView.View.BindCall("OnDropdownUpdate_" + ms_category.Identifier, new Action(OnDropdownUpdate)); + }; + ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) => + { + ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js")); + ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js")); + foreach(var l_entry in ms_entries) + ViewManager.Instance.gameMenuView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString()); + }; + } + + static void Load() + { + Enabled = (bool)ms_entries[(int)ModSetting.Enabled].BoxedValue; + DesktopOffset = new Vector3( + (int)ms_entries[(int)ModSetting.DesktopX].BoxedValue, + (int)ms_entries[(int)ModSetting.DesktopY].BoxedValue, + (int)ms_entries[(int)ModSetting.DesktopZ].BoxedValue + ) * 0.01f; + FingersOnly = (bool)ms_entries[(int)ModSetting.FingersOnly].BoxedValue; + ModelVisibility = (bool)ms_entries[(int)ModSetting.Model].BoxedValue; + TrackingMode = (LeapTrackingMode)(int)ms_entries[(int)ModSetting.Mode].BoxedValue; + RootAngle = new Vector3( + (int)ms_entries[(int)ModSetting.AngleX].BoxedValue, + (int)ms_entries[(int)ModSetting.AngleY].BoxedValue, + (int)ms_entries[(int)ModSetting.AngleZ].BoxedValue + ); + HeadAttach = (bool)ms_entries[(int)ModSetting.Head].BoxedValue; + HeadOffset = new Vector3( + (int)ms_entries[(int)ModSetting.HeadX].BoxedValue, + (int)ms_entries[(int)ModSetting.HeadY].BoxedValue, + (int)ms_entries[(int)ModSetting.HeadZ].BoxedValue + ) * 0.01f; + TrackElbows = (bool)ms_entries[(int)ModSetting.TrackElbows].BoxedValue; + Interaction = (bool)ms_entries[(int)ModSetting.Interaction].BoxedValue; + Gestures = (bool)ms_entries[(int)ModSetting.Gestures].BoxedValue; + InteractThreadhold = (int)ms_entries[(int)ModSetting.InteractThreadhold].BoxedValue * 0.01f; + GripThreadhold = (int)ms_entries[(int)ModSetting.GripThreadhold].BoxedValue * 0.01f; + VisualHands = (bool)ms_entries[(int)ModSetting.VisualHands].BoxedValue; + } + + static void OnToggleUpdate(string p_name, string p_value) + { + if(Enum.TryParse(p_name, out ModSetting l_setting)) + { + switch(l_setting) + { + case ModSetting.Enabled: + { + Enabled = bool.Parse(p_value); + EnabledChange?.Invoke(Enabled); + } + break; + + case ModSetting.FingersOnly: + { + FingersOnly = bool.Parse(p_value); + FingersOnlyChange?.Invoke(FingersOnly); + } + break; + + case ModSetting.Model: + { + ModelVisibility = bool.Parse(p_value); + ModelVisibilityChange?.Invoke(ModelVisibility); + } + break; + + case ModSetting.Head: + { + HeadAttach = bool.Parse(p_value); + HeadAttachChange?.Invoke(HeadAttach); + } + break; + + case ModSetting.TrackElbows: + { + TrackElbows = bool.Parse(p_value); + TrackElbowsChange?.Invoke(TrackElbows); + } + break; + + case ModSetting.Interaction: + { + Interaction = bool.Parse(p_value); + InteractionChange?.Invoke(Interaction); + } + break; + + case ModSetting.Gestures: + { + Gestures = bool.Parse(p_value); + GesturesChange?.Invoke(Gestures); + } + break; + + case ModSetting.VisualHands: + { + VisualHands = bool.Parse(p_value); + VisualHandsChange?.Invoke(VisualHands); + } + break; + } + + ms_entries[(int)l_setting].BoxedValue = bool.Parse(p_value); + } + } + + static void OnSliderUpdate(string p_name, string p_value) + { + if(Enum.TryParse(p_name, out ModSetting l_setting)) + { + switch(l_setting) + { + case ModSetting.DesktopX: + { + Vector3 l_current = DesktopOffset; + l_current.x = int.Parse(p_value) * 0.01f; + DesktopOffset = l_current; + DesktopOffsetChange?.Invoke(l_current); + } + break; + case ModSetting.DesktopY: + { + Vector3 l_current = DesktopOffset; + l_current.y = int.Parse(p_value) * 0.01f; + DesktopOffset = l_current; + DesktopOffsetChange?.Invoke(l_current); + } + break; + case ModSetting.DesktopZ: + { + Vector3 l_current = DesktopOffset; + l_current.z = int.Parse(p_value) * 0.01f; + DesktopOffset = l_current; + DesktopOffsetChange?.Invoke(l_current); + } + break; + + case ModSetting.AngleX: + { + Vector3 l_current = RootAngle; + l_current.x = int.Parse(p_value); + RootAngle = l_current; + RootAngleChange?.Invoke(l_current); + } + break; + + case ModSetting.AngleY: + { + Vector3 l_current = RootAngle; + l_current.y = int.Parse(p_value); + RootAngle = l_current; + RootAngleChange?.Invoke(l_current); + } + break; + + case ModSetting.AngleZ: + { + Vector3 l_current = RootAngle; + l_current.z = int.Parse(p_value); + RootAngle = l_current; + RootAngleChange?.Invoke(l_current); + } + break; + + case ModSetting.HeadX: + { + Vector3 l_current = HeadOffset; + l_current.x = int.Parse(p_value) * 0.01f; + HeadOffset = l_current; + HeadOffsetChange?.Invoke(l_current); + } + break; + case ModSetting.HeadY: + { + Vector3 l_current = HeadOffset; + l_current.y = int.Parse(p_value) * 0.01f; + HeadOffset = l_current; + HeadOffsetChange?.Invoke(l_current); + } + break; + case ModSetting.HeadZ: + { + Vector3 l_current = HeadOffset; + l_current.z = int.Parse(p_value) * 0.01f; + HeadOffset = l_current; + HeadOffsetChange?.Invoke(l_current); + } + break; + case ModSetting.InteractThreadhold: + { + InteractThreadhold = int.Parse(p_value) * 0.01f; + InteractThreadholdChange?.Invoke(InteractThreadhold); + } + break; + case ModSetting.GripThreadhold: + { + GripThreadhold = int.Parse(p_value) * 0.01f; + GripThreadholdChange?.Invoke(GripThreadhold); + } + break; + } + + ms_entries[(int)l_setting].BoxedValue = int.Parse(p_value); + } + } + + static void OnDropdownUpdate(string p_name, string p_value) + { + if(Enum.TryParse(p_name, out ModSetting l_setting)) + { + switch(l_setting) + { + case ModSetting.Mode: + { + TrackingMode = (LeapTrackingMode)int.Parse(p_value); + TrackingModeChange?.Invoke(TrackingMode); + } + break; + } + + ms_entries[(int)l_setting].BoxedValue = int.Parse(p_value); + } + } + } +} diff --git a/ml_lme/VisualHand.cs b/ml_lme/VisualHand.cs deleted file mode 100644 index e9453f2..0000000 --- a/ml_lme/VisualHand.cs +++ /dev/null @@ -1,68 +0,0 @@ -using UnityEngine; - -namespace ml_lme -{ - class VisualHand - { - readonly Transform m_wrist = null; - readonly Transform[] m_fingers = null; - - public VisualHand(Transform p_root, bool p_left) - { - if(p_root != null) - { - m_wrist = p_root.Find(p_left ? "LeftHand/Wrist" : "RightHand/Wrist"); - if(m_wrist != null) - { - m_fingers = new Transform[20]; - - m_fingers[0] = null; // Actual thumb-meta, look at Leap Motion docs, dummy - m_fingers[1] = m_wrist.Find("thumb_meta"); - m_fingers[2] = m_wrist.Find("thumb_meta/thumb_a"); - m_fingers[3] = m_wrist.Find("thumb_meta/thumb_a/thumb_b"); - - m_fingers[4] = m_wrist.Find("index_meta"); - m_fingers[5] = m_wrist.Find("index_meta/index_a"); - m_fingers[6] = m_wrist.Find("index_meta/index_a/index_b"); - m_fingers[7] = m_wrist.Find("index_meta/index_a/index_b/index_c"); - - m_fingers[8] = m_wrist.Find("middle_meta"); - m_fingers[9] = m_wrist.Find("middle_meta/middle_a"); - m_fingers[10] = m_wrist.Find("middle_meta/middle_a/middle_b"); - m_fingers[11] = m_wrist.Find("middle_meta/middle_a/middle_b/middle_c"); - - m_fingers[12] = m_wrist.Find("ring_meta"); - m_fingers[13] = m_wrist.Find("ring_meta/ring_a"); - m_fingers[14] = m_wrist.Find("ring_meta/ring_a/ring_b"); - m_fingers[15] = m_wrist.Find("ring_meta/ring_a/ring_b/ring_c"); - - m_fingers[16] = m_wrist.Find("pinky_meta"); - m_fingers[17] = m_wrist.Find("pinky_meta/pinky_a"); - m_fingers[18] = m_wrist.Find("pinky_meta/pinky_a/pinky_b"); - m_fingers[19] = m_wrist.Find("pinky_meta/pinky_a/pinky_b/pinky_c"); - } - } - } - - public void Update(LeapParser.HandData p_data) - { - if(m_wrist != null) - { - m_wrist.position = p_data.m_position; - m_wrist.rotation = p_data.m_rotation; - - for(int i = 0; i < 20; i++) - { - if(m_fingers[i] != null) - { - //m_fingers[i].position = p_data.m_fingerPosition[i]; - m_fingers[i].rotation = p_data.m_fingerRotation[i]; - } - } - - m_wrist.localPosition = p_data.m_position; - m_wrist.localRotation = p_data.m_rotation; - } - } - } -} diff --git a/ml_lme/ml_lme.csproj b/ml_lme/ml_lme.csproj index 88208a6..2d70ed7 100644 --- a/ml_lme/ml_lme.csproj +++ b/ml_lme/ml_lme.csproj @@ -11,8 +11,8 @@ - none - false + embedded + true diff --git a/ml_lme/resources/leapmotion_hands.asset b/ml_lme/resources/leapmotion_hands.asset index e7f9e7a..4fc9276 100644 Binary files a/ml_lme/resources/leapmotion_hands.asset and b/ml_lme/resources/leapmotion_hands.asset differ diff --git a/ml_lme/resources/mod_menu.js b/ml_lme/resources/mod_menu.js index 235c5b4..dadaee1 100644 --- a/ml_lme/resources/mod_menu.js +++ b/ml_lme/resources/mod_menu.js @@ -1,162 +1,162 @@ -{ - let l_block = document.createElement('div'); - l_block.innerHTML = ` -
-
Leap Motion tracking
-
-
- -
-
Enable tracking:
-
-
-
-
- -
-
Tracking mode:
-
-
-
-
- -
-
Desktop offset X:
-
-
-
-
- -
-
Desktop offset Y:
-
-
-
-
- -
-
Desktop offset Z:
-
-
-
-
- -
-
Attach to head:
-
- -
-
- -
-
Head offset X:
-
-
-
-
- -
-
Head offset Y:
-
-
-
-
- -
-
Head offset Z:
-
-
-
-
- -
-
Offset angle X:
-
-
-
-
- -
-
Offset angle Y:
-
-
-
-
- -
-
Offset angle Z:
-
-
-
-
- -
-
Track elbows:
-
-
-
-
- -
-
Fingers tracking only:
-
-
-
-
- -
-
Model visibility:
-
-
-
-
- -
-
Visualize hands:
-
-
-
-
- -
-
Interaction input:
-
-
-
-
- -
-
Recognize gestures:
-
-
-
-
- -
-
Interact gesture threadhold:
-
-
-
-
- -
-
Grip gesture threadhold:
-
-
-
-
- `; - document.getElementById('settings-implementation').appendChild(l_block); - - // Toggles - for (let l_toggle of l_block.querySelectorAll('.inp_toggle')) - modsExtension.addSetting('LME', l_toggle.id, modsExtension.createToggle(l_toggle, 'OnToggleUpdate_LME')); - - // Sliders - for (let l_slider of l_block.querySelectorAll('.inp_slider')) - modsExtension.addSetting('LME', l_slider.id, modsExtension.createSlider(l_slider, 'OnSliderUpdate_LME')); - - // Dropdowns - for (let l_dropdown of l_block.querySelectorAll('.inp_dropdown')) - modsExtension.addSetting('LME', l_dropdown.id, modsExtension.createDropdown(l_dropdown, 'OnDropdownUpdate_LME')); -} +{ + let l_block = document.createElement('div'); + l_block.innerHTML = ` +
+
Leap Motion tracking
+
+
+ +
+
Enable tracking:
+
+
+
+
+ +
+
Tracking mode:
+
+
+
+
+ +
+
Desktop offset X:
+
+
+
+
+ +
+
Desktop offset Y:
+
+
+
+
+ +
+
Desktop offset Z:
+
+
+
+
+ +
+
Attach to head:
+
+ +
+
+ +
+
Head offset X:
+
+
+
+
+ +
+
Head offset Y:
+
+
+
+
+ +
+
Head offset Z:
+
+
+
+
+ +
+
Offset angle X:
+
+
+
+
+ +
+
Offset angle Y:
+
+
+
+
+ +
+
Offset angle Z:
+
+
+
+
+ +
+
Track elbows:
+
+
+
+
+ +
+
Fingers tracking only:
+
+
+
+
+ +
+
Model visibility:
+
+
+
+
+ +
+
Visualize hands:
+
+
+
+
+ +
+
Interaction input:
+
+
+
+
+ +
+
Recognize gestures:
+
+
+
+
+ +
+
Interact gesture threadhold:
+
+
+
+
+ +
+
Grip gesture threadhold:
+
+
+
+
+ `; + document.getElementById('settings-implementation').appendChild(l_block); + + // Toggles + for (let l_toggle of l_block.querySelectorAll('.inp_toggle')) + modsExtension.addSetting('LME', l_toggle.id, modsExtension.createToggle(l_toggle, 'OnToggleUpdate_LME')); + + // Sliders + for (let l_slider of l_block.querySelectorAll('.inp_slider')) + modsExtension.addSetting('LME', l_slider.id, modsExtension.createSlider(l_slider, 'OnSliderUpdate_LME')); + + // Dropdowns + for (let l_dropdown of l_block.querySelectorAll('.inp_dropdown')) + modsExtension.addSetting('LME', l_dropdown.id, modsExtension.createDropdown(l_dropdown, 'OnDropdownUpdate_LME')); +} diff --git a/ml_pmc/PoseCopycat.cs b/ml_pmc/PoseCopycat.cs index 46ea306..3ccfeaa 100644 --- a/ml_pmc/PoseCopycat.cs +++ b/ml_pmc/PoseCopycat.cs @@ -84,26 +84,56 @@ namespace ml_pmc ref readonly float[] l_curls = ref m_puppetParser.GetFingerCurls(); ref readonly float[] l_spreads = ref m_puppetParser.GetFingerSpreads(); - CVRInputManager.Instance.fingerCurlLeftThumb = l_curls[l_mirror ? 5 : 0]; - CVRInputManager.Instance.fingerCurlLeftIndex = l_curls[l_mirror ? 6 : 1]; - CVRInputManager.Instance.fingerCurlLeftMiddle = l_curls[l_mirror ? 7 : 2]; - CVRInputManager.Instance.fingerCurlLeftRing = l_curls[l_mirror ? 8 : 3]; - CVRInputManager.Instance.fingerCurlLeftPinky = l_curls[l_mirror ? 9 : 4]; - CVRInputManager.Instance.fingerCurlRightThumb = l_curls[l_mirror ? 0 : 5]; - CVRInputManager.Instance.fingerCurlRightIndex = l_curls[l_mirror ? 1 : 6]; - CVRInputManager.Instance.fingerCurlRightMiddle = l_curls[l_mirror ? 2 : 7]; - CVRInputManager.Instance.fingerCurlRightRing = l_curls[l_mirror ? 3 : 8]; - CVRInputManager.Instance.fingerCurlRightPinky = l_curls[l_mirror ? 4 : 9]; - + // Left hand + CVRInputManager.Instance.finger1StretchedLeftThumb = l_curls[l_mirror ? 15 : 0]; + CVRInputManager.Instance.finger2StretchedLeftThumb = l_curls[l_mirror ? 16 : 1]; + CVRInputManager.Instance.finger3StretchedLeftThumb = l_curls[l_mirror ? 17 : 2]; CVRInputManager.Instance.fingerSpreadLeftThumb = l_spreads[l_mirror ? 5 : 0]; + + CVRInputManager.Instance.finger1StretchedLeftIndex = l_curls[l_mirror ? 18 : 3]; + CVRInputManager.Instance.finger2StretchedLeftIndex = l_curls[l_mirror ? 19 : 4]; + CVRInputManager.Instance.finger3StretchedLeftIndex = l_curls[l_mirror ? 20 : 5]; CVRInputManager.Instance.fingerSpreadLeftIndex = l_spreads[l_mirror ? 6 : 1]; + + CVRInputManager.Instance.finger1StretchedLeftMiddle = l_curls[l_mirror ? 21 : 6]; + CVRInputManager.Instance.finger2StretchedLeftMiddle = l_curls[l_mirror ? 22 : 7]; + CVRInputManager.Instance.finger3StretchedLeftMiddle = l_curls[l_mirror ? 23 : 8]; CVRInputManager.Instance.fingerSpreadLeftMiddle = l_spreads[l_mirror ? 7 : 2]; + + CVRInputManager.Instance.finger1StretchedLeftRing = l_curls[l_mirror ? 24 : 9]; + CVRInputManager.Instance.finger2StretchedLeftRing = l_curls[l_mirror ? 25 : 10]; + CVRInputManager.Instance.finger3StretchedLeftRing = l_curls[l_mirror ? 26 : 11]; CVRInputManager.Instance.fingerSpreadLeftRing = l_spreads[l_mirror ? 8 : 3]; + + CVRInputManager.Instance.finger1StretchedLeftPinky = l_curls[l_mirror ? 27 : 12]; + CVRInputManager.Instance.finger2StretchedLeftPinky = l_curls[l_mirror ? 28 : 13]; + CVRInputManager.Instance.finger3StretchedLeftPinky = l_curls[l_mirror ? 29 : 14]; CVRInputManager.Instance.fingerSpreadLeftPinky = l_spreads[l_mirror ? 9 : 4]; + + // Right hand + CVRInputManager.Instance.finger1StretchedRightThumb = l_curls[l_mirror ? 0 : 15]; + CVRInputManager.Instance.finger2StretchedRightThumb = l_curls[l_mirror ? 1 : 16]; + CVRInputManager.Instance.finger3StretchedRightThumb = l_curls[l_mirror ? 2 : 17]; CVRInputManager.Instance.fingerSpreadRightThumb = l_spreads[l_mirror ? 0 : 5]; + + CVRInputManager.Instance.finger1StretchedRightIndex = l_curls[l_mirror ? 3 : 18]; + CVRInputManager.Instance.finger2StretchedRightIndex = l_curls[l_mirror ? 4 : 19]; + CVRInputManager.Instance.finger3StretchedRightIndex = l_curls[l_mirror ? 5 : 20]; CVRInputManager.Instance.fingerSpreadRightIndex = l_spreads[l_mirror ? 1 : 6]; + + CVRInputManager.Instance.finger1StretchedRightMiddle = l_curls[l_mirror ? 6 : 21]; + CVRInputManager.Instance.finger2StretchedRightMiddle = l_curls[l_mirror ? 7 : 22]; + CVRInputManager.Instance.finger3StretchedRightMiddle = l_curls[l_mirror ? 8 : 23]; CVRInputManager.Instance.fingerSpreadRightMiddle = l_spreads[l_mirror ? 2 : 7]; + + CVRInputManager.Instance.finger1StretchedRightRing = l_curls[l_mirror ? 9 : 24]; + CVRInputManager.Instance.finger2StretchedRightRing = l_curls[l_mirror ? 10 : 25]; + CVRInputManager.Instance.finger3StretchedRightRing = l_curls[l_mirror ? 11 : 26]; CVRInputManager.Instance.fingerSpreadRightRing = l_spreads[l_mirror ? 3 : 8]; + + CVRInputManager.Instance.finger1StretchedRightPinky = l_curls[l_mirror ? 12 : 27]; + CVRInputManager.Instance.finger2StretchedRightPinky = l_curls[l_mirror ? 13 : 28]; + CVRInputManager.Instance.finger3StretchedRightPinky = l_curls[l_mirror ? 14 : 29]; CVRInputManager.Instance.fingerSpreadRightPinky = l_spreads[l_mirror ? 4 : 9]; } else @@ -341,27 +371,69 @@ namespace ml_pmc if(!CVRInputManager.Instance.individualFingerTracking) { - CVRInputManager.Instance.fingerCurlLeftThumb = 0f; - CVRInputManager.Instance.fingerCurlLeftIndex = 0f; - CVRInputManager.Instance.fingerCurlLeftMiddle = 0f; - CVRInputManager.Instance.fingerCurlLeftRing = 0f; - CVRInputManager.Instance.fingerCurlLeftPinky = 0f; - CVRInputManager.Instance.fingerCurlRightThumb = 0f; - CVRInputManager.Instance.fingerCurlRightIndex = 0f; - CVRInputManager.Instance.fingerCurlRightMiddle = 0f; - CVRInputManager.Instance.fingerCurlRightRing = 0f; - CVRInputManager.Instance.fingerCurlRightPinky = 0f; + // Left hand + CVRInputManager.Instance.finger1StretchedLeftThumb = -0.5f; + CVRInputManager.Instance.finger2StretchedLeftThumb = 0.7f; + CVRInputManager.Instance.finger3StretchedLeftThumb = 0.7f; + CVRInputManager.Instance.fingerSpreadLeftThumb = 0f; - CVRInputManager.Instance.fingerSpreadLeftThumb = 0.5f; - CVRInputManager.Instance.fingerSpreadLeftIndex = 0.5f; - CVRInputManager.Instance.fingerSpreadLeftMiddle = 0.5f; - CVRInputManager.Instance.fingerSpreadLeftRing = 0.5f; - CVRInputManager.Instance.fingerSpreadLeftPinky = 0.5f; - CVRInputManager.Instance.fingerSpreadRightThumb = 0.5f; - CVRInputManager.Instance.fingerSpreadRightIndex = 0.5f; - CVRInputManager.Instance.fingerSpreadRightMiddle = 0.5f; - CVRInputManager.Instance.fingerSpreadRightRing = 0.5f; - CVRInputManager.Instance.fingerSpreadRightPinky = 0.5f; + CVRInputManager.Instance.finger1StretchedLeftIndex = 0.5f; + CVRInputManager.Instance.finger2StretchedLeftIndex = 0.7f; + CVRInputManager.Instance.finger3StretchedLeftIndex = 0.7f; + CVRInputManager.Instance.fingerSpreadLeftIndex = 0f; + + CVRInputManager.Instance.finger1StretchedLeftMiddle = 0.5f; + CVRInputManager.Instance.finger2StretchedLeftMiddle = 0.7f; + CVRInputManager.Instance.finger3StretchedLeftMiddle = 0.7f; + CVRInputManager.Instance.fingerSpreadLeftMiddle = 0f; + + CVRInputManager.Instance.finger1StretchedLeftRing = 0.5f; + CVRInputManager.Instance.finger2StretchedLeftRing = 0.7f; + CVRInputManager.Instance.finger3StretchedLeftRing = 0.7f; + CVRInputManager.Instance.fingerSpreadLeftRing = 0f; + + CVRInputManager.Instance.finger1StretchedLeftPinky = 0.5f; + CVRInputManager.Instance.finger2StretchedLeftPinky = 0.7f; + CVRInputManager.Instance.finger3StretchedLeftPinky = 0.7f; + CVRInputManager.Instance.fingerSpreadLeftPinky = 0f; + + CVRInputManager.Instance.fingerFullCurlNormalizedLeftThumb = 0f; + CVRInputManager.Instance.fingerFullCurlNormalizedLeftIndex = 0f; + CVRInputManager.Instance.fingerFullCurlNormalizedLeftMiddle = 0f; + CVRInputManager.Instance.fingerFullCurlNormalizedLeftRing = 0f; + CVRInputManager.Instance.fingerFullCurlNormalizedLeftPinky = 0f; + + // Right hand + CVRInputManager.Instance.finger1StretchedRightThumb = -0.5f; + CVRInputManager.Instance.finger2StretchedRightThumb = 0.7f; + CVRInputManager.Instance.finger3StretchedRightThumb = 0.7f; + CVRInputManager.Instance.fingerSpreadRightThumb = 0f; + + CVRInputManager.Instance.finger1StretchedRightIndex = 0.5f; + CVRInputManager.Instance.finger2StretchedRightIndex = 0.7f; + CVRInputManager.Instance.finger3StretchedRightIndex = 0.7f; + CVRInputManager.Instance.fingerSpreadRightIndex = 0f; + + CVRInputManager.Instance.finger1StretchedRightMiddle = 0.5f; + CVRInputManager.Instance.finger2StretchedRightMiddle = 0.7f; + CVRInputManager.Instance.finger3StretchedRightMiddle = 0.7f; + CVRInputManager.Instance.fingerSpreadRightMiddle = 0f; + + CVRInputManager.Instance.finger1StretchedRightRing = 0.5f; + CVRInputManager.Instance.finger2StretchedRightRing = 0.7f; + CVRInputManager.Instance.finger3StretchedRightRing = 0.7f; + CVRInputManager.Instance.fingerSpreadRightRing = 0f; + + CVRInputManager.Instance.finger1StretchedRightPinky = 0.5f; + CVRInputManager.Instance.finger2StretchedRightPinky = 0.7f; + CVRInputManager.Instance.finger3StretchedRightPinky = 0.7f; + CVRInputManager.Instance.fingerSpreadRightPinky = 0f; + + CVRInputManager.Instance.fingerFullCurlNormalizedRightThumb = 0f; + CVRInputManager.Instance.fingerFullCurlNormalizedRightIndex = 0f; + CVRInputManager.Instance.fingerFullCurlNormalizedRightMiddle = 0f; + CVRInputManager.Instance.fingerFullCurlNormalizedRightRing = 0f; + CVRInputManager.Instance.fingerFullCurlNormalizedRightPinky = 0f; } } } diff --git a/ml_pmc/PuppetParser.cs b/ml_pmc/PuppetParser.cs index fece340..046a798 100644 --- a/ml_pmc/PuppetParser.cs +++ b/ml_pmc/PuppetParser.cs @@ -1,108 +1,136 @@ -using ABI_RC.Core.Player; -using UnityEngine; - -namespace ml_pmc -{ - [DisallowMultipleComponent] - class PuppetParser : MonoBehaviour - { - internal PuppetMaster m_puppetMaster = null; - Animator m_animator = null; - AnimatorCullingMode m_cullMode; - - HumanPoseHandler m_poseHandler = null; - HumanPose m_pose; - - Matrix4x4 m_matrix = Matrix4x4.identity; - Matrix4x4 m_offset = Matrix4x4.identity; - - bool m_sitting = false; - float m_leftGesture = 0f; - float m_rightGesture = 0f; - bool m_fingerTracking = false; - readonly float[] m_fingerCurls = null; - readonly float[] m_fingerSpreads = null; - - internal PuppetParser() - { - m_fingerCurls = new float[10]; - m_fingerSpreads = new float[10]; - } - - // Unity events - void Start() - { - m_animator = this.GetComponent(); - m_cullMode = m_animator.cullingMode; - m_animator.cullingMode = AnimatorCullingMode.AlwaysAnimate; - m_poseHandler = new HumanPoseHandler(m_animator.avatar, m_animator.transform); - m_poseHandler.GetHumanPose(ref m_pose); - m_matrix = this.transform.GetMatrix(); - } - - void OnDestroy() - { - m_puppetMaster = null; - if(m_animator != null) - m_animator.cullingMode = m_cullMode; - m_animator = null; - - m_poseHandler?.Dispose(); - m_poseHandler = null; - } - - void Update() - { - if(m_puppetMaster != null) - { - m_sitting = m_puppetMaster.PlayerAvatarMovementDataInput.AnimatorSitting; - m_leftGesture = m_puppetMaster.PlayerAvatarMovementDataInput.AnimatorGestureLeft; - m_rightGesture = m_puppetMaster.PlayerAvatarMovementDataInput.AnimatorGestureRight; - m_fingerTracking = m_puppetMaster.PlayerAvatarMovementDataInput.IndexUseIndividualFingers; - if(m_fingerTracking) - { - m_fingerCurls[0] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftThumbCurl; - m_fingerCurls[1] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftIndexCurl; - m_fingerCurls[2] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftMiddleCurl; - m_fingerCurls[3] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftRingCurl; - m_fingerCurls[4] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftPinkyCurl; - m_fingerCurls[5] = m_puppetMaster.PlayerAvatarMovementDataInput.RightThumbCurl; - m_fingerCurls[6] = m_puppetMaster.PlayerAvatarMovementDataInput.RightIndexCurl; - m_fingerCurls[7] = m_puppetMaster.PlayerAvatarMovementDataInput.RightMiddleCurl; - m_fingerCurls[8] = m_puppetMaster.PlayerAvatarMovementDataInput.RightRingCurl; - m_fingerCurls[9] = m_puppetMaster.PlayerAvatarMovementDataInput.RightPinkyCurl; - - m_fingerSpreads[0] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftThumbSpread; - m_fingerSpreads[1] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftIndexSpread; - m_fingerSpreads[2] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftMiddleSpread; - m_fingerSpreads[3] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftRingSpread; - m_fingerSpreads[4] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftPinkySpread; - m_fingerSpreads[5] = m_puppetMaster.PlayerAvatarMovementDataInput.RightThumbSpread; - m_fingerSpreads[6] = m_puppetMaster.PlayerAvatarMovementDataInput.RightIndexSpread; - m_fingerSpreads[7] = m_puppetMaster.PlayerAvatarMovementDataInput.RightMiddleSpread; - m_fingerSpreads[8] = m_puppetMaster.PlayerAvatarMovementDataInput.RightRingSpread; - m_fingerSpreads[9] = m_puppetMaster.PlayerAvatarMovementDataInput.RightPinkySpread; - } - - Matrix4x4 l_current = this.transform.GetMatrix(); - m_offset = m_matrix.inverse * l_current; - m_matrix = l_current; - } - } - - void LateUpdate() - { - if((m_animator != null) && (m_poseHandler != null)) - m_poseHandler.GetHumanPose(ref m_pose); - } - - public ref HumanPose GetPose() => ref m_pose; - public ref Matrix4x4 GetLastOffset() => ref m_offset; - public bool IsSitting() => m_sitting; - public float GetLeftGesture() => m_leftGesture; - public float GetRightGesture() => m_rightGesture; - public bool HasFingerTracking() => m_fingerTracking; - public ref readonly float[] GetFingerCurls() => ref m_fingerCurls; - public ref readonly float[] GetFingerSpreads() => ref m_fingerSpreads; - } -} +using ABI_RC.Core.Player; +using UnityEngine; + +namespace ml_pmc +{ + [DisallowMultipleComponent] + class PuppetParser : MonoBehaviour + { + internal PuppetMaster m_puppetMaster = null; + Animator m_animator = null; + AnimatorCullingMode m_cullMode; + + HumanPoseHandler m_poseHandler = null; + HumanPose m_pose; + + Matrix4x4 m_matrix = Matrix4x4.identity; + Matrix4x4 m_offset = Matrix4x4.identity; + + bool m_sitting = false; + float m_leftGesture = 0f; + float m_rightGesture = 0f; + bool m_fingerTracking = false; + readonly float[] m_fingerCurls = null; + readonly float[] m_fingerSpreads = null; + + internal PuppetParser() + { + m_fingerCurls = new float[30]; + m_fingerSpreads = new float[10]; + } + + // Unity events + void Start() + { + m_animator = this.GetComponent(); + m_cullMode = m_animator.cullingMode; + m_animator.cullingMode = AnimatorCullingMode.AlwaysAnimate; + m_poseHandler = new HumanPoseHandler(m_animator.avatar, m_animator.transform); + m_poseHandler.GetHumanPose(ref m_pose); + m_matrix = this.transform.GetMatrix(); + } + + void OnDestroy() + { + m_puppetMaster = null; + if(m_animator != null) + m_animator.cullingMode = m_cullMode; + m_animator = null; + + m_poseHandler?.Dispose(); + m_poseHandler = null; + } + + void Update() + { + if(m_puppetMaster != null) + { + m_sitting = m_puppetMaster.PlayerAvatarMovementDataInput.AnimatorSitting; + m_leftGesture = m_puppetMaster.PlayerAvatarMovementDataInput.AnimatorGestureLeft; + m_rightGesture = m_puppetMaster.PlayerAvatarMovementDataInput.AnimatorGestureRight; + m_fingerTracking = m_puppetMaster.PlayerAvatarMovementDataInput.UseIndividualFingers; + if(m_fingerTracking) + { + m_fingerCurls[0] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftThumb1Stretched; + m_fingerCurls[1] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftThumb2Stretched; + m_fingerCurls[2] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftThumb3Stretched; + m_fingerSpreads[0] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftThumbSpread; + + m_fingerCurls[3] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftIndex1Stretched; + m_fingerCurls[4] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftIndex2Stretched; + m_fingerCurls[5] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftIndex3Stretched; + m_fingerSpreads[1] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftIndexSpread; + + m_fingerCurls[6] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftMiddle1Stretched; + m_fingerCurls[7] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftMiddle2Stretched; + m_fingerCurls[8] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftMiddle3Stretched; + m_fingerSpreads[2] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftMiddleSpread; + + m_fingerCurls[9] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftRing1Stretched; + m_fingerCurls[10] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftRing2Stretched; + m_fingerCurls[11] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftRing3Stretched; + m_fingerSpreads[3] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftRingSpread; + + m_fingerCurls[12] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftPinky1Stretched; + m_fingerCurls[13] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftPinky2Stretched; + m_fingerCurls[14] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftPinky3Stretched; + m_fingerSpreads[4] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftPinkySpread; + + m_fingerCurls[15] = m_puppetMaster.PlayerAvatarMovementDataInput.RightThumb1Stretched; + m_fingerCurls[16] = m_puppetMaster.PlayerAvatarMovementDataInput.RightThumb2Stretched; + m_fingerCurls[17] = m_puppetMaster.PlayerAvatarMovementDataInput.RightThumb3Stretched; + m_fingerSpreads[5] = m_puppetMaster.PlayerAvatarMovementDataInput.RightThumbSpread; + + m_fingerCurls[18] = m_puppetMaster.PlayerAvatarMovementDataInput.RightIndex1Stretched; + m_fingerCurls[19] = m_puppetMaster.PlayerAvatarMovementDataInput.RightIndex2Stretched; + m_fingerCurls[20] = m_puppetMaster.PlayerAvatarMovementDataInput.RightIndex3Stretched; + m_fingerSpreads[6] = m_puppetMaster.PlayerAvatarMovementDataInput.RightIndexSpread; + + m_fingerCurls[21] = m_puppetMaster.PlayerAvatarMovementDataInput.RightMiddle1Stretched; + m_fingerCurls[22] = m_puppetMaster.PlayerAvatarMovementDataInput.RightMiddle2Stretched; + m_fingerCurls[23] = m_puppetMaster.PlayerAvatarMovementDataInput.RightMiddle3Stretched; + m_fingerSpreads[7] = m_puppetMaster.PlayerAvatarMovementDataInput.RightMiddleSpread; + + m_fingerCurls[24] = m_puppetMaster.PlayerAvatarMovementDataInput.RightRing1Stretched; + m_fingerCurls[25] = m_puppetMaster.PlayerAvatarMovementDataInput.RightRing2Stretched; + m_fingerCurls[26] = m_puppetMaster.PlayerAvatarMovementDataInput.RightRing3Stretched; + m_fingerSpreads[8] = m_puppetMaster.PlayerAvatarMovementDataInput.RightRingSpread; + + m_fingerCurls[27] = m_puppetMaster.PlayerAvatarMovementDataInput.RightPinky1Stretched; + m_fingerCurls[28] = m_puppetMaster.PlayerAvatarMovementDataInput.RightPinky2Stretched; + m_fingerCurls[29] = m_puppetMaster.PlayerAvatarMovementDataInput.RightPinky3Stretched; + m_fingerSpreads[9] = m_puppetMaster.PlayerAvatarMovementDataInput.RightPinkySpread; + } + + Matrix4x4 l_current = this.transform.GetMatrix(); + m_offset = m_matrix.inverse * l_current; + m_matrix = l_current; + } + } + + void LateUpdate() + { + if((m_animator != null) && (m_poseHandler != null)) + m_poseHandler.GetHumanPose(ref m_pose); + } + + public ref HumanPose GetPose() => ref m_pose; + public ref Matrix4x4 GetLastOffset() => ref m_offset; + public bool IsSitting() => m_sitting; + public float GetLeftGesture() => m_leftGesture; + public float GetRightGesture() => m_rightGesture; + public bool HasFingerTracking() => m_fingerTracking; + public ref readonly float[] GetFingerCurls() => ref m_fingerCurls; + public ref readonly float[] GetFingerSpreads() => ref m_fingerSpreads; + } +}