204 lines
6.4 KiB
C#
204 lines
6.4 KiB
C#
/*
|
||
* @Author: 白哉
|
||
* @Description:
|
||
* @Date: 2025年09月05日 星期五 15:09:36
|
||
* @Modify:
|
||
*/
|
||
|
||
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using Logic.CrashSight;
|
||
using MemoryPack;
|
||
using UnityEngine;
|
||
|
||
|
||
namespace Logic
|
||
{
|
||
public class InputConfigManager
|
||
{
|
||
public static InputConfigManager Instance = new InputConfigManager();
|
||
|
||
private InputConfig _config;
|
||
private List<KeyCode> _pressedKeys = new List<KeyCode>();
|
||
private bool _isListening = false;
|
||
private float _waitTime = 0.2f; // 等待时间,防止误触
|
||
private float _lastKeyPressTime;
|
||
private InputEnum _curInputEnum;
|
||
private Dictionary<InputEnum, List<System.Action>> _inputCallBack;
|
||
public InputConfig Config => _config;
|
||
public bool IsListening => _isListening;
|
||
|
||
|
||
public void Init()
|
||
{
|
||
RefreshInputConfig();
|
||
_config.Init();
|
||
_inputCallBack = new Dictionary<InputEnum, List<System.Action>>();
|
||
}
|
||
|
||
// 开始监听按键绑定, UI 调用开始记录输入
|
||
public void StartRecordInput(InputEnum inputEnum)
|
||
{
|
||
if (_isListening) return;
|
||
_curInputEnum = inputEnum;
|
||
_isListening = true;
|
||
_pressedKeys.Clear();
|
||
}
|
||
|
||
// 外部获取状态使用, 游戏逻辑用
|
||
public bool IsActive(InputEnum inputEnum)
|
||
{
|
||
if (_config == null) return false;
|
||
var keyConfig = _config.GetInputKeyConfig(inputEnum);
|
||
if (keyConfig == null) return false;
|
||
return keyConfig.IsActive;
|
||
}
|
||
|
||
// 注册输入回调
|
||
public void RegisterInputCallback(InputEnum inputEnum, System.Action callback)
|
||
{
|
||
if (!_inputCallBack.ContainsKey(inputEnum))
|
||
{
|
||
_inputCallBack[inputEnum] = new List<System.Action>();
|
||
}
|
||
_inputCallBack[inputEnum].Add(callback);
|
||
}
|
||
|
||
public void RefreshInputConfig()
|
||
{
|
||
if (_config != null) return;
|
||
string path = Application.persistentDataPath + "/input_config.dat";
|
||
if (File.Exists(path))
|
||
{
|
||
try
|
||
{
|
||
byte[] bytes = File.ReadAllBytes(path);
|
||
_config = MemoryPackSerializer.Deserialize<InputConfig>(bytes);
|
||
}
|
||
catch (System.Exception e)
|
||
{
|
||
LogSystem.LogWarning($"InputConfig 反序列化失败,将重新创建配置: {e.Message}");
|
||
_config = null;
|
||
}
|
||
}
|
||
_config ??= new InputConfig();
|
||
}
|
||
|
||
// 保存输入配置
|
||
public void SaveInputConfig()
|
||
{
|
||
if (_config == null) return;
|
||
byte[] bytes = MemoryPackSerializer.Serialize(_config);
|
||
File.WriteAllBytes(Application.persistentDataPath + "/input_config.dat", bytes);
|
||
}
|
||
|
||
// 每帧调用,返回绑定结果(null表示还在监听中)
|
||
public void Update()
|
||
{
|
||
UpdateConfigListening();
|
||
UpdateConfigActive();
|
||
}
|
||
|
||
private void UpdateConfigListening()
|
||
{
|
||
if (!_isListening) return;
|
||
|
||
// 检测所有按下的键
|
||
foreach (KeyCode key in System.Enum.GetValues(typeof(KeyCode)))
|
||
{
|
||
if (key == KeyCode.None) continue;
|
||
|
||
if (Input.GetKeyDown(key))
|
||
{
|
||
if (!_pressedKeys.Contains(key))
|
||
{
|
||
_pressedKeys.Add(key);
|
||
_lastKeyPressTime = Time.time;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 检查是否所有键都已释放
|
||
if (_pressedKeys.Count > 0)
|
||
{
|
||
bool allReleased = true;
|
||
foreach (var key in _pressedKeys)
|
||
{
|
||
if (Input.GetKey(key))
|
||
{
|
||
allReleased = false;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (_pressedKeys.Count >= 3) allReleased = true;
|
||
// 所有键释放后,确认绑定
|
||
if (allReleased && Time.time - _lastKeyPressTime > _waitTime)
|
||
{
|
||
_isListening = false;
|
||
_config?.SetInputKeyConfig(_curInputEnum, _pressedKeys);
|
||
SaveInputConfig();
|
||
// TODO 这里可以调用 UI 刷新,因为配置发生了变化
|
||
}
|
||
}
|
||
}
|
||
|
||
private void UpdateConfigActive()
|
||
{
|
||
if (_config == null || _isListening) return;
|
||
|
||
foreach (var keyConfig in _config.InputKeyConfigs)
|
||
{
|
||
keyConfig.IsActive = IsKeyCombinationActive(keyConfig.KeyCodes);
|
||
if (IsKeyCombinationTriggered(keyConfig.KeyCodes)) OnInputCallback(keyConfig.InputType);
|
||
}
|
||
}
|
||
|
||
// 检查组合键是否被激活
|
||
private bool IsKeyCombinationActive(List<KeyCode> keyCodes)
|
||
{
|
||
for (int i = 0; i < keyCodes.Count; i++)
|
||
{
|
||
if (!Input.GetKey(keyCodes[i]))
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
// 检查组合键是否被触发
|
||
private bool IsKeyCombinationTriggered(List<KeyCode> keyCodes)
|
||
{
|
||
if (keyCodes == null || keyCodes.Count == 0) return false;
|
||
|
||
// 单键情况
|
||
if (keyCodes.Count == 1)
|
||
{
|
||
return Input.GetKeyDown(keyCodes[0]);
|
||
}
|
||
|
||
// 组合键:前面的键必须按住,最后一个键检测 GetKeyDown
|
||
for (int i = 0; i < keyCodes.Count - 1; i++)
|
||
{
|
||
if (!Input.GetKey(keyCodes[i]))
|
||
return false;
|
||
}
|
||
|
||
return Input.GetKeyDown(keyCodes[^1]);
|
||
}
|
||
|
||
// 输入触发时的回调
|
||
private void OnInputCallback(InputEnum inputEnum)
|
||
{
|
||
LogSystem.LogInfo($"触发 {inputEnum}");
|
||
if (_inputCallBack != null && _inputCallBack.TryGetValue(inputEnum, out var callbackList))
|
||
{
|
||
foreach (var callback in callbackList)
|
||
{
|
||
callback?.Invoke();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} |