HKMBFZ/Assets/SKFramework/Core/Input/KeyInputController.cs

166 lines
5.6 KiB
C#

using System;
using UnityEngine;
using System.Collections.Generic;
namespace SK.Framework
{
public sealed class KeyInputController
{
private class KeyInputInfo
{
public readonly KeyCode keyCode;
public readonly List<KeyInput> keyInputs;
public InputState state = InputState.None;
public KeyInputInfo(KeyCode keyCode)
{
this.keyCode = keyCode;
keyInputs = new List<KeyInput>();
}
public void Reset()
{
state = InputState.None;
}
}
private readonly List<KeyInput> keyInputs;
private readonly List<KeyInputInfo> infos;
private readonly Dictionary<KeyCode, InputTrigger> triggers;
public KeyInputController()
{
keyInputs = new List<KeyInput>();
infos = new List<KeyInputInfo>();
triggers = new Dictionary<KeyCode, InputTrigger>();
}
public void Update()
{
for (int i = 0; i < keyInputs.Count; i++)
{
keyInputs[i].Value = Input.GetKey(keyInputs[i].Key);
}
for (int i = 0; i < infos.Count; i++)
{
var info = infos[i];
bool flag = false;
for (int j = info.keyInputs.Count - 1; j >= 0; j--)
{
if (info.keyInputs[j].Value)
{
flag = true;
break;
}
}
if (flag)
{
info.state = info.state == InputState.None || info.state == InputState.Released
? InputState.Pressed
: InputState.Held;
triggers.Clear();
}
else if (triggers.ContainsKey(info.keyCode))
{
switch (triggers[info.keyCode].type)
{
case InputTriggerType.Pressed:
info.state = InputState.Pressed;
triggers.Remove(info.keyCode);
break;
case InputTriggerType.Held:
info.state = InputState.Held;
if (triggers[info.keyCode].disposeWhen.Invoke())
triggers.Remove(info.keyCode);
break;
case InputTriggerType.Released:
info.state = InputState.Released;
triggers.Remove(info.keyCode);
break;
}
}
else
{
info.state = info.state == InputState.Pressed || info.state == InputState.Held
? InputState.Released
: InputState.None;
}
}
}
public void Reset()
{
for (int i = 0; i < keyInputs.Count; i++)
{
keyInputs[i].Reset();
}
}
public bool Register(KeyInput keyInput)
{
if (keyInputs.Contains(keyInput))
{
return false;
}
keyInputs.Add(keyInput);
var target = infos.Find(m => m.keyCode == keyInput.Key);
if (target == null)
{
target = new KeyInputInfo(keyInput.Key);
infos.Add(target);
}
target.keyInputs.Add(keyInput);
return true;
}
public bool Unregister(KeyInput keyInput)
{
if (!keyInputs.Contains(keyInput))
{
return false;
}
keyInputs.Remove(keyInput);
var target = infos.Find(m => m.keyCode == keyInput.Key);
if (target != null)
{
target.keyInputs.Remove(keyInput);
if (target.keyInputs.Count == 0)
{
infos.Remove(target);
}
}
return true;
}
public bool GetKeyDown(KeyInput keyInput)
{
var target = infos.Find(m => m.keyCode == keyInput.Key);
return target != null && target.state == InputState.Pressed;
}
public bool GetKey(KeyInput keyInput)
{
var target = infos.Find(m => m.keyCode == keyInput.Key);
return target != null && (target.state == InputState.Held || target.state == InputState.Pressed);
}
public bool GetKeyUp(KeyInput keyInput)
{
var target = infos.Find(m => m.keyCode == keyInput.Key);
return target != null && target.state == InputState.Released;
}
public void Trigger(KeyCode keyCode, InputTriggerType type)
{
if (keyCode != KeyCode.None && !triggers.ContainsKey(keyCode) && type != InputTriggerType.Held)
{
triggers.Add(keyCode, new InputTrigger(type));
Debug.Log($"触发键盘按键 [{keyCode}] {(type == InputTriggerType.Pressed ? "" : "")}");
}
}
public void Trigger(KeyCode keyCode, InputTriggerType type, Func<bool> disposeWhen)
{
if (keyCode != KeyCode.None && !triggers.ContainsKey(keyCode) && type == InputTriggerType.Held)
{
triggers.Add(keyCode, new InputTrigger(type, disposeWhen));
Debug.Log($"触发键盘按键 [{keyCode}] 持续按下");
}
}
}
}