using System;
using System.Collections.Generic;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.XR.Interaction.Toolkit.Utilities.Pooling;
namespace UnityEngine.XR.Interaction.Toolkit.UI
{
///
/// Matches the UI Model to the state of the Interactor.
///
public interface IUIInteractor
{
///
/// Updates the current UI Model to match the state of the Interactor.
///
/// The returned model that will match this Interactor.
void UpdateUIModel(ref TrackedDeviceModel model);
///
/// Attempts to retrieve the current UI Model.
///
/// The returned model that reflects the UI state of this Interactor.
/// Returns if the model was retrieved. Otherwise, returns .
bool TryGetUIModel(out TrackedDeviceModel model);
}
///
/// Matches the UI Model to the state of the Interactor with support for hover events.
///
public interface IUIHoverInteractor : IUIInteractor
{
///
/// The event that is called when the Interactor begins hovering over a UI element.
///
///
/// The passed to each listener is only valid while the event is invoked,
/// do not hold a reference to it.
///
UIHoverEnterEvent uiHoverEntered { get; }
///
/// The event that is called when this Interactor ends hovering over a UI element.
///
///
/// The passed to each listener is only valid while the event is invoked,
/// do not hold a reference to it.
///
UIHoverExitEvent uiHoverExited { get; }
///
/// The calls this method when the Interactor begins hovering over a UI element.
///
/// Event data containing the UI element that is being hovered over.
///
/// is only valid during this method call, do not hold a reference to it.
///
///
void OnUIHoverEntered(UIHoverEventArgs args);
///
/// The calls this method when the Interactor ends hovering over a UI element.
///
/// Event data containing the UI element that is no longer hovered over.
///
/// is only valid during this method call, do not hold a reference to it.
///
///
void OnUIHoverExited(UIHoverEventArgs args);
}
///
/// Custom class for input modules that send UI input in XR.
///
[AddComponentMenu("Event/XR UI Input Module", 11)]
[HelpURL(XRHelpURLConstants.k_XRUIInputModule)]
public partial class XRUIInputModule : UIInputModule
{
struct RegisteredInteractor
{
public IUIInteractor interactor;
public TrackedDeviceModel model;
internal bool deactivating;
internal bool active;
public RegisteredInteractor(IUIInteractor interactor, int deviceIndex)
{
this.interactor = interactor;
model = new TrackedDeviceModel(deviceIndex)
{
interactor = interactor,
};
active = true;
deactivating = false;
}
}
struct RegisteredTouch
{
public bool isValid;
public int touchId;
public TouchModel model;
public RegisteredTouch(Touch touch, int deviceIndex)
{
touchId = touch.fingerId;
model = new TouchModel(deviceIndex);
isValid = true;
}
}
///
/// Represents which Active Input Mode will be used in the situation where the Active Input Handling project setting is set to Both.
///
///
public enum ActiveInputMode
{
///
/// Only use input polled through the built-in Unity Input Manager (Old).
///
InputManagerBindings,
///
/// Only use input polled from through the newer Input System package.
///
InputSystemActions,
///
/// Scan through input from both Unity Input Manager and Input System action references.
/// Note: This may cause undesired effects or may impact performance if input configuration is duplicated.
///
Both,
}
[HideInInspector]
[SerializeField]
ActiveInputMode m_ActiveInputMode;
///
/// Configures which Active Input Mode will be used in the situation where the Active Input Handling project setting is set to Both.
///
///
[Obsolete("activeInputMode has been deprecated in version 3.1.0. Input System Package (New) will be the default input handling mode used when active input handling is set to Both.")]
public ActiveInputMode activeInputMode
{
get => m_ActiveInputMode;
set => m_ActiveInputMode = value;
}
[Header("Input Devices")]
[SerializeField]
[Tooltip("If true, will forward 3D tracked device data to UI elements.")]
bool m_EnableXRInput = true;
///
/// If , will forward 3D tracked device data to UI elements.
///
public bool enableXRInput
{
get => m_EnableXRInput;
set => m_EnableXRInput = value;
}
[SerializeField]
[Tooltip("If true, will forward 2D mouse data to UI elements. Ignored when any Input System UI Actions are used.")]
bool m_EnableMouseInput = true;
///
/// If , will forward 2D mouse data to UI elements. Ignored when any Input System UI Actions are used.
///
public bool enableMouseInput
{
get => m_EnableMouseInput;
set => m_EnableMouseInput = value;
}
[SerializeField]
[Tooltip("If true, will forward 2D touch data to UI elements. Ignored when any Input System UI Actions are used.")]
bool m_EnableTouchInput = true;
///
/// If , will forward 2D touch data to UI elements. Ignored when any Input System UI Actions are used.
///
public bool enableTouchInput
{
get => m_EnableTouchInput;
set => m_EnableTouchInput = value;
}
[SerializeField]
[Tooltip("If true, will forward gamepad data to UI elements. Ignored when any Input System UI Actions are used.")]
bool m_EnableGamepadInput = true;
///
/// If , will forward gamepad data to UI elements. Ignored when any Input System UI Actions are used.
///
public bool enableGamepadInput
{
get => m_EnableGamepadInput;
set => m_EnableGamepadInput = value;
}
[SerializeField]
[Tooltip("If true, will forward joystick data to UI elements. Ignored when any Input System UI Actions are used.")]
bool m_EnableJoystickInput = true;
///
/// If , will forward joystick data to UI elements. Ignored when any Input System UI Actions are used.
///
public bool enableJoystickInput
{
get => m_EnableJoystickInput;
set => m_EnableJoystickInput = value;
}
#if ENABLE_INPUT_SYSTEM
[Header("Input System UI Actions")]
#else
[HideInInspector]
#endif
[SerializeField]
[Tooltip("Pointer input action reference, such as a mouse or single-finger touch device.")]
InputActionReference m_PointAction;
///
/// The Input System action to use to move the pointer on the currently active UI. Must be a Control.
///
public InputActionReference pointAction
{
get => m_PointAction;
set => SetInputAction(ref m_PointAction, value);
}
#if !ENABLE_INPUT_SYSTEM
[HideInInspector]
#endif
[SerializeField]
[Tooltip("Left-click input action reference, typically the left button on a mouse.")]
InputActionReference m_LeftClickAction;
///
/// The Input System action to use to determine whether the left button of a pointer is pressed. Must be a Control.
///
public InputActionReference leftClickAction
{
get => m_LeftClickAction;
set => SetInputAction(ref m_LeftClickAction, value);
}
#if !ENABLE_INPUT_SYSTEM
[HideInInspector]
#endif
[SerializeField]
[Tooltip("Middle-click input action reference, typically the middle button on a mouse.")]
InputActionReference m_MiddleClickAction;
///
/// The Input System action to use to determine whether the middle button of a pointer is pressed. Must be a Control.
///
public InputActionReference middleClickAction
{
get => m_MiddleClickAction;
set => SetInputAction(ref m_MiddleClickAction, value);
}
#if !ENABLE_INPUT_SYSTEM
[HideInInspector]
#endif
[SerializeField]
[Tooltip("Right-click input action reference, typically the right button on a mouse.")]
InputActionReference m_RightClickAction;
///
/// The Input System action to use to determine whether the right button of a pointer is pressed. Must be a Control.
///
public InputActionReference rightClickAction
{
get => m_RightClickAction;
set => SetInputAction(ref m_RightClickAction, value);
}
#if !ENABLE_INPUT_SYSTEM
[HideInInspector]
#endif
[SerializeField]
[Tooltip("Scroll wheel input action reference, typically the scroll wheel on a mouse.")]
InputActionReference m_ScrollWheelAction;
///
/// The Input System action to use to move the pointer on the currently active UI. Must be a Control.
///
public InputActionReference scrollWheelAction
{
get => m_ScrollWheelAction;
set => SetInputAction(ref m_ScrollWheelAction, value);
}
#if !ENABLE_INPUT_SYSTEM
[HideInInspector]
#endif
[SerializeField]
[Tooltip("Navigation input action reference will change which UI element is currently selected to the one up, down, left of or right of the currently selected one.")]
InputActionReference m_NavigateAction;
///
/// The Input System action to use to navigate the currently active UI. Must be a Control.
///
public InputActionReference navigateAction
{
get => m_NavigateAction;
set => SetInputAction(ref m_NavigateAction, value);
}
#if !ENABLE_INPUT_SYSTEM
[HideInInspector]
#endif
[SerializeField]
[Tooltip("Submit input action reference will trigger a submission of the currently selected UI in the Event System.")]
InputActionReference m_SubmitAction;
///
/// The Input System action to use for submitting or activating a UI element. Must be a Control.
///
public InputActionReference submitAction
{
get => m_SubmitAction;
set => SetInputAction(ref m_SubmitAction, value);
}
#if !ENABLE_INPUT_SYSTEM
[HideInInspector]
#endif
[SerializeField]
[Tooltip("Cancel input action reference will trigger canceling out of the currently selected UI in the Event System.")]
InputActionReference m_CancelAction;
///
/// The Input System action to use for cancelling or backing out of a UI element. Must be a Control.
///
public InputActionReference cancelAction
{
get => m_CancelAction;
set => SetInputAction(ref m_CancelAction, value);
}
#if !ENABLE_INPUT_SYSTEM
[HideInInspector]
#endif
[SerializeField]
[Tooltip("When enabled, built-in Input System actions will be used if no Input System UI Actions are assigned.")]
bool m_EnableBuiltinActionsAsFallback = true;
///
/// When enabled, built-in Input System actions will be used if no Input System UI Actions are assigned. This uses the
/// currently enabled Input System devices: , , , and .
///
public bool enableBuiltinActionsAsFallback
{
get => m_EnableBuiltinActionsAsFallback;
set
{
m_EnableBuiltinActionsAsFallback = value;
m_UseBuiltInInputSystemActions = m_EnableBuiltinActionsAsFallback && !InputActionReferencesAreSet();
}
}
#if !ENABLE_LEGACY_INPUT_MANAGER || ENABLE_INPUT_SYSTEM
[HideInInspector]
#else
[Header("Input Manager (Old) Gamepad/Joystick Bindings")]
#endif
[SerializeField]
[Tooltip("Name of the horizontal axis for gamepad/joystick UI navigation when using the old Input Manager.")]
string m_HorizontalAxis = "Horizontal";
///
/// Name of the horizontal axis for UI navigation when using the old Input Manager.
///
public string horizontalAxis
{
get => m_HorizontalAxis;
set => m_HorizontalAxis = value;
}
#if !ENABLE_LEGACY_INPUT_MANAGER || ENABLE_INPUT_SYSTEM
[HideInInspector]
#endif
[SerializeField]
[Tooltip("Name of the vertical axis for gamepad/joystick UI navigation when using the old Input Manager.")]
string m_VerticalAxis = "Vertical";
///
/// Name of the vertical axis for UI navigation when using the old Input Manager.
///
public string verticalAxis
{
get => m_VerticalAxis;
set => m_VerticalAxis = value;
}
#if !ENABLE_LEGACY_INPUT_MANAGER || ENABLE_INPUT_SYSTEM
[HideInInspector]
#endif
[SerializeField]
[Tooltip("Name of the gamepad/joystick button to use for UI selection or submission when using the old Input Manager.")]
string m_SubmitButton = "Submit";
///
/// Name of the gamepad/joystick button to use for UI selection or submission when using the old Input Manager.
///
public string submitButton
{
get => m_SubmitButton;
set => m_SubmitButton = value;
}
#if !ENABLE_LEGACY_INPUT_MANAGER || ENABLE_INPUT_SYSTEM
[HideInInspector]
#endif
[SerializeField]
[Tooltip("Name of the gamepad/joystick button to use for UI cancel or back commands when using the old Input Manager.")]
string m_CancelButton = "Cancel";
///
/// Name of the gamepad/joystick button to use for UI cancel or back commands when using the old Input Manager.
///
public string cancelButton
{
get => m_CancelButton;
set => m_CancelButton = value;
}
// Initialize to 1 so mouse always uses pointer ID of 0
int m_RollingPointerId = 1;
Stack m_DeletedPointerIds = new Stack();
bool m_UseBuiltInInputSystemActions;
PointerModel m_PointerState;
NavigationModel m_NavigationState;
internal const float kPixelPerLine = 20f;
readonly List m_RegisteredTouches = new List();
readonly List m_RegisteredInteractors = new List();
// Reusable event args
readonly LinkedPool m_UIHoverEventArgs = new LinkedPool(() => new UIHoverEventArgs(), collectionCheck: false);
///
/// See MonoBehavior.OnEnable.
///
protected override void OnEnable()
{
base.OnEnable();
// Check active input mode is correct
#if ENABLE_LEGACY_INPUT_MANAGER && !ENABLE_INPUT_SYSTEM
m_ActiveInputMode = ActiveInputMode.InputManagerBindings;
#else
m_ActiveInputMode = ActiveInputMode.InputSystemActions;
#endif
m_PointerState = new PointerModel(0);
m_NavigationState = new NavigationModel();
m_UseBuiltInInputSystemActions = m_EnableBuiltinActionsAsFallback && !InputActionReferencesAreSet();
if (m_ActiveInputMode != ActiveInputMode.InputManagerBindings)
EnableAllActions();
}
///
/// See MonoBehavior.OnDisable.
///
protected override void OnDisable()
{
RemovePointerEventData(m_PointerState.pointerId);
if (m_ActiveInputMode != ActiveInputMode.InputManagerBindings)
DisableAllActions();
base.OnDisable();
}
///
/// Register an with the UI system.
/// Calling this will enable it to start interacting with UI.
///
/// The to use.
public void RegisterInteractor(IUIInteractor interactor)
{
if (interactor == null)
return;
for (var i = 0; i < m_RegisteredInteractors.Count; i++)
{
var registeredInteractor = m_RegisteredInteractors[i];
if (registeredInteractor.interactor == interactor)
{
// If it was previously disabled by deactivation, reactivate
if (!registeredInteractor.active)
{
registeredInteractor.active = true;
registeredInteractor.deactivating = false;
registeredInteractor.model.Reset(true);
m_RegisteredInteractors[i] = registeredInteractor;
}
return;
}
}
if (!m_DeletedPointerIds.TryPop(out var newId))
newId = m_RollingPointerId++;
m_RegisteredInteractors.Add(new RegisteredInteractor(interactor, newId));
}
///
/// Unregisters an with the UI system.
/// This cancels all UI Interaction and makes the no longer able to affect UI.
///
/// The to stop using.
public void UnregisterInteractor(IUIInteractor interactor)
{
if (interactor == null)
return;
for (var i = 0; i < m_RegisteredInteractors.Count; i++)
{
var registeredInteractor = m_RegisteredInteractors[i];
if (registeredInteractor.interactor == interactor)
{
if (registeredInteractor.active)
{
registeredInteractor.deactivating = true;
registeredInteractor.active = false;
m_RegisteredInteractors[i] = registeredInteractor;
}
return;
}
}
}
///
/// Gets an from its corresponding Unity UI Pointer Id.
/// This can be used to identify individual Interactors from the underlying UI Events.
///
/// A unique integer representing an object that can point at UI.
/// Returns the interactor associated with .
/// Returns if no Interactor is associated (e.g. if it's a mouse event).
public IUIInteractor GetInteractor(int pointerId)
{
for (var i = 0; i < m_RegisteredInteractors.Count; i++)
{
if (m_RegisteredInteractors[i].model.pointerId == pointerId && m_RegisteredInteractors[i].active)
{
return m_RegisteredInteractors[i].interactor;
}
}
return null;
}
/// Retrieves the UI Model for a selected .
/// The you want the model for.
/// The returned model that reflects the UI state of the .
/// Returns if the model was retrieved. Otherwise, returns .
public bool GetTrackedDeviceModel(IUIInteractor interactor, out TrackedDeviceModel model)
{
for (var i = 0; i < m_RegisteredInteractors.Count; i++)
{
if (m_RegisteredInteractors[i].interactor == interactor)
{
model = m_RegisteredInteractors[i].model;
return true;
}
}
model = new TrackedDeviceModel(-1);
return false;
}
///
protected override void DoProcess()
{
if (m_EnableXRInput)
{
for (var i = 0; i < m_RegisteredInteractors.Count; i++)
{
var registeredInteractor = m_RegisteredInteractors[i];
var oldTarget = registeredInteractor.model.implementationData.pointerTarget;
// If device is removed, we send a default state to unclick any UI
var isDestroyedUnityObject = registeredInteractor.interactor is Object unityObject && unityObject == null;
if (isDestroyedUnityObject || registeredInteractor.deactivating)
{
registeredInteractor.model.Reset(false);
ProcessTrackedDevice(ref registeredInteractor.model, true);
RemovePointerEventData(registeredInteractor.model.pointerId);
if (isDestroyedUnityObject)
{
m_DeletedPointerIds.Push(registeredInteractor.model.pointerId);
m_RegisteredInteractors.RemoveAt(i--);
continue;
}
else
{
registeredInteractor.deactivating = false;
registeredInteractor.model.Reset(true);
m_RegisteredInteractors[i] = registeredInteractor;
}
}
else if (!registeredInteractor.active)
{
continue;
}
else
{
registeredInteractor.interactor.UpdateUIModel(ref registeredInteractor.model);
ProcessTrackedDevice(ref registeredInteractor.model);
// Some poke logic happens during the Raycast call in ProcessTrackedDevice
// and requires an additional update to the select field of the UI Model
registeredInteractor.model.UpdatePokeSelectState();
m_RegisteredInteractors[i] = registeredInteractor;
}
// If hover target changed, send event
var newTarget = registeredInteractor.model.implementationData.pointerTarget;
if (oldTarget != newTarget)
{
using (m_UIHoverEventArgs.Get(out var args))
{
args.interactorObject = registeredInteractor.interactor;
args.deviceModel = registeredInteractor.model;
if (args.interactorObject != null && args.interactorObject is IUIHoverInteractor hoverInteractor)
{
if (oldTarget != null)
{
args.uiObject = oldTarget;
hoverInteractor.OnUIHoverExited(args);
}
if (newTarget != null && newTarget.activeInHierarchy)
{
args.uiObject = newTarget;
hoverInteractor.OnUIHoverEntered(args);
}
}
}
}
// In the case where the target is disabled while being hovered, this
// will fire the appropriate event to any listeners as well as reset the
// current model to prevent stale data from causing unwanted behavior
if ((oldTarget != null && !oldTarget.activeInHierarchy) || (oldTarget is not null && oldTarget == null))
{
using (m_UIHoverEventArgs.Get(out var args))
{
if (oldTarget == newTarget)
{
registeredInteractor.model.Reset(true);
m_RegisteredInteractors[i] = registeredInteractor;
}
var interactor = registeredInteractor.interactor;
if (interactor != null && interactor is IUIHoverInteractor hoverInteractor)
{
args.interactorObject = interactor;
args.uiObject = oldTarget;
args.deviceModel = registeredInteractor.model;
hoverInteractor.OnUIHoverExited(args);
}
}
}
}
}
#if ENABLE_LEGACY_INPUT_MANAGER && !ENABLE_INPUT_SYSTEM
// Touch needs to take precedence because of the mouse emulation layer
if (m_ActiveInputMode != ActiveInputMode.InputSystemActions)
{
var hasTouches = false;
if (m_EnableTouchInput)
hasTouches = ProcessLegacyTouches();
if (m_EnableMouseInput && !hasTouches)
GetLegacyMouseState();
GetLegacyNavigationState();
}
#endif
if (m_ActiveInputMode != ActiveInputMode.InputManagerBindings)
GetPointerStates();
ProcessPointerState(ref m_PointerState);
ProcessNavigationState(ref m_NavigationState);
}
void GetPointerStates()
{
if (m_UseBuiltInInputSystemActions)
{
if (m_EnableTouchInput && Touchscreen.current != null)
{
m_PointerState.position = Touchscreen.current.position.ReadValue();
#if UNITY_2022_3_OR_NEWER
m_PointerState.displayIndex = Touchscreen.current.displayIndex.ReadValue();
#endif
}
if (m_EnableMouseInput && Mouse.current != null)
{
m_PointerState.position = Mouse.current.position.ReadValue();
#if UNITY_2022_3_OR_NEWER
m_PointerState.displayIndex = Mouse.current.displayIndex.ReadValue();
#endif
m_PointerState.scrollDelta = Mouse.current.scroll.ReadValue() * (1 / kPixelPerLine);
m_PointerState.leftButtonPressed = Mouse.current.leftButton.isPressed;
m_PointerState.rightButtonPressed = Mouse.current.rightButton.isPressed;
m_PointerState.middleButtonPressed = Mouse.current.middleButton.isPressed;
}
if (m_EnableGamepadInput && Gamepad.current != null)
{
// Combine left stick and dpad for navigation movement
m_NavigationState.move = Gamepad.current.leftStick.ReadValue() + Gamepad.current.dpad.ReadValue();
m_NavigationState.submitButtonDown = Gamepad.current.buttonSouth.isPressed;
m_NavigationState.cancelButtonDown = Gamepad.current.buttonEast.isPressed;
}
if (m_EnableJoystickInput && Joystick.current != null)
{
// Combine main joystick and hatswitch for navigation movement
m_NavigationState.move = Joystick.current.stick.ReadValue() +
(Joystick.current.hatswitch != null ? Joystick.current.hatswitch.ReadValue() : Vector2.zero);
m_NavigationState.submitButtonDown = Joystick.current.trigger.isPressed;
// This will always be false until we can rely on a secondary button from the joystick
m_NavigationState.cancelButtonDown = false;
}
}
else
{
if (IsActionEnabled(m_PointAction))
{
m_PointerState.position = m_PointAction.action.ReadValue();
#if UNITY_2022_3_OR_NEWER
m_PointerState.displayIndex = GetDisplayIndexFor(m_PointAction.action.activeControl);
#endif
}
if (IsActionEnabled(m_ScrollWheelAction))
m_PointerState.scrollDelta = m_ScrollWheelAction.action.ReadValue() * (1 / kPixelPerLine);
if (IsActionEnabled(m_LeftClickAction))
m_PointerState.leftButtonPressed = m_LeftClickAction.action.IsPressed();
if (IsActionEnabled(m_RightClickAction))
m_PointerState.rightButtonPressed = m_RightClickAction.action.IsPressed();
if (IsActionEnabled(m_MiddleClickAction))
m_PointerState.middleButtonPressed = m_MiddleClickAction.action.IsPressed();
if (IsActionEnabled(m_NavigateAction))
m_NavigationState.move = m_NavigateAction.action.ReadValue();
if (IsActionEnabled(m_SubmitAction))
m_NavigationState.submitButtonDown = m_SubmitAction.action.WasPerformedThisFrame();
if (IsActionEnabled(m_CancelAction))
m_NavigationState.cancelButtonDown = m_CancelAction.action.WasPerformedThisFrame();
}
}
#if ENABLE_LEGACY_INPUT_MANAGER && !ENABLE_INPUT_SYSTEM
void GetLegacyMouseState()
{
if (Input.mousePresent)
{
m_PointerState.position = Input.mousePosition;
m_PointerState.scrollDelta = Input.mouseScrollDelta;
m_PointerState.leftButtonPressed = Input.GetMouseButton(0);
m_PointerState.rightButtonPressed = Input.GetMouseButton(1);
m_PointerState.middleButtonPressed = Input.GetMouseButton(2);
}
}
bool ProcessLegacyTouches()
{
var hasTouches = Input.touchCount > 0;
if (!hasTouches)
return false;
var touchCount = Input.touchCount;
for (var touchIndex = 0; touchIndex < touchCount; ++touchIndex)
{
var touch = Input.GetTouch(touchIndex);
var registeredTouchIndex = -1;
// Find if touch already exists
for (var j = 0; j < m_RegisteredTouches.Count; j++)
{
if (touch.fingerId == m_RegisteredTouches[j].touchId)
{
registeredTouchIndex = j;
break;
}
}
if (registeredTouchIndex < 0)
{
// Not found, search empty pool
for (var j = 0; j < m_RegisteredTouches.Count; j++)
{
if (!m_RegisteredTouches[j].isValid)
{
// Re-use the Id
var pointerId = m_RegisteredTouches[j].model.pointerId;
m_RegisteredTouches[j] = new RegisteredTouch(touch, pointerId);
registeredTouchIndex = j;
break;
}
}
if (registeredTouchIndex < 0)
{
// No Empty slots, add one
registeredTouchIndex = m_RegisteredTouches.Count;
if (!m_DeletedPointerIds.TryPop(out var newId))
newId = m_RollingPointerId++;
m_RegisteredTouches.Add(new RegisteredTouch(touch, newId));
}
}
var registeredTouch = m_RegisteredTouches[registeredTouchIndex];
registeredTouch.model.selectPhase = touch.phase;
registeredTouch.model.position = touch.position;
m_RegisteredTouches[registeredTouchIndex] = registeredTouch;
}
for (var i = 0; i < m_RegisteredTouches.Count; i++)
{
var registeredTouch = m_RegisteredTouches[i];
ProcessTouch(ref registeredTouch.model);
if (registeredTouch.model.selectPhase == TouchPhase.Ended || registeredTouch.model.selectPhase == TouchPhase.Canceled)
registeredTouch.isValid = false;
m_RegisteredTouches[i] = registeredTouch;
}
return true;
}
void GetLegacyNavigationState()
{
if ((m_EnableGamepadInput || m_EnableJoystickInput) && Input.GetJoystickNames().Length > 0)
{
m_NavigationState.move = new Vector2(Input.GetAxis(m_HorizontalAxis), Input.GetAxis(m_VerticalAxis));
m_NavigationState.submitButtonDown = Input.GetButton(m_SubmitButton);
m_NavigationState.cancelButtonDown = Input.GetButton(m_CancelButton);
}
}
#endif
bool InputActionReferencesAreSet()
{
return (m_PointAction != null ||
m_LeftClickAction != null ||
m_RightClickAction != null ||
m_MiddleClickAction != null ||
m_NavigateAction != null ||
m_SubmitAction != null ||
m_CancelAction != null ||
m_ScrollWheelAction != null);
}
void EnableAllActions()
{
EnableInputAction(m_PointAction);
EnableInputAction(m_LeftClickAction);
EnableInputAction(m_RightClickAction);
EnableInputAction(m_MiddleClickAction);
EnableInputAction(m_NavigateAction);
EnableInputAction(m_SubmitAction);
EnableInputAction(m_CancelAction);
EnableInputAction(m_ScrollWheelAction);
}
void DisableAllActions()
{
DisableInputAction(m_PointAction);
DisableInputAction(m_LeftClickAction);
DisableInputAction(m_RightClickAction);
DisableInputAction(m_MiddleClickAction);
DisableInputAction(m_NavigateAction);
DisableInputAction(m_SubmitAction);
DisableInputAction(m_CancelAction);
DisableInputAction(m_ScrollWheelAction);
}
static bool IsActionEnabled(InputActionReference inputAction)
{
return inputAction != null && inputAction.action != null && inputAction.action.enabled;
}
static void EnableInputAction(InputActionReference inputAction)
{
if (inputAction == null || inputAction.action == null)
return;
inputAction.action.Enable();
}
static void DisableInputAction(InputActionReference inputAction)
{
if (inputAction == null || inputAction.action == null)
return;
inputAction.action.Disable();
}
void SetInputAction(ref InputActionReference inputAction, InputActionReference value)
{
if (Application.isPlaying && inputAction != null)
inputAction.action?.Disable();
inputAction = value;
if (Application.isPlaying && isActiveAndEnabled && inputAction != null)
inputAction.action?.Enable();
}
#if UNITY_2022_3_OR_NEWER
int GetDisplayIndexFor(InputControl control)
{
var displayIndex = 0;
if (control != null && control.device is Pointer pointerCast && pointerCast != null)
{
displayIndex = pointerCast.displayIndex.ReadValue();
Debug.Assert(displayIndex <= byte.MaxValue, "Display index was larger than expected", this);
}
return displayIndex;
}
#endif
}
}