完成输入管理器variant

This commit is contained in:
Ziyu
2025-06-16 14:44:47 +08:00
parent e015ff4a49
commit a7334b2ccb
2 changed files with 21 additions and 16 deletions
+11 -12
View File
@@ -48,8 +48,8 @@ void InputManager::processEvent(const SDL_Event& event) {
bool is_down = event.key.down;
bool is_repeat = event.key.repeat;
auto it = scancode_to_actions_map_.find(scancode);
if (it != scancode_to_actions_map_.end()) { // 如果按键有对应的action
auto it = input_to_actions_map_.find(scancode);
if (it != input_to_actions_map_.end()) { // 如果按键有对应的action
const std::vector<std::string>& associated_actions = it->second;
for (const std::string& action_name : associated_actions) {
updateActionState(action_name, is_down, is_repeat); // 更新action状态
@@ -59,10 +59,10 @@ void InputManager::processEvent(const SDL_Event& event) {
}
case SDL_EVENT_MOUSE_BUTTON_DOWN:
case SDL_EVENT_MOUSE_BUTTON_UP: {
Uint8 button = event.button.button; // 获取鼠标按钮
Uint32 button = event.button.button; // 获取鼠标按钮
bool is_down = event.button.down;
auto it = mouse_button_to_actions_map_.find(button);
if (it != mouse_button_to_actions_map_.end()) { // 如果鼠标按钮有对应的action
auto it = input_to_actions_map_.find(button);
if (it != input_to_actions_map_.end()) { // 如果鼠标按钮有对应的action
const std::vector<std::string>& associated_actions = it->second;
for (const std::string& action_name : associated_actions) {
// 鼠标事件不考虑repeat, 所以第三个参数传false
@@ -139,8 +139,7 @@ void InputManager::initializeMappings(const engine::core::Config* config) {
throw std::runtime_error("输入管理器: Config 为空指针");
}
actions_to_keyname_map_ = config->input_mappings_; // 获取配置中的输入映射(动作 -> 按键名称)
scancode_to_actions_map_.clear();
mouse_button_to_actions_map_.clear();
input_to_actions_map_.clear();
action_states_.clear();
// 如果配置中没有定义鼠标按钮动作(通常不需要配置),则添加默认映射, 用于 UI
@@ -160,14 +159,14 @@ void InputManager::initializeMappings(const engine::core::Config* config) {
// 设置 "按键 -> 动作" 的映射
for (const std::string& key_name : key_names) {
SDL_Scancode scancode = scancodeFromString(key_name); // 尝试根据按键名称获取scancode
Uint8 mouse_button = mouseButtonUint8FromString(key_name); // 尝试根据按键名称获取鼠标按钮
Uint32 mouse_button = mouseButtonFromString(key_name); // 尝试根据按键名称获取鼠标按钮
// 未来可添加其它输入类型 ...
if (scancode != SDL_SCANCODE_UNKNOWN) { // 如果scancode有效,则将action添加到scancode_to_actions_map_中
scancode_to_actions_map_[scancode].push_back(action_name);
input_to_actions_map_[scancode].push_back(action_name);
spdlog::trace(" 映射按键: {} (Scancode: {}) 到动作: {}", key_name, static_cast<int>(scancode), action_name);
} else if (mouse_button != 0) { // 如果鼠标按钮有效,则将action添加到mouse_button_to_actions_map_中
mouse_button_to_actions_map_[mouse_button].push_back(action_name);
input_to_actions_map_[mouse_button].push_back(action_name);
spdlog::trace(" 映射鼠标按钮: {} (Button ID: {}) 到动作: {}", key_name, static_cast<int>(mouse_button), action_name);
// else if: 未来可添加其它输入类型 ...
} else {
@@ -184,8 +183,8 @@ SDL_Scancode InputManager::scancodeFromString(const std::string& key_name) {
return SDL_GetScancodeFromName(key_name.c_str());
}
// 将鼠标按钮名称字符串转换为 SDL 按钮 Uint8 值
Uint8 InputManager::mouseButtonUint8FromString(const std::string& button_name) {
// 将鼠标按钮名称字符串转换为 SDL 按钮 Uint32 值
Uint32 InputManager::mouseButtonFromString(const std::string& button_name) {
if (button_name == "MouseLeft") return SDL_BUTTON_LEFT;
if (button_name == "MouseMiddle") return SDL_BUTTON_MIDDLE;
if (button_name == "MouseRight") return SDL_BUTTON_RIGHT;
+10 -4
View File
@@ -2,6 +2,7 @@
#include <string>
#include <unordered_map>
#include <vector>
#include <variant>
#include <SDL3/SDL_render.h>
#include <glm/vec2.hpp>
@@ -18,12 +19,17 @@ enum class ActionState {
RELEASED_THIS_FRAME ///< @brief 动作在本帧刚刚被释放
};
/**
* @brief 输入管理器类,负责处理输入事件和动作状态。
*
* 该类管理输入事件,将按键转换为动作状态,并提供查询动作状态的功能。
* 它还处理鼠标位置的逻辑坐标转换。
*/
class InputManager final {
private:
SDL_Renderer* sdl_renderer_; ///< @brief 用于获取逻辑坐标的 SDL_Renderer 指针
std::unordered_map<std::string, std::vector<std::string>> actions_to_keyname_map_; ///< @brief 存储动作名称到按键名称列表的映射
std::unordered_map<SDL_Scancode, std::vector<std::string>> scancode_to_actions_map_;///< @brief 从键盘(Scancode)到关联的动作名称列表
std::unordered_map<Uint8, std::vector<std::string>> mouse_button_to_actions_map_; ///< @brief 从鼠标按钮 (Uint8) 到关联的动作名称列表
std::unordered_map<std::variant<SDL_Scancode, Uint32>, std::vector<std::string>> input_to_actions_map_;///< @brief 从输入到关联的动作名称列表
std::unordered_map<std::string, ActionState> action_states_; ///< @brief 存储每个动作的当前状态
@@ -56,10 +62,10 @@ public:
private:
void processEvent(const SDL_Event& event); ///< @brief 处理 SDL 事件(将按键转换为动作状态)
void initializeMappings(const engine::core::Config* config); ///< @brief 根据 Config配置初始化映射表
void updateActionState(const std::string& action_name, bool is_input_active, bool is_repeat_event); ///< @brief 辅助更新动作状态
SDL_Scancode scancodeFromString(const std::string& key_name); ///< @brief 将字符串键名转换为 SDL_Scancode
Uint8 mouseButtonUint8FromString(const std::string& button_name); ///< @brief 将字符串按钮名转换为 SDL_Button
Uint32 mouseButtonFromString(const std::string& button_name); ///< @brief 将字符串按钮名转换为 SDL_Button
};
} // namespace engine::input