2023-06-05 19:57:17 +08:00
|
|
|
using System;
|
|
|
|
using System.Collections;
|
2023-11-15 23:55:06 +08:00
|
|
|
using System.Collections.Concurrent;
|
2023-06-05 19:57:17 +08:00
|
|
|
using System.Collections.Generic;
|
|
|
|
using UnityEngine;
|
|
|
|
using UnityEngine.InputSystem;
|
|
|
|
using System.Linq;
|
2023-09-01 14:35:05 +08:00
|
|
|
|
2023-06-05 19:57:17 +08:00
|
|
|
namespace BITKit
|
|
|
|
{
|
2025-04-17 19:21:44 +08:00
|
|
|
[Serializable]
|
2023-06-05 19:57:17 +08:00
|
|
|
public class InputActionGroup : IDisposable
|
|
|
|
{
|
2025-04-17 19:21:44 +08:00
|
|
|
private class InputActionProxy
|
2024-03-31 23:31:00 +08:00
|
|
|
{
|
2025-04-17 19:21:44 +08:00
|
|
|
public event Action<InputAction.CallbackContext> Callback;
|
|
|
|
public void Invoke(InputAction.CallbackContext context)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
Callback?.Invoke(context);
|
|
|
|
}
|
|
|
|
catch (OperationCanceledException)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
2024-03-31 23:31:00 +08:00
|
|
|
}
|
2025-04-17 19:21:44 +08:00
|
|
|
|
|
|
|
private int _lockFile = Guid.NewGuid().GetHashCode();
|
2023-06-05 19:57:17 +08:00
|
|
|
public bool allowGlobalActivation = true;
|
2023-09-01 14:35:05 +08:00
|
|
|
[SerializeField, ReadOnly] private bool isEnabled;
|
2025-04-17 19:21:44 +08:00
|
|
|
private InitializationState _state = InitializationState.None;
|
2024-03-31 23:31:00 +08:00
|
|
|
public readonly ValidHandle allowInput = new();
|
2025-04-17 19:21:44 +08:00
|
|
|
private readonly ConcurrentDictionary<string,InputAction> _actions = new();
|
|
|
|
private readonly ConcurrentDictionary<int, InputActionProxy> _callbacks = new();
|
2023-09-01 14:35:05 +08:00
|
|
|
|
2024-03-31 23:31:00 +08:00
|
|
|
/// <summary>
|
|
|
|
/// 注册所有(started,performed,canceled)回调
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="reference"></param>
|
|
|
|
/// <param name="callback"></param>
|
|
|
|
/// <returns></returns>
|
2023-09-01 14:35:05 +08:00
|
|
|
public InputActionGroup RegisterCallback(InputActionReference reference,
|
|
|
|
Action<InputAction.CallbackContext> callback)
|
2024-03-31 23:31:00 +08:00
|
|
|
{
|
|
|
|
var action = EnsureCreated(reference);
|
2025-04-17 19:21:44 +08:00
|
|
|
_callbacks[action.GetHashCode()].Callback += callback;
|
2024-03-31 23:31:00 +08:00
|
|
|
return this;
|
|
|
|
}
|
2025-02-24 23:02:43 +08:00
|
|
|
|
|
|
|
public InputActionGroup RegisterCallback(InputAction inputAction,Action<InputAction.CallbackContext> callback)
|
|
|
|
{
|
2025-04-17 19:21:44 +08:00
|
|
|
var action = EnsureCreated(inputAction);
|
|
|
|
_callbacks[action.GetHashCode()].Callback += callback;
|
2025-02-24 23:02:43 +08:00
|
|
|
return this;
|
|
|
|
}
|
2024-03-31 23:31:00 +08:00
|
|
|
|
|
|
|
public InputAction EnsureCreated(InputActionReference reference)
|
2023-06-05 19:57:17 +08:00
|
|
|
{
|
2023-06-07 02:02:14 +08:00
|
|
|
if (reference is null)
|
|
|
|
{
|
|
|
|
Debug.LogWarning($"未知的引用");
|
2024-03-31 23:31:00 +08:00
|
|
|
return null;
|
2023-06-07 02:02:14 +08:00
|
|
|
}
|
2023-09-01 14:35:05 +08:00
|
|
|
|
2023-06-05 19:57:17 +08:00
|
|
|
EnsureConfiguration();
|
2025-04-17 19:21:44 +08:00
|
|
|
var action = _actions.GetOrAdd(reference.name, _ =>
|
2023-11-15 23:55:06 +08:00
|
|
|
{
|
|
|
|
var newAction = reference.action.Clone();
|
|
|
|
newAction.Rename(reference.name);
|
2025-04-17 19:21:44 +08:00
|
|
|
|
|
|
|
var callback = _callbacks[newAction.GetHashCode()] = new();
|
|
|
|
newAction.performed += callback.Invoke;
|
|
|
|
newAction.canceled+=callback.Invoke;
|
|
|
|
newAction.started+=callback.Invoke;
|
|
|
|
|
2023-11-15 23:55:06 +08:00
|
|
|
return newAction;
|
|
|
|
});
|
2023-06-05 19:57:17 +08:00
|
|
|
|
2024-03-31 23:31:00 +08:00
|
|
|
allowInput.Invoke();
|
2023-06-05 19:57:17 +08:00
|
|
|
|
2024-03-31 23:31:00 +08:00
|
|
|
return action;
|
2023-06-05 19:57:17 +08:00
|
|
|
}
|
2025-02-24 23:02:43 +08:00
|
|
|
public InputAction EnsureCreated(InputAction inputAction)
|
|
|
|
{
|
|
|
|
EnsureConfiguration();
|
2025-04-17 19:21:44 +08:00
|
|
|
var action = _actions.GetOrAdd(inputAction.name, _ =>
|
2025-02-24 23:02:43 +08:00
|
|
|
{
|
|
|
|
var newAction = inputAction.Clone();
|
|
|
|
newAction.Rename(inputAction.name);
|
2025-04-17 19:21:44 +08:00
|
|
|
|
|
|
|
var callback = _callbacks[newAction.GetHashCode()] = new();
|
|
|
|
newAction.performed += callback.Invoke;
|
|
|
|
newAction.canceled+=callback.Invoke;
|
|
|
|
newAction.started+=callback.Invoke;
|
|
|
|
|
2025-02-24 23:02:43 +08:00
|
|
|
return newAction;
|
|
|
|
});
|
|
|
|
|
|
|
|
allowInput.Invoke();
|
|
|
|
|
|
|
|
return action;
|
|
|
|
}
|
2024-03-31 23:31:00 +08:00
|
|
|
|
2023-11-15 23:55:06 +08:00
|
|
|
public void Inherit(InputActionGroup other)
|
|
|
|
{
|
|
|
|
throw new NotImplementedException();
|
|
|
|
}
|
|
|
|
public InputAction GetAction(string name)
|
|
|
|
{
|
2025-04-17 19:21:44 +08:00
|
|
|
if(_actions.TryGetValue(name,out var action))
|
2023-11-15 23:55:06 +08:00
|
|
|
return action;
|
|
|
|
throw new ArgumentException($"未知的引用{name}");
|
|
|
|
}
|
|
|
|
public InputAction GetAction(InputActionReference reference)
|
|
|
|
{
|
2025-04-17 19:21:44 +08:00
|
|
|
if(_actions.TryGetValue(reference.name,out var action))
|
2023-11-15 23:55:06 +08:00
|
|
|
return action;
|
|
|
|
throw new ArgumentException($"未知的引用{reference.name}");
|
|
|
|
}
|
2023-06-05 19:57:17 +08:00
|
|
|
public void UnRegisterCallback(InputActionReference reference, Action<InputAction.CallbackContext> callback)
|
|
|
|
{
|
2025-04-17 19:21:44 +08:00
|
|
|
if (_actions.TryGetValue(reference.name, out var action))
|
|
|
|
{
|
|
|
|
_callbacks[action.GetHashCode()].Callback -= callback;
|
|
|
|
}
|
2023-06-05 19:57:17 +08:00
|
|
|
}
|
2023-09-01 14:35:05 +08:00
|
|
|
|
2025-02-24 23:02:43 +08:00
|
|
|
public void UnRegisterCallback(InputAction inputAction, Action<InputAction.CallbackContext> callback)
|
|
|
|
{
|
2025-04-17 19:21:44 +08:00
|
|
|
if (_actions.TryGetValue(inputAction.name, out var action))
|
|
|
|
{
|
|
|
|
_callbacks[action.GetHashCode()].Callback -= callback;
|
|
|
|
}
|
2025-02-24 23:02:43 +08:00
|
|
|
}
|
|
|
|
|
2023-09-01 14:35:05 +08:00
|
|
|
private void EnsureConfiguration()
|
2023-06-05 19:57:17 +08:00
|
|
|
{
|
2025-04-17 19:21:44 +08:00
|
|
|
if (_state is not InitializationState.Initialized)
|
2023-06-05 19:57:17 +08:00
|
|
|
{
|
|
|
|
Init();
|
2025-04-17 19:21:44 +08:00
|
|
|
_state = InitializationState.Initialized;
|
2023-06-05 19:57:17 +08:00
|
|
|
}
|
|
|
|
}
|
2023-09-01 14:35:05 +08:00
|
|
|
|
|
|
|
private void Init()
|
2023-06-05 19:57:17 +08:00
|
|
|
{
|
|
|
|
if (allowGlobalActivation)
|
2023-10-24 23:38:22 +08:00
|
|
|
BITInputSystem.AllowInput.AddListener(ListenGlobalInput);
|
|
|
|
allowInput.AddListener(AllowInput);
|
2023-06-05 19:57:17 +08:00
|
|
|
}
|
2023-09-01 14:35:05 +08:00
|
|
|
|
2023-10-24 23:38:22 +08:00
|
|
|
private void ListenGlobalInput(bool allowInput)
|
2023-06-05 19:57:17 +08:00
|
|
|
{
|
2025-04-17 19:21:44 +08:00
|
|
|
this.allowInput.SetDisableElements(_lockFile, !allowInput);
|
2023-06-05 19:57:17 +08:00
|
|
|
}
|
2023-09-01 14:35:05 +08:00
|
|
|
|
2023-10-24 23:38:22 +08:00
|
|
|
private void AllowInput(bool allow)
|
2023-06-05 19:57:17 +08:00
|
|
|
{
|
2025-04-17 19:21:44 +08:00
|
|
|
foreach (var action in _actions.Values)
|
2023-06-05 19:57:17 +08:00
|
|
|
{
|
|
|
|
if (allow)
|
|
|
|
{
|
|
|
|
action.Enable();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
action.Disable();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
isEnabled = allow;
|
|
|
|
}
|
|
|
|
public void Dispose()
|
|
|
|
{
|
2025-04-17 19:21:44 +08:00
|
|
|
foreach (var action in _actions.Values)
|
2023-06-05 19:57:17 +08:00
|
|
|
{
|
|
|
|
action.Disable();
|
2023-11-15 23:55:06 +08:00
|
|
|
action.Dispose();
|
2023-06-05 19:57:17 +08:00
|
|
|
}
|
2025-04-17 19:21:44 +08:00
|
|
|
_actions.Clear();
|
2023-06-05 19:57:17 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|