using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using UnityEngine; using UnityEngine.InputSystem; using System.Linq; namespace BITKit { [System.Serializable] public class InputActionGroup : IDisposable { public override string ToString() { return $"Source:{Source}\nEnabled:{isEnabled}\nInitialized:{state}\nKeys:{string.Join("\n",actions.Keys)}"; } public string Source; 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(); /// /// 注册所有(started,performed,canceled)回调 /// /// /// /// public InputActionGroup RegisterCallback(InputActionReference reference, Action callback) { var action = EnsureCreated(reference); action.RegisterCallback(callback); return this; } public InputActionGroup RegisterCallback(InputAction inputAction,Action callback) { EnsureConfiguration(); var action = actions.GetOrAdd(inputAction.name, _=>inputAction.Clone()); allowInput.Invoke(); action.RegisterCallback(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); 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); 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)) action.UnRegisterCallback(callback); } public void UnRegisterCallback(InputAction inputAction, Action callback) { if(actions.TryGetValue(inputAction.name,out var action)) action.UnRegisterCallback(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(); } } }