using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace UnityEngine.XR.Hands.Gestures
{
///
/// Description of a hand shape, which is a set of constraints on some or all of the fingers' shapes.
///
[CreateAssetMenu(fileName = "New Hand Shape", menuName = "XR/Hand Interactions/Hand Shape")]
public class XRHandShape : ScriptableObject
{
const float k_DefaultShapeTolerance = 0.3f;
[SerializeField]
[Tooltip("The finger shape conditions that must be met for this hand shape to be considered detected. " +
"The conditions are checked in order, ending at the first false condition. " +
"Usually the thumb and index should be first to rule out many other hand shapes.")]
List m_FingerShapeConditions = new List();
///
/// The list of finger state conditions for this hand shape.
///
public List fingerShapeConditions
{
get => m_FingerShapeConditions;
set => m_FingerShapeConditions = value;
}
///
/// Check the hand shape against the given updated hand joint data.
///
///
/// The check will end early if the hand is not tracked or after the
/// first finger state condition is found to be .
/// The order of the conditions will determine the order they are checked.
///
///
/// The hand joints updated event arguments to reference for the latest hand.
///
///
/// Returns if all the finger state conditions are met.
/// Otherwise, returns .
///
public bool CheckConditions(XRHandJointsUpdatedEventArgs eventArgs)
{
if (!eventArgs.hand.isTracked)
return false;
for (var index = 0; index < m_FingerShapeConditions.Count; ++index)
{
if (!m_FingerShapeConditions[index].CheckCondition(eventArgs))
return false;
}
return true;
}
#if UNITY_EDITOR
// In Editor only, allow modifications to the hand shape to update the finger state types needed for this condition
void OnValidate()
{
for (var index = 0; index < m_FingerShapeConditions.Count; ++index)
{
var condition = m_FingerShapeConditions[index];
for (int i = 0; i < condition.targets.Length; ++i)
{
// Upgrade any deprecated single tolerance range values to support separate upper and lower tolerances
var target = condition.targets[i];
#pragma warning disable 618
if (target.tolerance != 0f)
{
var targetCopy = target;
targetCopy.tolerance = target.tolerance;
condition.targets[i] = targetCopy;
EditorUtility.SetDirty(this);
AssetDatabase.SaveAssets();
}
#pragma warning restore 618
}
condition.UpdateTypesNeededIfDirty();
}
}
[ContextMenu("Reset All Tolerances")]
void ResetAllTolerances()
{
for (var index = 0; index < m_FingerShapeConditions.Count; ++index)
{
var condition = m_FingerShapeConditions[index];
for (var i = 0; i < condition.targets.Length; i++)
{
condition.targets[i].upperTolerance = k_DefaultShapeTolerance;
condition.targets[i].lowerTolerance = k_DefaultShapeTolerance;
}
}
}
#endif
}
}