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