mixedreality/com.microsoft.mixedreality..../Core/Providers/Hands/HandJointService.cs

192 lines
7.3 KiB
C#

// 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<TrackedHandJoint, Transform> leftHandFauxJoints = new Dictionary<TrackedHandJoint, Transform>();
private Dictionary<TrackedHandJoint, Transform> rightHandFauxJoints = new Dictionary<TrackedHandJoint, Transform>();
#region BaseInputDeviceManager Implementation
/// <summary>
/// Constructor.
/// </summary>
/// <param name="registrar">The <see cref="IMixedRealityServiceRegistrar"/> instance that loaded the data provider.</param>
/// <param name="inputSystem">The <see cref="Microsoft.MixedReality.Toolkit.Input.IMixedRealityInputSystem"/> instance that receives data from this provider.</param>
/// <param name="name">Friendly name of the service.</param>
/// <param name="priority">Service priority. Used to determine order of instantiation.</param>
/// <param name="profile">The service's configuration profile.</param>
[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;
}
/// <summary>
/// Constructor.
/// </summary>
/// <param name="inputSystem">The <see cref="Microsoft.MixedReality.Toolkit.Input.IMixedRealityInputSystem"/> instance that receives data from this provider.</param>
/// <param name="name">Friendly name of the service.</param>
/// <param name="priority">Service priority. Used to determine order of instantiation.</param>
/// <param name="profile">The service's configuration profile.</param>
public HandJointService(
IMixedRealityInputSystem inputSystem,
string name,
uint priority,
BaseMixedRealityProfile profile) : base(inputSystem, name, priority, profile) { }
/// <inheritdoc />
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);
}
}
}
}
/// <inheritdoc />
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<TrackedHandJoint, Transform> 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
}
}