diff --git a/Runtime/Input.meta b/Runtime/Input.meta deleted file mode 100644 index 946e48f..0000000 --- a/Runtime/Input.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 7f9ad1ce05574ba886146f9982e01142 -timeCreated: 1764839428 \ No newline at end of file diff --git a/Runtime/Input/InputDeviceWatcher.cs b/Runtime/Input/InputDeviceWatcher.cs deleted file mode 100644 index 5666299..0000000 --- a/Runtime/Input/InputDeviceWatcher.cs +++ /dev/null @@ -1,245 +0,0 @@ -#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; - - private static InputDeviceCategory _lastEmittedCategory = InputDeviceCategory.Keyboard; - - public static event Action OnDeviceChanged; - - private static bool initialized = false; - - [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] - public static void Initialize() - { - if (initialized) return; - initialized = true; - - CurrentCategory = InputDeviceCategory.Keyboard; - CurrentDeviceName = ""; - _lastEmittedCategory = CurrentCategory; // 初始化同步 - - _anyInputAction = new InputAction("AnyDevice", InputActionType.PassThrough); - _anyInputAction.AddBinding("/anyKey"); - _anyInputAction.AddBinding("/*"); - _anyInputAction.AddBinding("/*"); - - _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; - - _lastEmittedCategory = InputDeviceCategory.Keyboard; - } - - private static void OnAnyInputPerformed(InputAction.CallbackContext ctx) - { - if (ctx.control == null || ctx.control.device == null) return; - - var device = ctx.control.device; - - if (!IsRelevantDevice(device)) return; - - 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}"; - - EmitChange(); - } - - 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; - EmitChange(); - } - } - } - - // ------------------ 分类逻辑 -------------------- - private static InputDeviceCategory DetermineCategoryFromDevice(InputDevice device) - { - if (device == null) return InputDeviceCategory.Keyboard; - // 重要:鼠标不再被视为键盘类(避免鼠标触发时回退到 Keyboard) - if (device is Keyboard) return InputDeviceCategory.Keyboard; - if (device is Mouse) return InputDeviceCategory.Other; // 明确忽略鼠标 - 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(); - // 这里保留 controller/gamepad/joystick 的识别,但忽略 mouse/touch 等 - if (layout.Contains("mouse") || layout.Contains("touch") || layout.Contains("pen")) return false; - return layout.Contains("gamepad") || layout.Contains("controller") || layout.Contains("joystick"); - } - - private static bool IsRelevantDevice(InputDevice device) - { - if (device == null) return false; - if (device is Keyboard) return true; - if (IsGamepadLike(device)) return true; - return false; - } - - 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 EmitChange() - { - if (CurrentCategory == _lastEmittedCategory) - { - return; - } - - 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); - _lastEmittedCategory = 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 diff --git a/Runtime/Input/InputDeviceWatcher.cs.meta b/Runtime/Input/InputDeviceWatcher.cs.meta deleted file mode 100644 index ac22b49..0000000 --- a/Runtime/Input/InputDeviceWatcher.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e78f6224467e13742a70115f1942d941 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: