170 lines
4.8 KiB
C#
170 lines
4.8 KiB
C#
#if INPUTSYSTEM_SUPPORT && UX_NAVIGATION
|
|
using System;
|
|
using UnityEngine.InputSystem;
|
|
using UnityEngine.InputSystem.Controls;
|
|
|
|
namespace UnityEngine.UI
|
|
{
|
|
internal sealed class UXInputModeService : MonoBehaviour
|
|
{
|
|
private static UXInputModeService _instance;
|
|
|
|
private InputAction _pointerAction;
|
|
private InputAction _gamepadAction;
|
|
|
|
public static UXInputMode CurrentMode { get; private set; } = UXInputMode.Pointer;
|
|
|
|
public static event Action<UXInputMode> OnModeChanged;
|
|
|
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
|
|
private static void Bootstrap()
|
|
{
|
|
EnsureInstance();
|
|
}
|
|
|
|
internal static UXInputModeService EnsureInstance()
|
|
{
|
|
if (_instance != null)
|
|
{
|
|
return _instance;
|
|
}
|
|
|
|
var go = new GameObject("[UXInputModeService]");
|
|
go.hideFlags = HideFlags.HideAndDontSave;
|
|
DontDestroyOnLoad(go);
|
|
_instance = go.AddComponent<UXInputModeService>();
|
|
return _instance;
|
|
}
|
|
|
|
private void Awake()
|
|
{
|
|
if (_instance != null && _instance != this)
|
|
{
|
|
Destroy(gameObject);
|
|
return;
|
|
}
|
|
|
|
_instance = this;
|
|
DontDestroyOnLoad(gameObject);
|
|
hideFlags = HideFlags.HideAndDontSave;
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
CreateActions();
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
DisposeActions();
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
DisposeActions();
|
|
if (_instance == this)
|
|
{
|
|
_instance = null;
|
|
}
|
|
}
|
|
|
|
private void CreateActions()
|
|
{
|
|
if (_pointerAction != null || _gamepadAction != null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_pointerAction = new InputAction("UXPointerInput", InputActionType.PassThrough);
|
|
_pointerAction.AddBinding("<Keyboard>/anyKey");
|
|
_pointerAction.AddBinding("<Mouse>/delta");
|
|
_pointerAction.AddBinding("<Mouse>/scroll");
|
|
_pointerAction.AddBinding("<Mouse>/leftButton");
|
|
_pointerAction.AddBinding("<Mouse>/rightButton");
|
|
_pointerAction.AddBinding("<Mouse>/middleButton");
|
|
_pointerAction.performed += OnPointerInput;
|
|
_pointerAction.Enable();
|
|
|
|
_gamepadAction = new InputAction("UXGamepadInput", InputActionType.PassThrough);
|
|
_gamepadAction.AddBinding("<Gamepad>/*");
|
|
_gamepadAction.AddBinding("<Joystick>/*");
|
|
_gamepadAction.performed += OnGamepadInput;
|
|
_gamepadAction.Enable();
|
|
}
|
|
|
|
private void DisposeActions()
|
|
{
|
|
if (_pointerAction != null)
|
|
{
|
|
_pointerAction.performed -= OnPointerInput;
|
|
_pointerAction.Disable();
|
|
_pointerAction.Dispose();
|
|
_pointerAction = null;
|
|
}
|
|
|
|
if (_gamepadAction != null)
|
|
{
|
|
_gamepadAction.performed -= OnGamepadInput;
|
|
_gamepadAction.Disable();
|
|
_gamepadAction.Dispose();
|
|
_gamepadAction = null;
|
|
}
|
|
}
|
|
|
|
private static void OnPointerInput(InputAction.CallbackContext context)
|
|
{
|
|
if (!IsInputMeaningful(context.control))
|
|
{
|
|
return;
|
|
}
|
|
|
|
SetMode(UXInputMode.Pointer);
|
|
}
|
|
|
|
private static void OnGamepadInput(InputAction.CallbackContext context)
|
|
{
|
|
if (!IsInputMeaningful(context.control))
|
|
{
|
|
return;
|
|
}
|
|
|
|
SetMode(UXInputMode.Gamepad);
|
|
}
|
|
|
|
private static bool IsInputMeaningful(InputControl control)
|
|
{
|
|
if (control == null || control.device == null || control.synthetic)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
switch (control)
|
|
{
|
|
case ButtonControl button:
|
|
return button.IsPressed();
|
|
case StickControl stick:
|
|
return stick.ReadValue().sqrMagnitude >= 0.04f;
|
|
case Vector2Control vector2:
|
|
return vector2.ReadValue().sqrMagnitude >= 0.04f;
|
|
case AxisControl axis:
|
|
return Mathf.Abs(axis.ReadValue()) >= 0.2f;
|
|
default:
|
|
return !control.noisy;
|
|
}
|
|
}
|
|
|
|
internal static void SetMode(UXInputMode mode)
|
|
{
|
|
EnsureInstance();
|
|
if (CurrentMode == mode)
|
|
{
|
|
return;
|
|
}
|
|
|
|
CurrentMode = mode;
|
|
OnModeChanged?.Invoke(mode);
|
|
}
|
|
}
|
|
}
|
|
#endif
|