using System; using Unity.Collections; namespace UnityEngine.XR.Hands.Processing { /// /// Utility methods for processing joints from a . /// public static class XRHandProcessingUtility { /// /// Sets the subsystem's hand corresponding to hand passed in, which must /// have been initially retrieved from the 's /// or /// property. /// /// /// The invoking subsystem for this extension method. To call this method, /// call .SetCorrespondingHand() on an . /// /// /// The hand to update to on the subsystem. Must have originally been /// retrieved from that /// public static void SetCorrespondingHand(this XRHandSubsystem subsystem, XRHand hand) { if (hand.handedness == Handedness.Left) subsystem.SetLeftHand(hand); else if (hand.handedness == Handedness.Right) subsystem.SetRightHand(hand); else throw new InvalidOperationException("Cannot set hand on subsystem that was not initially retrieved from a subsystem's leftHand or rightHand properties!"); } /// /// Gets the of /// contained in the invoking hand. /// /// /// The invoking hand for this extension method. To call this method, /// call .GetRawJointArray() on an . /// /// /// The raw joint array contained in the supplied hand. /// /// /// After manipulating data for a particular joint, be sure to assign it /// back to the array you got it from, as you can only manipulate copies /// of objects from a . /// public static NativeArray GetRawJointArray(this XRHand hand) { if (hand.handedness == Handedness.Invalid) throw new ArgumentException("Cannot manipulate joints on an invalid hand. Only use hands retrieved from an XRHandSubsystem's leftHand or rightHand property."); return hand.m_Joints; } /// /// Sets the of the invoking . /// /// /// The invoking hand for this extension method. To call this method, /// call .SetRootPose(modifiedRootPose) on an . /// /// /// The root to set for the . /// /// /// Be sure to follow this with a call to yourHandSubsystem.SetCorrespondingHand(modifiedHand), /// or you will only update the root pose of a copy of a hand. /// public static void SetRootPose(this ref XRHand hand, Pose rootPose) { if (hand.handedness == Handedness.Invalid) throw new ArgumentException("Cannot set root pose on an invalid hand. Only use hands retrieved from an XRHandSubsystem's leftHand or rightHand property."); var offsetRotation = rootPose.rotation * Quaternion.Inverse(hand.m_RootPose.rotation); for (int jointIndex = 0; jointIndex < hand.m_Joints.Length; ++jointIndex) { if (hand.m_Joints[jointIndex].TryGetPose(out var pose)) { pose.position = offsetRotation * (pose.position - hand.m_RootPose.position) + rootPose.position; pose.rotation = offsetRotation * pose.rotation; var joint = hand.m_Joints[jointIndex]; joint.SetPose(pose); hand.m_Joints[jointIndex] = joint; } } hand.m_RootPose = rootPose; } /// /// Sets the pose that can be retrieved from /// and sets the flag for that pose to be valid. /// /// /// The invoking joint for this extension method. To call this method, /// call .SetPose(modifiedPose) on an . /// /// /// The to set for the . /// /// /// After manipulating data for a particular joint, be sure to assign it /// back to the array you got it from, as you can only manipulate copies /// of objects from a . /// public static void SetPose(this ref XRHandJoint joint, Pose pose) { if (joint.m_TrackingState.HasFlag(XRHandJointTrackingState.WillNeverBeValid)) throw new ArgumentException("Cannot set pose on a joint that was not registered as being part of the hand layout for this subsystem's provider.", nameof(joint)); joint.m_TrackingState |= XRHandJointTrackingState.Pose; joint.m_Pose = pose; } /// /// Sets the velocity that can be retrieved from /// and sets the flag for that data to be valid. /// /// /// The invoking joint for this extension method. To call this method, /// call .SetLinearVelocity(modifiedVelocity) on an . /// /// /// The linear velocity to set for the . /// /// /// After manipulating data for a particular joint, be sure to assign it /// back to the array you got it from, as you can only manipulate copies /// of objects from a . /// public static void SetLinearVelocity(this ref XRHandJoint joint, Vector3 linearVelocity) { if (joint.m_TrackingState.HasFlag(XRHandJointTrackingState.WillNeverBeValid)) throw new ArgumentException("Cannot set linear velocity on a joint that was not registered as being part of the hand layout for this subsystem's provider.", nameof(joint)); joint.m_TrackingState |= XRHandJointTrackingState.LinearVelocity; joint.m_LinearVelocity = linearVelocity; } /// /// Sets the velocity that can be retrieved from /// and sets the flag for that data to be valid. /// /// /// The invoking joint for this extension method. To call this method, /// call .SetAngularVelocity(modifiedVelocity) on an . /// /// /// The angular velocity to set for the . /// /// /// After manipulating data for a particular joint, be sure to assign it /// back to the array you got it from, as you can only manipulate copies /// of objects from a . /// public static void SetAngularVelocity(this ref XRHandJoint joint, Vector3 angularVelocity) { if (joint.m_TrackingState.HasFlag(XRHandJointTrackingState.WillNeverBeValid)) throw new ArgumentException("Cannot set angular velocity on a joint that was not registered as being part of the hand layout for this subsystem's provider.", nameof(joint)); joint.m_TrackingState |= XRHandJointTrackingState.AngularVelocity; joint.m_AngularVelocity = angularVelocity; } } }