241 lines
8.6 KiB
C#
241 lines
8.6 KiB
C#
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
|
|
using Microsoft.MixedReality.Toolkit.Utilities;
|
|
using Unity.Profiling;
|
|
using UnityEngine;
|
|
|
|
namespace Microsoft.MixedReality.Toolkit.Input.UnityInput
|
|
{
|
|
[MixedRealityController(
|
|
SupportedControllerType.TouchScreen,
|
|
new[] { Handedness.Any })]
|
|
public class UnityTouchController : BaseController
|
|
{
|
|
public UnityTouchController(
|
|
TrackingState trackingState,
|
|
Handedness controllerHandedness,
|
|
IMixedRealityInputSource inputSource = null,
|
|
MixedRealityInteractionMapping[] interactions = null)
|
|
: base(trackingState, controllerHandedness, inputSource, interactions, new TouchScreenDefinition())
|
|
{ }
|
|
|
|
/// <summary>
|
|
/// Time in seconds to determine if the contact registers as a tap or a hold
|
|
/// </summary>
|
|
public float MaxTapContactTime { get; set; } = 0.5f;
|
|
|
|
/// <summary>
|
|
/// The threshold a finger must move before starting a manipulation gesture.
|
|
/// </summary>
|
|
public float ManipulationThreshold { get; set; } = 5f;
|
|
|
|
/// <summary>
|
|
/// Current Touch Data for the Controller.
|
|
/// </summary>
|
|
public Touch TouchData { get; internal set; }
|
|
|
|
/// <summary>
|
|
/// Current Screen point ray for the Touch.
|
|
/// </summary>
|
|
public Ray ScreenPointRay { get; internal set; }
|
|
|
|
/// <summary>
|
|
/// The current lifetime of the Touch.
|
|
/// </summary>
|
|
public float Lifetime { get; private set; } = 0.0f;
|
|
|
|
private bool isTouched;
|
|
private MixedRealityInputAction holdingAction;
|
|
private bool isHolding;
|
|
private MixedRealityInputAction manipulationAction;
|
|
private bool isManipulating;
|
|
private MixedRealityPose lastPose = MixedRealityPose.ZeroIdentity;
|
|
|
|
/// <inheritdoc />
|
|
public override void SetupDefaultInteractions()
|
|
{
|
|
base.SetupDefaultInteractions();
|
|
|
|
if (CoreServices.InputSystem?.InputSystemProfile.GesturesProfile != null)
|
|
{
|
|
var gestures = CoreServices.InputSystem.InputSystemProfile.GesturesProfile.Gestures;
|
|
for (int i = 0; i < gestures.Length; i++)
|
|
{
|
|
var gesture = gestures[i];
|
|
|
|
switch (gesture.GestureType)
|
|
{
|
|
case GestureInputType.Hold:
|
|
holdingAction = gesture.Action;
|
|
break;
|
|
case GestureInputType.Manipulation:
|
|
manipulationAction = gesture.Action;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool isNewController = false;
|
|
|
|
/// <summary>
|
|
/// Start the touch.
|
|
/// </summary>
|
|
public void StartTouch()
|
|
{
|
|
// Indicate that this is a new controller.
|
|
isNewController = true;
|
|
}
|
|
|
|
private static readonly ProfilerMarker UpdatePerfMarker = new ProfilerMarker("[MRTK] UnityTouchController.Update");
|
|
|
|
/// <summary>
|
|
/// Update the touch data.
|
|
/// </summary>
|
|
public void Update()
|
|
{
|
|
using (UpdatePerfMarker.Auto())
|
|
{
|
|
var inputSystem = CoreServices.InputSystem;
|
|
if (inputSystem == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (isNewController)
|
|
{
|
|
isNewController = false;
|
|
|
|
inputSystem.RaiseOnInputDown(InputSource, Handedness.None, Interactions[2].MixedRealityInputAction);
|
|
inputSystem.RaisePointerDown(InputSource.Pointers[0], Interactions[2].MixedRealityInputAction);
|
|
isTouched = true;
|
|
inputSystem.RaiseGestureStarted(this, holdingAction);
|
|
isHolding = true;
|
|
}
|
|
|
|
if (!isTouched)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Lifetime += Time.deltaTime;
|
|
|
|
if (TouchData.phase == TouchPhase.Moved)
|
|
{
|
|
Interactions[0].Vector2Data = TouchData.deltaPosition;
|
|
|
|
if (Interactions[0].Changed)
|
|
{
|
|
inputSystem.RaisePositionInputChanged(InputSource, ControllerHandedness, Interactions[0].MixedRealityInputAction, TouchData.deltaPosition);
|
|
}
|
|
|
|
lastPose.Position = InputSource.Pointers[0].Position;
|
|
lastPose.Rotation = InputSource.Pointers[0].Rotation;
|
|
inputSystem.RaiseSourcePoseChanged(InputSource, this, lastPose);
|
|
|
|
Interactions[1].PoseData = lastPose;
|
|
|
|
if (Interactions[1].Changed)
|
|
{
|
|
inputSystem.RaisePoseInputChanged(InputSource, ControllerHandedness, Interactions[1].MixedRealityInputAction, lastPose);
|
|
}
|
|
|
|
if (!isManipulating)
|
|
{
|
|
if (Mathf.Abs(TouchData.deltaPosition.x) > ManipulationThreshold ||
|
|
Mathf.Abs(TouchData.deltaPosition.y) > ManipulationThreshold)
|
|
{
|
|
inputSystem?.RaiseGestureCanceled(this, holdingAction);
|
|
isHolding = false;
|
|
|
|
inputSystem?.RaiseGestureStarted(this, manipulationAction);
|
|
isManipulating = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
inputSystem.RaiseGestureUpdated(this, manipulationAction, TouchData.deltaPosition);
|
|
}
|
|
|
|
// Send dragged event, to inform manipulation handlers.
|
|
inputSystem.RaisePointerDragged(InputSource.Pointers[0], Interactions[1].MixedRealityInputAction);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static readonly ProfilerMarker EndTouchPerfMarker = new ProfilerMarker("[MRTK] UnityTouchController.EndTouch");
|
|
|
|
/// <summary>
|
|
/// End the touch.
|
|
/// </summary>
|
|
public void EndTouch()
|
|
{
|
|
using (EndTouchPerfMarker.Auto())
|
|
{
|
|
var inputSystem = CoreServices.InputSystem;
|
|
|
|
if (inputSystem == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (TouchData.phase == TouchPhase.Ended)
|
|
{
|
|
if (Lifetime < MaxTapContactTime)
|
|
{
|
|
if (isHolding)
|
|
{
|
|
inputSystem.RaiseGestureCanceled(this, holdingAction);
|
|
isHolding = false;
|
|
}
|
|
|
|
if (isManipulating)
|
|
{
|
|
inputSystem.RaiseGestureCanceled(this, manipulationAction);
|
|
isManipulating = false;
|
|
}
|
|
|
|
inputSystem.RaisePointerClicked(InputSource.Pointers[0], Interactions[2].MixedRealityInputAction, TouchData.tapCount);
|
|
}
|
|
|
|
if (isHolding)
|
|
{
|
|
inputSystem.RaiseGestureCompleted(this, holdingAction);
|
|
isHolding = false;
|
|
}
|
|
|
|
if (isManipulating)
|
|
{
|
|
inputSystem.RaiseGestureCompleted(this, manipulationAction, TouchData.deltaPosition);
|
|
isManipulating = false;
|
|
}
|
|
}
|
|
|
|
if (isHolding)
|
|
{
|
|
inputSystem.RaiseGestureCompleted(this, holdingAction);
|
|
isHolding = false;
|
|
}
|
|
|
|
Debug.Assert(!isHolding);
|
|
|
|
if (isManipulating)
|
|
{
|
|
inputSystem.RaiseGestureCompleted(this, manipulationAction, TouchData.deltaPosition);
|
|
isManipulating = false;
|
|
}
|
|
|
|
Debug.Assert(!isManipulating);
|
|
|
|
inputSystem.RaiseOnInputUp(InputSource, Handedness.None, Interactions[2].MixedRealityInputAction);
|
|
inputSystem.RaisePointerUp(InputSource.Pointers[0], Interactions[2].MixedRealityInputAction);
|
|
|
|
Lifetime = 0.0f;
|
|
isTouched = false;
|
|
Interactions[1].PoseData = MixedRealityPose.ZeroIdentity;
|
|
Interactions[0].Vector2Data = Vector2.zero;
|
|
}
|
|
}
|
|
}
|
|
} |