// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using Microsoft.MixedReality.Toolkit.Utilities; using System; using System.Collections.Generic; using UnityEngine; namespace Microsoft.MixedReality.Toolkit.Input { /// /// Snapshot of simulated hand data. /// [Serializable] public class SimulatedHandData { [SerializeField] private bool isTracked = false; /// /// Whether the hand is currently being tracked /// public bool IsTracked => isTracked; [SerializeField] private MixedRealityPose[] joints = new MixedRealityPose[ArticulatedHandPose.JointCount]; /// /// Array storing the joints of the hand /// public MixedRealityPose[] Joints => joints; [SerializeField] private bool isPinching = false; /// /// Whether the hand is pinching /// public bool IsPinching => isPinching; /// /// Generator function producing joint positions and rotations /// public delegate void HandJointDataGenerator(MixedRealityPose[] jointPoses); public void Copy(SimulatedHandData other) { isTracked = other.isTracked; isPinching = other.isPinching; for (int i = 0; i < ArticulatedHandPose.JointCount; ++i) { joints[i] = other.joints[i]; } } /// /// Replace the hand data with the given values. /// /// True if the hand data has been changed. /// True if the hand is currently tracked. /// True if the hand is in a pinching pose that causes a "Select" action. /// Generator function that produces joint positions and rotations. The joint data generator is only used when the hand is tracked. /// The timestamp of the hand data will be the current time, see [DateTime.UtcNow](https://docs.microsoft.com/dotnet/api/system.datetime.utcnow?view=netframework-4.8). public bool Update(bool isTrackedNew, bool isPinchingNew, HandJointDataGenerator generator) { bool handDataChanged = false; if (isTracked != isTrackedNew || isPinching != isPinchingNew) { isTracked = isTrackedNew; isPinching = isPinchingNew; handDataChanged = true; } if (isTracked) { generator?.Invoke(Joints); handDataChanged = true; } return handDataChanged; } } public abstract class SimulatedHand : BaseHand { public abstract ControllerSimulationMode SimulationMode { get; } protected readonly Dictionary jointPoses = new Dictionary(); /// /// Constructor. /// protected SimulatedHand( TrackingState trackingState, Handedness controllerHandedness, IMixedRealityInputSource inputSource = null, MixedRealityInteractionMapping[] interactions = null, IMixedRealityInputSourceDefinition definition = null) : base(trackingState, controllerHandedness, inputSource, interactions, definition) { } /// public override bool TryGetJoint(TrackedHandJoint joint, out MixedRealityPose pose) => jointPoses.TryGetValue(joint, out pose); public void UpdateState(SimulatedHandData handData) { UpdateHandJoints(handData); UpdateVelocity(); UpdateInteractions(handData); } /// /// Updates the positions and orientations of the hand joints of the simulated hand /// /// hand data provided by the simulation protected abstract void UpdateHandJoints(SimulatedHandData handData); /// /// Updates the interactions raised by the simulated hand /// /// hand data provided by the simulation protected abstract void UpdateInteractions(SimulatedHandData handData); } }