TH1/Unity/Assets/Scripts/TH1_Logic/Input/InputConfigManager.cs
2025-12-24 16:03:33 +08:00

204 lines
6.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* @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();
}
}
}
}
}