using Facepunch.XR; namespace Sandbox.VR; partial record VRController { class JointDataContainer { public InputPoseHandState Pose; private readonly VRHandJointData[] _jointData = new VRHandJointData[Enum.GetValues().Length]; internal Transform GetBoneTransform( VRHandJoint joint ) { var index = (int)joint; return Pose[index].pose.GetTransform(); } public VRHandJointData[] GetJoints() { UpdateJointData(); return _jointData; } private void UpdateJointData() { for ( int i = 0; i < _jointData.Length; i++ ) { ref var jointData = ref _jointData[i]; var joint = (VRHandJoint)i; jointData.Joint = joint; jointData.Transform = GetBoneTransform( joint ); } } } private JointDataContainer _handJoints = new(); private JointDataContainer _conformingJoints = new(); internal Transform GetBoneTransform( VRHandJoint joint, MotionRange motionRange ) { if ( motionRange == MotionRange.Hand ) return _handJoints.GetBoneTransform( joint ); else if ( motionRange == MotionRange.Controller ) return _conformingJoints.GetBoneTransform( joint ); return Transform.Zero; } /// /// Returns joint data for a specific motion range. /// /// Whether the joints returned represent a raw hand pose, or one that represents the hand wrapping around the controller. public VRHandJointData[] GetJoints( MotionRange motionRange = MotionRange.Hand ) { if ( motionRange == MotionRange.Hand ) return _handJoints.GetJoints(); else if ( motionRange == MotionRange.Controller ) return _conformingJoints.GetJoints(); return Array.Empty(); } /// /// Get the skeletal value (from 0 to 1) of a specified - includes curl and splay. /// public float GetFingerValue( FingerValue value ) { bool isCurl = value == FingerValue.ThumbCurl || value == FingerValue.IndexCurl || value == FingerValue.MiddleCurl || value == FingerValue.RingCurl || value == FingerValue.PinkyCurl; if ( isCurl ) { return VRNative.GetFingerCurl( _trackedDevice.InputSource, value ); } return 0; } /// /// Get the skeletal value (from 0 to 1) of a specified finger curl index. /// public float GetFingerCurl( int index ) { if ( index < 0 ) throw new ArgumentOutOfRangeException( "Should be 0-4", nameof( index ) ); if ( index > 4 ) throw new ArgumentOutOfRangeException( "Should be 0-4", nameof( index ) ); return GetFingerValue( (FingerValue)index ); } /// /// Get the skeletal value (from 0 to 1) of a specified finger splay index. /// public float GetFingerSplay( int index ) { if ( index < 0 ) throw new ArgumentOutOfRangeException( "Should be 0-3", nameof( index ) ); if ( index > 3 ) throw new ArgumentOutOfRangeException( "Should be 0-3", nameof( index ) ); return GetFingerValue( (FingerValue.ThumbIndexSplay + index) ); } private readonly List _jointList = new(); [Obsolete( "Please use GetJoints()" )] public List GetJointData() { _jointList.Clear(); _jointList.AddRange( GetJoints( MotionRange.Hand ) ); return _jointList; } }