BITKit/Src/Unity/Scripts/InputSystem/InputActionGroup.cs

183 lines
5.8 KiB
C#
Raw Normal View History

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
}
}
}