// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) VRMADA, All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- using System; using System.Collections.Generic; using UltimateXR.Core; using UltimateXR.Extensions.Unity; using UnityEngine; namespace UltimateXR.Avatar.Rig { /// /// /// Stores references to all elements in an avatar rig. These are the components of the /// bones that drive the visual representation of a humanoid avatar. /// /// It also contains functionality to transform the hand using hand poses. /// [Serializable] public partial class UxrAvatarRig { #region Inspector Properties/Serialized Fields [SerializeField] private UxrAvatarHead _head; [SerializeField] private UxrAvatarArm _leftArm; [SerializeField] private UxrAvatarArm _rightArm; [SerializeField] private Transform _upperChest; [SerializeField] private Transform _chest; [SerializeField] private Transform _spine; [SerializeField] private Transform _hips; [SerializeField] private UxrAvatarLeg _leftLeg; [SerializeField] private UxrAvatarLeg _rightLeg; #endregion #region Public Types & Data /// /// Number of fingers in a hand. /// public const int HandFingerCount = 5; /// /// Gets a sequence of all the non-null transforms in the avatar rig. /// public IEnumerable Transforms { get { foreach (Transform transform in Head.Transforms) { yield return transform; } foreach (Transform transform in LeftArm.Transforms) { yield return transform; } foreach (Transform transform in RightArm.Transforms) { yield return transform; } foreach (Transform transform in LeftLeg.Transforms) { yield return transform; } foreach (Transform transform in RightLeg.Transforms) { yield return transform; } if (UpperChest != null) { yield return UpperChest; } if (Chest != null) { yield return Chest; } if (Spine != null) { yield return Spine; } if (Hips != null) { yield return Hips; } } } /// /// Gets the head. /// public UxrAvatarHead Head => _head; /// /// Gets the left arm. /// public UxrAvatarArm LeftArm => _leftArm; /// /// Gets the right arm. /// public UxrAvatarArm RightArm => _rightArm; /// /// Gets the upper chest transform or null if there isn't any. /// public Transform UpperChest => _upperChest; /// /// Gets the chest transform or null if there isn't any. /// public Transform Chest => _chest; /// /// Gets the spine transform or null if there isn't any. /// public Transform Spine => _spine; /// /// Gets the hips transform or null if there isn't any. /// public Transform Hips => _hips; /// /// Gets the left leg. /// public UxrAvatarLeg LeftLeg => _leftLeg; /// /// Gets the right leg. /// public UxrAvatarLeg RightLeg => _rightLeg; #endregion #region Constructors & Finalizer /// /// Constructor. /// public UxrAvatarRig() { ClearRigElements(); } #endregion #region Public Methods /// /// Checks which side a transform is part of, based on which wrist it hangs from or if it hangs from an /// . /// /// Transform to check which side it is part of /// Returns the side, if found /// Whether a side was found public static bool GetHandSide(Transform transform, out UxrHandSide side) { UxrAvatar avatar = transform.SafeGetComponentInParent(); if (avatar) { if (transform.HasParent(avatar.LeftHandBone)) { side = UxrHandSide.Left; return true; } if (transform.HasParent(avatar.RightHandBone)) { side = UxrHandSide.Right; return true; } UxrHandIntegration handIntegration = transform.SafeGetComponentInParent(); if (handIntegration) { side = handIntegration.HandSide; return true; } } side = UxrHandSide.Left; return false; } /// /// Sets all the rig element references to null. /// public void ClearRigElements() { _head = new UxrAvatarHead(); _leftArm = new UxrAvatarArm(); _rightArm = new UxrAvatarArm(); _leftLeg = new UxrAvatarLeg(); _rightLeg = new UxrAvatarLeg(); _upperChest = null; _chest = null; _spine = null; _hips = null; } /// /// Gets the avatar arms. /// /// Avatar arms public IEnumerable GetArms() { if (_leftArm != null) { yield return _leftArm; } if (_rightArm != null) { yield return _rightArm; } } /// /// Gets whether the given rig has any of the references used in upper body IK (head, neck, upper chest, chest or /// spine). /// /// Whether the given rig has any upper body reference used in IK public bool HasAnyUpperBodyIKReference() { return _head.Head != null || _head.Neck != null || _upperChest != null || _chest != null || _spine != null; } /// /// Gets whether the given rig has all arm references (upper arm, forearm and hand). /// /// Whether the given rig has arm references for both sides public bool HasArmData() { return LeftArm.Hand.Wrist != null && RightArm.Hand.Wrist != null && LeftArm.Forearm != null && RightArm.Forearm != null && LeftArm.UpperArm != null && RightArm.UpperArm != null; } /// /// Gets whether the given rig has all hand and finger bone references. /// /// Whether the given rig has all the references public bool HasFullHandData() { return LeftArm.Hand.Wrist != null && RightArm.Hand.Wrist != null && LeftArm.Hand.HasFingerData() && RightArm.Hand.HasFingerData(); } /// /// Gets whether the given rig has all finger data. /// /// Whether the given rig has all finger data of both hands public bool HasFingerData() { return LeftArm.Hand.HasFingerData() && RightArm.Hand.HasFingerData(); } /// /// Gets whether the given rig has all finger data. /// /// Which hand to check /// Whether the given rig has the given hand finger data public bool HasFingerData(UxrHandSide handSide) { return handSide == UxrHandSide.Left ? LeftArm.Hand.HasFingerData() : RightArm.Hand.HasFingerData(); } #endregion } }