修改临时
This commit is contained in:
parent
74aa459a38
commit
99446198cf
3
Runtime/Input.meta
Normal file
3
Runtime/Input.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f9ad1ce05574ba886146f9982e01142
|
||||
timeCreated: 1764839428
|
||||
224
Runtime/Input/InputDeviceWatcher.cs
Normal file
224
Runtime/Input/InputDeviceWatcher.cs
Normal file
@ -0,0 +1,224 @@
|
||||
#if INPUTSYSTEM_SUPPORT
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
public static class InputDeviceWatcher
|
||||
{
|
||||
public enum InputDeviceCategory
|
||||
{
|
||||
Keyboard,
|
||||
Xbox,
|
||||
PlayStation,
|
||||
Other
|
||||
}
|
||||
|
||||
static readonly float DebounceWindow = 1f;
|
||||
public static InputDeviceCategory CurrentCategory = InputDeviceCategory.Keyboard;
|
||||
public static string CurrentDeviceName = "";
|
||||
|
||||
private static InputAction _anyInputAction;
|
||||
private static int _lastDeviceId = -1;
|
||||
private static float _lastInputTime = -Mathf.Infinity;
|
||||
|
||||
|
||||
public static event Action<InputDeviceCategory> OnDeviceChanged;
|
||||
|
||||
private static bool initialized = false;
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
public static void Initialize()
|
||||
{
|
||||
if (initialized) return;
|
||||
initialized = true;
|
||||
|
||||
CurrentCategory = InputDeviceCategory.Keyboard;
|
||||
CurrentDeviceName = "";
|
||||
|
||||
_anyInputAction = new InputAction("AnyDevice", InputActionType.PassThrough);
|
||||
_anyInputAction.AddBinding("<Keyboard>/anyKey");
|
||||
_anyInputAction.AddBinding("<Mouse>/*");
|
||||
_anyInputAction.AddBinding("<Gamepad>/*");
|
||||
_anyInputAction.AddBinding("<Joystick>/*");
|
||||
|
||||
_anyInputAction.performed += OnAnyInputPerformed;
|
||||
_anyInputAction.Enable();
|
||||
|
||||
InputSystem.onDeviceChange += OnDeviceChange;
|
||||
#if UNITY_EDITOR
|
||||
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
static void OnPlayModeStateChanged(PlayModeStateChange state)
|
||||
{
|
||||
if (state == PlayModeStateChange.ExitingPlayMode)
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
|
||||
}
|
||||
#endif
|
||||
|
||||
public static void Dispose()
|
||||
{
|
||||
if (!initialized) return;
|
||||
CurrentCategory = InputDeviceCategory.Keyboard;
|
||||
_anyInputAction.performed -= OnAnyInputPerformed;
|
||||
_anyInputAction.Disable();
|
||||
_anyInputAction.Dispose();
|
||||
|
||||
InputSystem.onDeviceChange -= OnDeviceChange;
|
||||
|
||||
OnDeviceChanged = null;
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
// ------------------ 监听输入 --------------------
|
||||
private static void OnAnyInputPerformed(InputAction.CallbackContext ctx)
|
||||
{
|
||||
if (ctx.control == null || ctx.control.device == null) return;
|
||||
|
||||
var device = ctx.control.device;
|
||||
int curId = device.deviceId;
|
||||
float now = Time.realtimeSinceStartup;
|
||||
|
||||
if (curId == _lastDeviceId) return;
|
||||
if (DebounceWindow > 0f && (now - _lastInputTime) < DebounceWindow) return;
|
||||
|
||||
_lastInputTime = now;
|
||||
_lastDeviceId = curId;
|
||||
|
||||
CurrentCategory = DetermineCategoryFromDevice(device);
|
||||
CurrentDeviceName = device.displayName ?? $"Device_{curId}";
|
||||
|
||||
EmitChangeLog();
|
||||
}
|
||||
|
||||
// ------------------ 监听设备变更 --------------------
|
||||
private static void OnDeviceChange(InputDevice device, InputDeviceChange change)
|
||||
{
|
||||
if (change == InputDeviceChange.Removed || change == InputDeviceChange.Disconnected)
|
||||
{
|
||||
if (device.deviceId == _lastDeviceId)
|
||||
{
|
||||
_lastDeviceId = -1;
|
||||
_lastInputTime = -Mathf.Infinity;
|
||||
CurrentDeviceName = "";
|
||||
CurrentCategory = InputDeviceCategory.Keyboard;
|
||||
EmitChangeLog();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------ 分类逻辑 --------------------
|
||||
private static InputDeviceCategory DetermineCategoryFromDevice(InputDevice device)
|
||||
{
|
||||
if (device == null) return InputDeviceCategory.Keyboard;
|
||||
if (device is Keyboard || device is Mouse) return InputDeviceCategory.Keyboard;
|
||||
if (IsGamepadLike(device)) return GetGamepadCategory(device);
|
||||
|
||||
string combined = $"{device.description.interfaceName} {device.layout} {device.description.product} {device.description.manufacturer} {device.displayName}".ToLower();
|
||||
|
||||
if (combined.Contains("xbox") || combined.Contains("xinput")) return InputDeviceCategory.Xbox;
|
||||
if (combined.Contains("dualshock") || combined.Contains("dualsense") || combined.Contains("playstation")) return InputDeviceCategory.PlayStation;
|
||||
|
||||
return InputDeviceCategory.Other;
|
||||
}
|
||||
|
||||
private static bool IsGamepadLike(InputDevice device)
|
||||
{
|
||||
if (device is Gamepad) return true;
|
||||
if (device is Joystick) return true;
|
||||
|
||||
var layout = (device.layout ?? "").ToLower();
|
||||
return layout.Contains("gamepad") || layout.Contains("controller") || layout.Contains("joystick");
|
||||
}
|
||||
|
||||
private static InputDeviceCategory GetGamepadCategory(InputDevice device)
|
||||
{
|
||||
if (device == null) return InputDeviceCategory.Other;
|
||||
|
||||
var iface = (device.description.interfaceName ?? "").ToLower();
|
||||
if (iface.Contains("xinput")) return InputDeviceCategory.Xbox;
|
||||
|
||||
if (TryParseVidPidFromCapabilities(device.description.capabilities, out int vendorId, out int _))
|
||||
{
|
||||
if (vendorId == 0x045E || vendorId == 1118) return InputDeviceCategory.Xbox;
|
||||
if (vendorId == 0x054C || vendorId == 1356) return InputDeviceCategory.PlayStation;
|
||||
}
|
||||
|
||||
string combined = $"{device.description.interfaceName} {device.layout} {device.description.product} {device.description.manufacturer} {device.displayName}".ToLower();
|
||||
if (combined.Contains("xbox")) return InputDeviceCategory.Xbox;
|
||||
if (combined.Contains("dualshock") || combined.Contains("playstation")) return InputDeviceCategory.PlayStation;
|
||||
|
||||
return InputDeviceCategory.Other;
|
||||
}
|
||||
|
||||
// ------------------ VID/PID 解析 --------------------
|
||||
private static bool TryParseVidPidFromCapabilities(string capabilities, out int vendorId, out int productId)
|
||||
{
|
||||
vendorId = 0;
|
||||
productId = 0;
|
||||
if (string.IsNullOrEmpty(capabilities)) return false;
|
||||
|
||||
try
|
||||
{
|
||||
var decVendor = Regex.Match(capabilities, "\"vendorId\"\\s*:\\s*(\\d+)", RegexOptions.IgnoreCase);
|
||||
var decProduct = Regex.Match(capabilities, "\"productId\"\\s*:\\s*(\\d+)", RegexOptions.IgnoreCase);
|
||||
|
||||
if (decVendor.Success) int.TryParse(decVendor.Groups[1].Value, out vendorId);
|
||||
if (decProduct.Success) int.TryParse(decProduct.Groups[1].Value, out productId);
|
||||
|
||||
return vendorId != 0 || productId != 0;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------ 输出 --------------------
|
||||
private static void EmitChangeLog()
|
||||
{
|
||||
int vid = GetVendorId();
|
||||
int pid = GetProductId();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
Debug.Log($"输入设备变更 -> {CurrentCategory} 触发设备: {CurrentDeviceName} vid=0x{vid:X} pid=0x{pid:X}");
|
||||
#endif
|
||||
|
||||
OnDeviceChanged?.Invoke(CurrentCategory);
|
||||
}
|
||||
|
||||
private static int GetVendorId()
|
||||
{
|
||||
foreach (var d in InputSystem.devices)
|
||||
{
|
||||
if ((d.displayName ?? "") == CurrentDeviceName &&
|
||||
TryParseVidPidFromCapabilities(d.description.capabilities, out int v, out int _))
|
||||
return v;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int GetProductId()
|
||||
{
|
||||
foreach (var d in InputSystem.devices)
|
||||
{
|
||||
if ((d.displayName ?? "") == CurrentDeviceName &&
|
||||
TryParseVidPidFromCapabilities(d.description.capabilities, out int _, out int p))
|
||||
return p;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
11
Runtime/Input/InputDeviceWatcher.cs.meta
Normal file
11
Runtime/Input/InputDeviceWatcher.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e78f6224467e13742a70115f1942d941
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -19,8 +19,7 @@ namespace AlicizaX.UI.Extension
|
||||
|
||||
[SerializeField] private Mode m_Mode;
|
||||
|
||||
[Tooltip("Enables navigation to wrap around from last to first or first to last element. Does not work for automatic grid navigation")] [HideInInspector] [SerializeField]
|
||||
private bool m_WrapAround;
|
||||
[HideInInspector] [SerializeField] private bool m_WrapAround;
|
||||
|
||||
[HideInInspector] [SerializeField] private UXSelectable m_SelectOnUp;
|
||||
[HideInInspector] [SerializeField] private UXSelectable m_SelectOnDown;
|
||||
|
||||
@ -25,11 +25,16 @@ namespace AlicizaX.UI.Extension
|
||||
private readonly List<CanvasGroup> m_CanvasGroupCache = new List<CanvasGroup>();
|
||||
|
||||
[SerializeField] private UXNavigation m_Navigation = UXNavigation.defaultNavigation;
|
||||
|
||||
public UXNavigation navigation
|
||||
{
|
||||
get { return m_Navigation; }
|
||||
set { if (SetPropertyUtility.SetStruct(ref m_Navigation, value)) OnSetProperty(); }
|
||||
set
|
||||
{
|
||||
if (SetPropertyUtility.SetStruct(ref m_Navigation, value)) OnSetProperty();
|
||||
}
|
||||
}
|
||||
|
||||
public static UXSelectable[] allSelectablesArray
|
||||
{
|
||||
get
|
||||
@ -167,6 +172,7 @@ namespace AlicizaX.UI.Extension
|
||||
maxFurthestScore = score;
|
||||
bestFurthestPick = sel;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -256,12 +262,35 @@ namespace AlicizaX.UI.Extension
|
||||
}
|
||||
}
|
||||
|
||||
// default handlers to be overridden
|
||||
public virtual void OnPointerDown(PointerEventData eventData) { }
|
||||
public virtual void OnPointerUp(PointerEventData eventData) { }
|
||||
public virtual void OnPointerEnter(PointerEventData eventData) { }
|
||||
public virtual void OnPointerExit(PointerEventData eventData) { }
|
||||
public virtual void OnSelect(BaseEventData eventData) { hasSelection = true; }
|
||||
public virtual void OnDeselect(BaseEventData eventData) { hasSelection = false; }
|
||||
public virtual void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
if (eventData.button != PointerEventData.InputButton.Left)
|
||||
return;
|
||||
|
||||
if (IsInteractable() && navigation.mode != UXNavigation.Mode.None && EventSystem.current != null)
|
||||
EventSystem.current.SetSelectedGameObject(gameObject, eventData);
|
||||
}
|
||||
|
||||
public virtual void OnPointerUp(PointerEventData eventData)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnPointerEnter(PointerEventData eventData)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnPointerExit(PointerEventData eventData)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnSelect(BaseEventData eventData)
|
||||
{
|
||||
hasSelection = true;
|
||||
}
|
||||
|
||||
public virtual void OnDeselect(BaseEventData eventData)
|
||||
{
|
||||
hasSelection = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
36
Runtime/UXComponent/TestUI.cs
Normal file
36
Runtime/UXComponent/TestUI.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace AlicizaX.UI.Extension.UXComponent
|
||||
{
|
||||
public class TestUI : UXSelectable
|
||||
{
|
||||
private float maxSliderValue;
|
||||
private float minSliderValue;
|
||||
[SerializeField] private Slider _slider;
|
||||
|
||||
private float sliderRange;
|
||||
|
||||
[SerializeField] private float SLIDERSTEP = 100.0f; //used to
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
maxSliderValue = _slider.maxValue;
|
||||
minSliderValue = _slider.minValue;
|
||||
sliderRange = maxSliderValue - minSliderValue;
|
||||
}
|
||||
|
||||
public override void OnMove(AxisEventData eventData)
|
||||
{
|
||||
if (eventData.moveDir == MoveDirection.Left || eventData.moveDir == MoveDirection.Right)
|
||||
{
|
||||
float sliderChange = eventData.moveDir == MoveDirection.Right ? 1 * (sliderRange / SLIDERSTEP) : -1 * (sliderRange / SLIDERSTEP);
|
||||
float tempValue = _slider.value + sliderChange;
|
||||
_slider.value = Mathf.Clamp(tempValue, minSliderValue, maxSliderValue);
|
||||
Debug.Log(_slider.value );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Runtime/UXComponent/TestUI.cs.meta
Normal file
3
Runtime/UXComponent/TestUI.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67a18ee6ebd4470b9e936543b01af7ca
|
||||
timeCreated: 1764765598
|
||||
Loading…
Reference in New Issue
Block a user