// ENABLE_VR is not defined on Game Core but the assembly is available with limited features when the XR module is enabled.
// These are the guards that Input System uses in GenericXRDevice.cs to define the XRController and XRHMD classes.
#if ((ENABLE_VR || UNITY_GAMECORE) && AR_FOUNDATION_PRESENT) || PACKAGE_DOCS_GENERATION
using System.Text;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.EnhancedTouch;
using UnityEngine.InputSystem.Layouts;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.Scripting;
namespace UnityEngine.XR.Interaction.Toolkit.AR.Inputs
{
///
/// An input device representing mobile 2D screen gestures.
///
[InputControlLayout(stateType = typeof(TouchscreenGestureInputControllerState), displayName = "Touchscreen Gesture Input Controller", isGenericTypeOfDevice = true, updateBeforeRender = false)]
[Preserve]
public class TouchscreenGestureInputController : InputSystem.XR.XRController, IInputUpdateCallbackReceiver
{
///
/// The screen position where the tap gesture started.
///
public Vector2Control tapStartPosition { get; private set; }
///
/// The screen position where the drag gesture started.
///
public Vector2Control dragStartPosition { get; private set; }
///
/// The current screen position of the drag gesture.
///
public Vector2Control dragCurrentPosition { get; private set; }
///
/// The delta screen position of the drag gesture.
///
public Vector2Control dragDelta { get; private set; }
///
/// The screen position of the first finger where the pinch gesture started.
///
public Vector2Control pinchStartPosition1 { get; private set; }
///
/// The screen position of the second finger where the pinch gesture started.
///
public Vector2Control pinchStartPosition2 { get; private set; }
///
/// The gap between then position of the first and second fingers for the pinch gesture.
///
public AxisControl pinchGap { get; private set; }
///
/// The gap delta between then position of the first and second fingers for the pinch gesture.
///
public AxisControl pinchGapDelta { get; private set; }
///
/// The screen position of the first finger where the twist gesture started.
///
public Vector2Control twistStartPosition1 { get; private set; }
///
/// The screen position of the second finger where the twist gesture started.
///
public Vector2Control twistStartPosition2 { get; private set; }
///
/// The delta rotation of the twist gesture.
///
public AxisControl twistDeltaRotation { get; private set; }
///
/// The screen position of the first finger where the two-finger drag gesture started.
///
public Vector2Control twoFingerDragStartPosition1 { get; private set; }
///
/// The screen position of the second finger where the two-finger drag gesture started.
///
public Vector2Control twoFingerDragStartPosition2 { get; private set; }
///
/// The current screen position of the two-finger drag gesture.
///
public Vector2Control twoFingerDragCurrentPosition { get; private set; }
///
/// The delta screen position of the two-finger drag gesture.
///
public Vector2Control twoFingerDragDelta { get; private set; }
///
/// The number of fingers on the touchscreen.
///
public IntegerControl fingerCount { get; private set; }
///
/// (Read Only) The Tap gesture recognizer.
///
public TapGestureRecognizer tapGestureRecognizer { get; private set; }
///
/// (Read Only) The Drag gesture recognizer.
///
public DragGestureRecognizer dragGestureRecognizer { get; private set; }
///
/// (Read Only) The Pinch gesture recognizer.
///
public PinchGestureRecognizer pinchGestureRecognizer { get; private set; }
///
/// (Read Only) The Twist gesture recognizer.
///
public TwistGestureRecognizer twistGestureRecognizer { get; private set; }
///
/// (Read Only) The two-finger Drag gesture recognizer.
///
public TwoFingerDragGestureRecognizer twoFingerDragGestureRecognizer { get; private set; }
TouchscreenGestureInputControllerState m_ControllerState;
///
/// Finishes setting up all the input values for the controller.
///
protected override void FinishSetup()
{
base.FinishSetup();
tapStartPosition = GetChildControl(nameof(tapStartPosition));
dragStartPosition = GetChildControl(nameof(dragStartPosition));
dragCurrentPosition = GetChildControl(nameof(dragCurrentPosition));
dragDelta = GetChildControl(nameof(dragDelta));
pinchStartPosition1 = GetChildControl(nameof(pinchStartPosition1));
pinchStartPosition2 = GetChildControl(nameof(pinchStartPosition2));
pinchGap = GetChildControl(nameof(pinchGap));
pinchGapDelta = GetChildControl(nameof(pinchGapDelta));
twistStartPosition1 = GetChildControl(nameof(twistStartPosition1));
twistStartPosition2 = GetChildControl(nameof(twistStartPosition2));
twistDeltaRotation = GetChildControl(nameof(twistDeltaRotation));
twoFingerDragStartPosition1 = GetChildControl(nameof(twoFingerDragStartPosition1));
twoFingerDragStartPosition2 = GetChildControl(nameof(twoFingerDragStartPosition2));
twoFingerDragCurrentPosition = GetChildControl(nameof(twoFingerDragCurrentPosition));
twoFingerDragDelta = GetChildControl(nameof(twoFingerDragDelta));
fingerCount = GetChildControl(nameof(fingerCount));
tapGestureRecognizer = new TapGestureRecognizer();
tapGestureRecognizer.onGestureStarted += OnGestureStarted;
dragGestureRecognizer = new DragGestureRecognizer();
dragGestureRecognizer.onGestureStarted += OnGestureStarted;
pinchGestureRecognizer = new PinchGestureRecognizer();
pinchGestureRecognizer.onGestureStarted += OnGestureStarted;
twistGestureRecognizer = new TwistGestureRecognizer();
twistGestureRecognizer.onGestureStarted += OnGestureStarted;
twoFingerDragGestureRecognizer = new TwoFingerDragGestureRecognizer();
twoFingerDragGestureRecognizer.onGestureStarted += OnGestureStarted;
}
///
protected override void OnAdded()
{
EnhancedTouchSupport.Enable();
}
///
protected override void OnRemoved()
{
EnhancedTouchSupport.Disable();
}
///
public void OnUpdate()
{
tapGestureRecognizer.Update();
dragGestureRecognizer.Update();
pinchGestureRecognizer.Update();
twistGestureRecognizer.Update();
twoFingerDragGestureRecognizer.Update();
var updatedTouchCount = GestureTouchesUtility.touches.Count;
if (m_ControllerState.fingerCount != updatedTouchCount)
{
m_ControllerState.fingerCount = updatedTouchCount;
InputSystem.InputSystem.QueueStateEvent(this, m_ControllerState);
}
}
void OnGestureStarted(Gesture gesture) where T : Gesture
{
gesture.onUpdated += OnGestureUpdated;
gesture.onFinished += OnGestureFinished;
switch (gesture)
{
case TapGesture tapGesture:
m_ControllerState.tapStartPosition = Vector2.zero;
break;
}
InputSystem.InputSystem.QueueStateEvent(this, m_ControllerState);
}
void OnGestureUpdated(Gesture gesture) where T : Gesture
{
switch (gesture)
{
case TapGesture tapGesture:
// Don't set the tapStartPosition since it should only be set when the gesture is successfully finished.
// We don't have another control to indicate tap status, so we have to use the position control
// for both status and position, so we must wait to set until the gesture is finished.
break;
case DragGesture dragGesture:
m_ControllerState.dragStartPosition = dragGesture.startPosition;
m_ControllerState.dragCurrentPosition = dragGesture.position;
m_ControllerState.dragDelta = dragGesture.delta;
break;
case PinchGesture pinchGesture:
m_ControllerState.pinchStartPosition1 = pinchGesture.startPosition1;
m_ControllerState.pinchStartPosition2 = pinchGesture.startPosition2;
m_ControllerState.pinchGap = pinchGesture.gap;
m_ControllerState.pinchGapDelta = pinchGesture.gapDelta;
break;
case TwistGesture twistGesture:
m_ControllerState.twistStartPosition1 = twistGesture.startPosition1;
m_ControllerState.twistStartPosition2 = twistGesture.startPosition2;
m_ControllerState.twistDeltaRotation = twistGesture.deltaRotation;
break;
case TwoFingerDragGesture twoFingerDragGesture:
m_ControllerState.twoFingerDragStartPosition1 = twoFingerDragGesture.startPosition1;
m_ControllerState.twoFingerDragStartPosition2 = twoFingerDragGesture.startPosition2;
m_ControllerState.twoFingerDragCurrentPosition = twoFingerDragGesture.position;
m_ControllerState.twoFingerDragDelta = twoFingerDragGesture.delta;
break;
}
InputSystem.InputSystem.QueueStateEvent(this, m_ControllerState);
}
void OnGestureFinished(Gesture gesture) where T : Gesture
{
switch (gesture)
{
case TapGesture tapGesture:
m_ControllerState.tapStartPosition = !tapGesture.isCanceled ? tapGesture.startPosition : Vector2.zero;
break;
case DragGesture dragGesture:
m_ControllerState.dragStartPosition = Vector2.zero;
m_ControllerState.dragCurrentPosition = Vector2.zero;
m_ControllerState.dragDelta = Vector2.zero;
break;
case PinchGesture pinchGesture:
m_ControllerState.pinchStartPosition1 = Vector2.zero;
m_ControllerState.pinchStartPosition2 = Vector2.zero;
m_ControllerState.pinchGap = 0f;
m_ControllerState.pinchGapDelta = 0f;
break;
case TwistGesture twistGesture:
m_ControllerState.twistStartPosition1 = Vector2.zero;
m_ControllerState.twistStartPosition2 = Vector2.zero;
m_ControllerState.twistDeltaRotation = 0f;
break;
case TwoFingerDragGesture twoFingerDragGesture:
m_ControllerState.twoFingerDragStartPosition1 = Vector2.zero;
m_ControllerState.twoFingerDragStartPosition2 = Vector2.zero;
m_ControllerState.twoFingerDragCurrentPosition = Vector2.zero;
m_ControllerState.twoFingerDragDelta = Vector2.zero;
break;
}
InputSystem.InputSystem.QueueStateEvent(this, m_ControllerState);
}
///
/// Converts state data to a string.
///
/// Returns a string representation.
public override string ToString()
{
var stringBuilder = new StringBuilder();
stringBuilder.Append($"tapStartPosition: {tapStartPosition.value}, dragStartPosition: {dragStartPosition.value}, dragCurrentPosition: {dragCurrentPosition.value}, dragDelta: {dragDelta.value}, ");
stringBuilder.Append($"pinchStartPosition1: {pinchStartPosition1.value}, pinchStartPosition2: {pinchStartPosition2.value}, pinchGap: {pinchGap.value}, pinchGapDelta: {pinchGapDelta.value}, ");
stringBuilder.Append($"twistStartPosition1: {twistStartPosition1.value}, twistStartPosition2: {twistStartPosition2.value}, twistDeltaRotation: {twistDeltaRotation.value}, ");
stringBuilder.Append($"twoFingerDragStartPosition1: {twoFingerDragStartPosition1.value}, twoFingerDragStartPosition2: {twoFingerDragStartPosition2.value}, twoFingerDragCurrentPosition: {twoFingerDragCurrentPosition.value}, twoFingerDragDelta: {twoFingerDragDelta.value}");
return stringBuilder.ToString();
}
}
}
#endif