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

162 lines
5.0 KiB
C#

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<string,InputAction> actions = new();
/// <summary>
/// 注册所有(started,performed,canceled)回调
/// </summary>
/// <param name="reference"></param>
/// <param name="callback"></param>
/// <returns></returns>
public InputActionGroup RegisterCallback(InputActionReference reference,
Action<InputAction.CallbackContext> callback)
{
var action = EnsureCreated(reference);
action.RegisterCallback(callback);
return this;
}
public InputActionGroup RegisterCallback(InputAction inputAction,Action<InputAction.CallbackContext> 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<InputAction.CallbackContext> callback)
{
if(actions.TryGetValue(reference.name,out var action))
action.UnRegisterCallback(callback);
}
public void UnRegisterCallback(InputAction inputAction, Action<InputAction.CallbackContext> 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();
}
}
}