// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using Microsoft.MixedReality.Toolkit.Utilities; using System.Collections.Generic; using UnityEngine; namespace Microsoft.MixedReality.Toolkit.Input { [MixedRealityDataProvider( typeof(IMixedRealityInputSystem), (SupportedPlatforms)(-1), // All platforms supported by Unity "Hand Joint Service")] [HelpURL("https://docs.microsoft.com/windows/mixed-reality/mrtk-unity/features/input/hand-tracking")] public class HandJointService : BaseInputDeviceManager, IMixedRealityHandJointService { private IMixedRealityHand leftHand; private IMixedRealityHand rightHand; private Dictionary leftHandFauxJoints = new Dictionary(); private Dictionary rightHandFauxJoints = new Dictionary(); #region BaseInputDeviceManager Implementation /// /// Constructor. /// /// The instance that loaded the data provider. /// The instance that receives data from this provider. /// Friendly name of the service. /// Service priority. Used to determine order of instantiation. /// The service's configuration profile. [System.Obsolete("This constructor is obsolete (registrar parameter is no longer required) and will be removed in a future version of the Microsoft Mixed Reality Toolkit.")] public HandJointService( IMixedRealityServiceRegistrar registrar, IMixedRealityInputSystem inputSystem, string name, uint priority, BaseMixedRealityProfile profile) : this(inputSystem, name, priority, profile) { Registrar = registrar; } /// /// Constructor. /// /// The instance that receives data from this provider. /// Friendly name of the service. /// Service priority. Used to determine order of instantiation. /// The service's configuration profile. public HandJointService( IMixedRealityInputSystem inputSystem, string name, uint priority, BaseMixedRealityProfile profile) : base(inputSystem, name, priority, profile) { } /// public override void LateUpdate() { base.LateUpdate(); leftHand = null; rightHand = null; foreach (var detectedController in Service.DetectedControllers) { if (detectedController is IMixedRealityHand hand) { if (detectedController.ControllerHandedness == Handedness.Left) { if (leftHand == null) { leftHand = hand; } } else if (detectedController.ControllerHandedness == Handedness.Right) { if (rightHand == null) { rightHand = hand; } } } } if (leftHand != null) { foreach (var fauxJoint in leftHandFauxJoints) { if (leftHand.TryGetJoint(fauxJoint.Key, out MixedRealityPose pose)) { fauxJoint.Value.SetPositionAndRotation(pose.Position, pose.Rotation); } } } if (rightHand != null) { foreach (var fauxJoint in rightHandFauxJoints) { if (rightHand.TryGetJoint(fauxJoint.Key, out MixedRealityPose pose)) { fauxJoint.Value.SetPositionAndRotation(pose.Position, pose.Rotation); } } } } /// public override void Disable() { base.Disable(); // Check existence of fauxJoints before destroying. This avoids a (harmless) race // condition when the service is getting destroyed at the same time that the gameObjects // are being destroyed at shutdown. if (leftHandFauxJoints != null) { foreach (var fauxJoint in leftHandFauxJoints.Values) { if (fauxJoint != null) { Object.Destroy(fauxJoint.gameObject); } } leftHandFauxJoints.Clear(); } if (rightHandFauxJoints != null) { foreach (var fauxJoint in rightHandFauxJoints.Values) { if (fauxJoint != null) { Object.Destroy(fauxJoint.gameObject); } } rightHandFauxJoints.Clear(); } } #endregion BaseInputDeviceManager Implementation #region IMixedRealityHandJointService Implementation public Transform RequestJointTransform(TrackedHandJoint joint, Handedness handedness) { IMixedRealityHand hand = null; Dictionary fauxJoints = null; if (handedness == Handedness.Left) { hand = leftHand; fauxJoints = leftHandFauxJoints; } else if (handedness == Handedness.Right) { hand = rightHand; fauxJoints = rightHandFauxJoints; } else { return null; } Transform jointTransform = null; if (fauxJoints != null && !fauxJoints.TryGetValue(joint, out jointTransform)) { jointTransform = new GameObject().transform; // Since this service survives scene loading and unloading, the fauxJoints it manages need to as well. Object.DontDestroyOnLoad(jointTransform.gameObject); jointTransform.name = string.Format("Joint Tracker: {1} {0}", joint, handedness); if (hand != null && hand.TryGetJoint(joint, out MixedRealityPose pose)) { jointTransform.SetPositionAndRotation(pose.Position, pose.Rotation); } fauxJoints.Add(joint, jointTransform); } return jointTransform; } public bool IsHandTracked(Handedness handedness) { return handedness == Handedness.Left ? leftHand != null : handedness == Handedness.Right && rightHand != null; } #endregion IMixedRealityHandJointService Implementation } }