mixedreality/com.microsoft.mixedreality..../SDK/Features/Input/Handlers/ControllerPoseSynchronizer.cs

256 lines
9.0 KiB
C#

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.MixedReality.Toolkit.Utilities;
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit.Input
{
/// <summary>
/// Waits for a controller to be initialized, then synchronizes its transform position to a specified handedness.
/// </summary>
[AddComponentMenu("Scripts/MRTK/SDK/ControllerPoseSynchronizer")]
public class ControllerPoseSynchronizer : InputSystemGlobalHandlerListener, IMixedRealityControllerPoseSynchronizer
{
#region Helpers
/// <summary>
/// Helper function used to determine whether or not the controller pose synchronizer is configured to make use of the SourcePoseEventData
/// </summary>
protected bool SourcePoseDataUsable<T>(SourcePoseEventData<T> eventData)
{
return ((UseSourcePoseAsFallback && !poseActionDetected) || UseSourcePoseData) && eventData.SourceId == Controller?.InputSource.SourceId;
}
/// <summary>
/// Helper function used to determine whether or not the controller pose synchronizer is configured to make use of the InputEventData
/// </summary>
protected bool InputEventDataUsable<T>(InputEventData<T> eventData)
{
return !UseSourcePoseData && eventData.SourceId == Controller?.InputSource.SourceId && PoseAction == eventData.MixedRealityInputAction;
}
#endregion
#region IMixedRealityControllerPoseSynchronizer Implementation
/// <inheritdoc />
public Handedness Handedness
{
get => Controller == null ? Handedness.None : Controller.ControllerHandedness;
}
[SerializeField]
[Tooltip("Should this GameObject clean itself up when its controller is lost?")]
private bool destroyOnSourceLost = true;
/// <inheritdoc />
public bool DestroyOnSourceLost
{
get => destroyOnSourceLost;
set => destroyOnSourceLost = value;
}
/// <summary>
/// Is the controller this Synchronizer is registered to currently tracked?
/// </summary>
public bool IsTracked => TrackingState == TrackingState.Tracked;
/// <summary>
/// The current tracking state of the assigned <see cref="Microsoft.MixedReality.Toolkit.Input.IMixedRealityController"/>
/// </summary>
protected TrackingState TrackingState = TrackingState.NotTracked;
private IMixedRealityController controller;
/// <inheritdoc />
public virtual IMixedRealityController Controller
{
get => controller;
set => controller = value;
}
[SerializeField]
[Tooltip("Should the Transform's position be driven from the source pose or from input handler?")]
private bool useSourcePoseData = true;
/// <inheritdoc />
public bool UseSourcePoseData
{
get => useSourcePoseData;
set => useSourcePoseData = value;
}
[SerializeField]
[Tooltip("Should the Transform's position use the source pose by default until the input handler events are received?")]
private bool useSourcePoseAsFallback = true;
/// <summary>
/// Should the Transform's position use the source pose by default until the input handler events are received?
/// </summary>
public bool UseSourcePoseAsFallback
{
get => useSourcePoseAsFallback;
set => useSourcePoseAsFallback = value;
}
/// <summary>
/// Tracks whether or not a pose action event has been fired is actively being used by the pointer
/// </summary>
private bool poseActionDetected;
[SerializeField]
[Tooltip("The input action that will drive the Transform's pose, position, or rotation.")]
private MixedRealityInputAction poseAction = MixedRealityInputAction.None;
/// <inheritdoc />
public MixedRealityInputAction PoseAction
{
get => poseAction;
set => poseAction = value;
}
#endregion IMixedRealityControllerPoseSynchronizer Implementation
#region InputSystemGlobalHandlerListener Implementation
/// <inheritdoc />
protected override void RegisterHandlers()
{
CoreServices.InputSystem?.RegisterHandler<IMixedRealityControllerPoseSynchronizer>(this);
}
/// <inheritdoc />
protected override void UnregisterHandlers()
{
CoreServices.InputSystem?.UnregisterHandler<IMixedRealityControllerPoseSynchronizer>(this);
}
#endregion InputSystemGlobalHandlerListener Implementation
#region IMixedRealitySourcePoseHandler Implementation
/// <inheritdoc />
public virtual void OnSourceDetected(SourceStateEventData eventData) { }
/// <inheritdoc />
public virtual void OnSourceLost(SourceStateEventData eventData)
{
if (eventData.SourceId == Controller?.InputSource.SourceId &&
eventData.Controller?.ControllerHandedness == Handedness)
{
poseActionDetected = false;
TrackingState = TrackingState.NotTracked;
if (DestroyOnSourceLost)
{
GameObjectExtensions.DestroyGameObject(gameObject);
}
}
}
/// <inheritdoc />
public virtual void OnSourcePoseChanged(SourcePoseEventData<TrackingState> eventData)
{
if (eventData.SourceId == Controller?.InputSource.SourceId)
{
TrackingState = eventData.SourceData;
}
}
/// <inheritdoc />
public virtual void OnSourcePoseChanged(SourcePoseEventData<Vector2> eventData) { }
/// <inheritdoc />
public virtual void OnSourcePoseChanged(SourcePoseEventData<Vector3> eventData)
{
if (SourcePoseDataUsable(eventData))
{
TrackingState = eventData.Controller.TrackingState;
transform.position = eventData.SourceData;
}
}
/// <inheritdoc />
public virtual void OnSourcePoseChanged(SourcePoseEventData<Quaternion> eventData)
{
if (SourcePoseDataUsable(eventData))
{
TrackingState = eventData.Controller.TrackingState;
transform.rotation = eventData.SourceData;
}
}
/// <inheritdoc />
public virtual void OnSourcePoseChanged(SourcePoseEventData<MixedRealityPose> eventData)
{
if (SourcePoseDataUsable(eventData))
{
TrackingState = eventData.Controller.TrackingState;
transform.SetPositionAndRotation(eventData.SourceData.Position, eventData.SourceData.Rotation);
}
}
#endregion IMixedRealitySourcePoseHandler Implementation
#region IMixedRealityInputHandler Implementation
/// <inheritdoc />
public virtual void OnInputUp(InputEventData eventData) { }
/// <inheritdoc />
public virtual void OnInputDown(InputEventData eventData) { }
/// <inheritdoc />
public virtual void OnInputChanged(InputEventData<float> eventData) { }
/// <inheritdoc />
public virtual void OnInputChanged(InputEventData<Vector2> eventData) { }
/// <inheritdoc />
public virtual void OnInputChanged(InputEventData<Vector3> eventData)
{
if (InputEventDataUsable(eventData))
{
poseActionDetected = true;
TrackingState = TrackingState.Tracked;
transform.position = eventData.InputData;
}
}
/// <inheritdoc />
public virtual void OnInputChanged(InputEventData<Quaternion> eventData)
{
if (InputEventDataUsable(eventData))
{
poseActionDetected = true;
TrackingState = TrackingState.Tracked;
transform.rotation = eventData.InputData;
}
}
/// <inheritdoc />
public virtual void OnInputChanged(InputEventData<MixedRealityPose> eventData)
{
if (InputEventDataUsable(eventData))
{
poseActionDetected = true;
TrackingState = TrackingState.Tracked;
transform.SetPositionAndRotation(eventData.InputData.Position, eventData.InputData.Rotation);
}
}
#endregion IMixedRealityInputHandler Implementation
#region Obsolete
#pragma warning disable 0414
[SerializeField]
[HideInInspector]
[System.Obsolete("Use the Handedness property instead to get current handedness which is set by Controller attached")]
[Tooltip("Use the Handedness property instead to get current handedness which is set by Controller attached")]
private Handedness handedness = Handedness.Left;
#pragma warning restore 0414
#endregion
}
}