// Touchpad Control|Locomotion|20070
namespace VRTK
{
using UnityEngine;
///
/// Provides the ability to control a GameObject's position based on the position of the controller touchpad axis.
///
///
/// > This script forms the stub of emitting the touchpad axis X and Y changes that are then digested by the corresponding Object Control Actions that are listening for the relevant event.
///
/// **Required Components:**
/// * `VRTK_ControllerEvents` - The Controller Events script to listen for the touchpad events on.
///
/// **Optional Components:**
/// * `VRTK_BodyPhysics` - The Body Physics script to utilise to determine if falling is occuring.
///
/// **Script Usage:**
/// * Place the `VRTK_TouchpadControl` script on either:
/// * The GameObject with the Controller Events script.
/// * Any other scene GameObject and provide a valid `VRTK_ControllerEvents` component to the `Controller` parameter of this script.
/// * Place a corresponding Object Control Action for the Touchpad Control script to notify of touchpad changes. Without a corresponding Object Control Action, the Touchpad Control script will do nothing.
///
///
/// `VRTK/Examples/017_CameraRig_TouchpadWalking` has a collection of walls and slopes that can be traversed by the user with the touchpad. There is also an area that can only be traversed if the user is crouching.
///
[AddComponentMenu("VRTK/Scripts/Locomotion/VRTK_TouchpadControl")]
public class VRTK_TouchpadControl : VRTK_ObjectControl
{
[Header("Touchpad Control Settings")]
[Tooltip("The axis to use for the direction coordinates.")]
public VRTK_ControllerEvents.Vector2AxisAlias coordinateAxis = VRTK_ControllerEvents.Vector2AxisAlias.Touchpad;
[Tooltip("An optional button that has to be engaged to allow the touchpad control to activate.")]
public VRTK_ControllerEvents.ButtonAlias primaryActivationButton = VRTK_ControllerEvents.ButtonAlias.TouchpadTouch;
[Tooltip("An optional button that when engaged will activate the modifier on the touchpad control action.")]
public VRTK_ControllerEvents.ButtonAlias actionModifierButton = VRTK_ControllerEvents.ButtonAlias.TouchpadPress;
[Tooltip("A deadzone threshold on the touchpad that will ignore input if the touch position is within the specified deadzone. Between `0f` and `1f`.")]
public Vector2 axisDeadzone = new Vector2(0.2f, 0.2f);
protected bool touchpadFirstChange;
protected bool otherTouchpadControlEnabledState;
protected bool otherTouchpadControlEnabledStateSet;
protected VRTK_ControllerEvents.ButtonAlias coordniateButtonAlias;
protected override void OnEnable()
{
base.OnEnable();
touchpadFirstChange = true;
otherTouchpadControlEnabledStateSet = false;
coordniateButtonAlias = (coordinateAxis == VRTK_ControllerEvents.Vector2AxisAlias.Touchpad ? VRTK_ControllerEvents.ButtonAlias.TouchpadTouch : VRTK_ControllerEvents.ButtonAlias.TouchpadTwoTouch);
}
protected override void ControlFixedUpdate()
{
ModifierButtonActive();
if (OutsideDeadzone(currentAxis.x, axisDeadzone.x) || currentAxis.x == 0f)
{
OnXAxisChanged(SetEventArguements(directionDevice.right, currentAxis.x, axisDeadzone.x));
}
if (OutsideDeadzone(currentAxis.y, axisDeadzone.y) || currentAxis.y == 0f)
{
OnYAxisChanged(SetEventArguements(directionDevice.forward, currentAxis.y, axisDeadzone.y));
}
}
protected override VRTK_ObjectControl GetOtherControl()
{
GameObject foundController = (VRTK_DeviceFinder.IsControllerLeftHand(gameObject) ? VRTK_DeviceFinder.GetControllerRightHand(false) : VRTK_DeviceFinder.GetControllerLeftHand(false));
if (foundController != null)
{
return foundController.GetComponentInChildren();
}
return null;
}
protected override void SetListeners(bool state)
{
if (controllerEvents != null)
{
if (state)
{
switch (coordinateAxis)
{
case VRTK_ControllerEvents.Vector2AxisAlias.Touchpad:
controllerEvents.TouchpadAxisChanged += TouchpadAxisChanged;
controllerEvents.TouchpadTouchEnd += TouchpadTouchEnd;
break;
case VRTK_ControllerEvents.Vector2AxisAlias.TouchpadTwo:
controllerEvents.TouchpadTwoAxisChanged += TouchpadAxisChanged;
controllerEvents.TouchpadTwoTouchEnd += TouchpadTouchEnd;
break;
}
}
else
{
switch (coordinateAxis)
{
case VRTK_ControllerEvents.Vector2AxisAlias.Touchpad:
controllerEvents.TouchpadAxisChanged -= TouchpadAxisChanged;
controllerEvents.TouchpadTouchEnd -= TouchpadTouchEnd;
break;
case VRTK_ControllerEvents.Vector2AxisAlias.TouchpadTwo:
controllerEvents.TouchpadTwoAxisChanged -= TouchpadAxisChanged;
controllerEvents.TouchpadTwoTouchEnd -= TouchpadTouchEnd;
break;
}
}
}
}
protected override bool IsInAction()
{
return (ValidPrimaryButton() && TouchpadTouched());
}
protected virtual bool OutsideDeadzone(float axisValue, float deadzoneThreshold)
{
return (axisValue > deadzoneThreshold || axisValue < -deadzoneThreshold);
}
protected virtual bool ValidPrimaryButton()
{
return (controllerEvents != null && (primaryActivationButton == VRTK_ControllerEvents.ButtonAlias.Undefined || controllerEvents.IsButtonPressed(primaryActivationButton)));
}
protected virtual void ModifierButtonActive()
{
modifierActive = (controllerEvents != null && actionModifierButton != VRTK_ControllerEvents.ButtonAlias.Undefined && controllerEvents.IsButtonPressed(actionModifierButton));
}
protected virtual bool TouchpadTouched()
{
return (controllerEvents != null && controllerEvents.IsButtonPressed(coordniateButtonAlias));
}
protected virtual void TouchpadAxisChanged(object sender, ControllerInteractionEventArgs e)
{
Vector2 actualAxis = (coordinateAxis == VRTK_ControllerEvents.Vector2AxisAlias.Touchpad ? e.touchpadAxis : e.touchpadTwoAxis);
if (touchpadFirstChange && otherObjectControl != null && disableOtherControlsOnActive && actualAxis != Vector2.zero)
{
otherTouchpadControlEnabledState = otherObjectControl.enabled;
otherTouchpadControlEnabledStateSet = true;
otherObjectControl.enabled = false;
}
currentAxis = (ValidPrimaryButton() ? actualAxis : Vector2.zero);
if (currentAxis != Vector2.zero)
{
touchpadFirstChange = false;
}
}
protected virtual void TouchpadTouchEnd(object sender, ControllerInteractionEventArgs e)
{
if (otherTouchpadControlEnabledStateSet && otherObjectControl != null && disableOtherControlsOnActive)
{
otherObjectControl.enabled = otherTouchpadControlEnabledState;
}
currentAxis = Vector2.zero;
touchpadFirstChange = true;
}
}
}