using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using UnityEngine; using UnityEngine.InputSystem; using System.Linq; namespace BITKit { [Serializable] public class InputActionGroup : IDisposable { private class InputActionProxy { public event Action Callback; public void Invoke(InputAction.CallbackContext context) { try { Callback?.Invoke(context); } catch (OperationCanceledException) { } } } private int _lockFile = Guid.NewGuid().GetHashCode(); public bool allowGlobalActivation = true; [SerializeField, ReadOnly] private bool isEnabled; private InitializationState _state = InitializationState.None; public readonly ValidHandle allowInput = new(); private readonly ConcurrentDictionary _actions = new(); private readonly ConcurrentDictionary _callbacks = new(); /// /// 注册所有(started,performed,canceled)回调 /// /// /// /// public InputActionGroup RegisterCallback(InputActionReference reference, Action callback) { var action = EnsureCreated(reference); _callbacks[action.GetHashCode()].Callback += callback; return this; } public InputActionGroup RegisterCallback(InputAction inputAction,Action callback) { var action = EnsureCreated(inputAction); _callbacks[action.GetHashCode()].Callback += callback; return this; } public InputAction EnsureCreated(InputActionReference reference) { if (reference is null) { Debug.LogWarning($"未知的引用"); return null; } EnsureConfiguration(); var action = _actions.GetOrAdd(reference.name, _ => { var newAction = reference.action.Clone(); newAction.Rename(reference.name); var callback = _callbacks[newAction.GetHashCode()] = new(); newAction.performed += callback.Invoke; newAction.canceled+=callback.Invoke; newAction.started+=callback.Invoke; return newAction; }); allowInput.Invoke(); return action; } public InputAction EnsureCreated(InputAction inputAction) { EnsureConfiguration(); var action = _actions.GetOrAdd(inputAction.name, _ => { var newAction = inputAction.Clone(); newAction.Rename(inputAction.name); var callback = _callbacks[newAction.GetHashCode()] = new(); newAction.performed += callback.Invoke; newAction.canceled+=callback.Invoke; newAction.started+=callback.Invoke; return newAction; }); allowInput.Invoke(); return action; } public void Inherit(InputActionGroup other) { throw new NotImplementedException(); } public InputAction GetAction(string name) { if(_actions.TryGetValue(name,out var action)) return action; throw new ArgumentException($"未知的引用{name}"); } public InputAction GetAction(InputActionReference reference) { if(_actions.TryGetValue(reference.name,out var action)) return action; throw new ArgumentException($"未知的引用{reference.name}"); } public void UnRegisterCallback(InputActionReference reference, Action callback) { if (_actions.TryGetValue(reference.name, out var action)) { _callbacks[action.GetHashCode()].Callback -= callback; } } public void UnRegisterCallback(InputAction inputAction, Action callback) { if (_actions.TryGetValue(inputAction.name, out var action)) { _callbacks[action.GetHashCode()].Callback -= callback; } } private void EnsureConfiguration() { if (_state is not InitializationState.Initialized) { Init(); _state = InitializationState.Initialized; } } private void Init() { if (allowGlobalActivation) BITInputSystem.AllowInput.AddListener(ListenGlobalInput); allowInput.AddListener(AllowInput); } private void ListenGlobalInput(bool allowInput) { this.allowInput.SetDisableElements(_lockFile, !allowInput); } private void AllowInput(bool allow) { foreach (var action in _actions.Values) { if (allow) { action.Enable(); } else { action.Disable(); } } isEnabled = allow; } public void Dispose() { foreach (var action in _actions.Values) { action.Disable(); action.Dispose(); } _actions.Clear(); } } }