// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) VRMADA, All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- using System; using UltimateXR.Avatar; using UltimateXR.Avatar.Rig; using UltimateXR.Core; using UltimateXR.Core.Math; using UnityEngine; namespace UltimateXR.Manipulation.HandPoses { /// /// Stores base-independent node orientations for all fingers of a hand. /// [Serializable] public class UxrHandDescriptor { #region Inspector Properties/Serialized Fields [SerializeField] private UxrFingerDescriptor _index; [SerializeField] private UxrFingerDescriptor _middle; [SerializeField] private UxrFingerDescriptor _ring; [SerializeField] private UxrFingerDescriptor _little; [SerializeField] private UxrFingerDescriptor _thumb; #endregion #region Public Types & Data /// /// Gets the index finger information. /// public UxrFingerDescriptor Index => _index; /// /// Gets the middle finger information. /// public UxrFingerDescriptor Middle => _middle; /// /// Gets the ring finger information. /// public UxrFingerDescriptor Ring => _ring; /// /// Gets the little finger information. /// public UxrFingerDescriptor Little => _little; /// /// Gets the thumb finger information. /// public UxrFingerDescriptor Thumb => _thumb; #endregion #region Constructors & Finalizer /// /// Default constructor. /// public UxrHandDescriptor() { _index = new UxrFingerDescriptor(); _middle = new UxrFingerDescriptor(); _ring = new UxrFingerDescriptor(); _little = new UxrFingerDescriptor(); _thumb = new UxrFingerDescriptor(); } /// /// Constructor. /// /// Avatar whose hand to compute the descriptor for /// Which hand to process public UxrHandDescriptor(UxrAvatar avatar, UxrHandSide handSide) { _index = new UxrFingerDescriptor(); _middle = new UxrFingerDescriptor(); _ring = new UxrFingerDescriptor(); _little = new UxrFingerDescriptor(); _thumb = new UxrFingerDescriptor(); Compute(avatar, handSide); } /// /// Constructor. /// /// Arm whose hand to compute the descriptor for /// Hand axes system /// Finger axes system public UxrHandDescriptor(UxrAvatarArm arm, UxrUniversalLocalAxes handLocalAxes, UxrUniversalLocalAxes fingerLocalAxes) { _index = new UxrFingerDescriptor(); _middle = new UxrFingerDescriptor(); _ring = new UxrFingerDescriptor(); _little = new UxrFingerDescriptor(); _thumb = new UxrFingerDescriptor(); Compute(arm, handLocalAxes, fingerLocalAxes); } #endregion #region Public Methods /// /// Gets the given finger. /// /// Which finger to get /// Finger information public UxrFingerDescriptor GetFinger(UxrFingerType fingerType) { switch (fingerType) { case UxrFingerType.Thumb: return Thumb; case UxrFingerType.Index: return Index; case UxrFingerType.Middle: return Middle; case UxrFingerType.Ring: return Ring; case UxrFingerType.Little: return Little; default: throw new ArgumentOutOfRangeException(nameof(fingerType), fingerType, null); } } /// /// Computes the hand data. /// /// Avatar to compute the hand data of /// Which hand to compute the hand data of /// Whether to compute the relative transform to the hand only public void Compute(UxrAvatar avatar, UxrHandSide handSide, bool computeRelativeMatrixOnly = false) { Compute(handSide == UxrHandSide.Left ? avatar.AvatarRig.LeftArm : avatar.AvatarRig.RightArm, avatar.AvatarRigInfo.GetArmInfo(handSide).HandUniversalLocalAxes, avatar.AvatarRigInfo.GetArmInfo(handSide).FingerUniversalLocalAxes, computeRelativeMatrixOnly); } /// /// Computes the hand data. /// /// Arm where the hand is /// Hand axes system /// Finger axes system /// Whether to compute the relative transform to the hand only public void Compute(UxrAvatarArm arm, UxrUniversalLocalAxes handLocalAxes, UxrUniversalLocalAxes fingerLocalAxes, bool computeRelativeMatrixOnly = false) { _index.Compute(arm.Hand.Wrist, arm.Hand.Index, handLocalAxes, fingerLocalAxes, computeRelativeMatrixOnly); _middle.Compute(arm.Hand.Wrist, arm.Hand.Middle, handLocalAxes, fingerLocalAxes, computeRelativeMatrixOnly); _ring.Compute(arm.Hand.Wrist, arm.Hand.Ring, handLocalAxes, fingerLocalAxes, computeRelativeMatrixOnly); _little.Compute(arm.Hand.Wrist, arm.Hand.Little, handLocalAxes, fingerLocalAxes, computeRelativeMatrixOnly); _thumb.Compute(arm.Hand.Wrist, arm.Hand.Thumb, handLocalAxes, fingerLocalAxes, computeRelativeMatrixOnly); } /// /// Copies the data from another descriptor. /// /// Source data public void CopyFrom(UxrHandDescriptor src) { _index = src._index; _middle = src._middle; _ring = src._ring; _little = src._little; _thumb = src._thumb; } /// /// Interpolates the data towards another descriptor. /// /// Descriptor to interpolate the data to /// Interpolation factor [0.0, 1.0] public void InterpolateTo(UxrHandDescriptor to, float t) { _index.InterpolateTo(to._index, t); _middle.InterpolateTo(to._middle, t); _ring.InterpolateTo(to._ring, t); _little.InterpolateTo(to._little, t); _thumb.InterpolateTo(to._thumb, t); } #if UNITY_EDITOR /// /// Outputs transform data in the editor window. /// public void DrawEditorDebugLabels() { _index.DrawEditorDebugLabels("index: "); _middle.DrawEditorDebugLabels("middle: "); _ring.DrawEditorDebugLabels("ring: "); _little.DrawEditorDebugLabels("little: "); _thumb.DrawEditorDebugLabels("thumb: "); } #endif /// /// Returns a hand descriptor with mirrored transforms, so that the data can be used for the opposite hand. /// /// Mirrored hand descriptor public UxrHandDescriptor Mirrored() { UxrHandDescriptor mirroredHandDescriptor = new UxrHandDescriptor(); mirroredHandDescriptor.CopyFrom(this); mirroredHandDescriptor._index.Mirror(); mirroredHandDescriptor._middle.Mirror(); mirroredHandDescriptor._ring.Mirror(); mirroredHandDescriptor._little.Mirror(); mirroredHandDescriptor._thumb.Mirror(); return mirroredHandDescriptor; } /// /// Checks whether a hand descriptor contains the same transform data. /// /// Hand descriptor to compare it to /// Whether the hand descriptor contains the same transform data public bool Equals(UxrHandDescriptor other) { if (other != null) { return _index.Equals(other._index) && _middle.Equals(other._middle) && _ring.Equals(other._ring) && _little.Equals(other._little) && _thumb.Equals(other._thumb); } return false; } #endregion } }