// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) VRMADA, All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- using UltimateXR.Core; using UltimateXR.Core.Math; using UltimateXR.Extensions.Unity; using UltimateXR.Extensions.Unity.Math; using UnityEngine; namespace UltimateXR.Animation.IK { /// /// IK solver that distributes a wrist torsion among different bones in a forearm in order to smooth it out. /// public class UxrWristTorsionIKSolver : UxrIKSolver { #region Inspector Properties/Serialized Fields [SerializeField] [Range(0.0f, 1.0f)] private float _amount = 1.0f; #endregion #region Public Types & Data /// /// Gets or sets the amount of torsion to apply on this Transform from the source. 0 = no torsion, 1 = full torsion, /// etc. /// public float Amount { get => _amount; set => _amount = value; } #endregion #region Public Overrides UxrIKSolver /// public override bool Initialized => _initialized; #endregion #region Unity /// /// Initializes the component. /// protected override void Awake() { base.Awake(); _handSide = transform.HasParent(Avatar.AvatarRig.LeftArm.UpperArm) ? UxrHandSide.Left : UxrHandSide.Right; _startLocalRotation = transform.localRotation; UxrUniversalLocalAxes handUniversalLocalAxes = Avatar.AvatarRigInfo.GetArmInfo(_handSide).HandUniversalLocalAxes; _torsionLocalAxis = transform.InverseTransformDirection(handUniversalLocalAxes.WorldForward).GetClosestAxis(); _initialized = true; } #endregion #region Protected Overrides UxrIKSolver /// /// Solves the Inverse Kinematics. /// protected override void InternalSolveIK() { float angle = Avatar.AvatarRigInfo.GetArmInfo(_handSide).WristTorsionInfo.WristTorsionAngle; transform.localRotation = _startLocalRotation * Quaternion.AngleAxis(angle * Amount, _torsionLocalAxis); } #endregion #region Private Types & Data private bool _initialized; private UxrHandSide _handSide; private Quaternion _startLocalRotation; private Vector3 _torsionLocalAxis; #endregion } }