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;
}
}
}