375 lines
8.8 KiB
C++
375 lines
8.8 KiB
C++
#pragma once
|
||
|
||
#include <SDL.h>
|
||
#include <array>
|
||
#include <functional>
|
||
#include <module/module.h>
|
||
#include <module/module_registry.h>
|
||
#include <types/base/types.h>
|
||
#include <vector>
|
||
|
||
namespace extra2d {
|
||
|
||
/**
|
||
* @brief 键码别名
|
||
*/
|
||
using Key = SDL_Scancode;
|
||
|
||
/**
|
||
* @brief 按键常量
|
||
*/
|
||
namespace Keys {
|
||
constexpr Key Unknown = SDL_SCANCODE_UNKNOWN;
|
||
constexpr Key A = SDL_SCANCODE_A;
|
||
constexpr Key B = SDL_SCANCODE_B;
|
||
constexpr Key C = SDL_SCANCODE_C;
|
||
constexpr Key D = SDL_SCANCODE_D;
|
||
constexpr Key E = SDL_SCANCODE_E;
|
||
constexpr Key F = SDL_SCANCODE_F;
|
||
constexpr Key G = SDL_SCANCODE_G;
|
||
constexpr Key H = SDL_SCANCODE_H;
|
||
constexpr Key I = SDL_SCANCODE_I;
|
||
constexpr Key J = SDL_SCANCODE_J;
|
||
constexpr Key K = SDL_SCANCODE_K;
|
||
constexpr Key L = SDL_SCANCODE_L;
|
||
constexpr Key M = SDL_SCANCODE_M;
|
||
constexpr Key N = SDL_SCANCODE_N;
|
||
constexpr Key O = SDL_SCANCODE_O;
|
||
constexpr Key P = SDL_SCANCODE_P;
|
||
constexpr Key Q = SDL_SCANCODE_Q;
|
||
constexpr Key R = SDL_SCANCODE_R;
|
||
constexpr Key S = SDL_SCANCODE_S;
|
||
constexpr Key T = SDL_SCANCODE_T;
|
||
constexpr Key U = SDL_SCANCODE_U;
|
||
constexpr Key V = SDL_SCANCODE_V;
|
||
constexpr Key W = SDL_SCANCODE_W;
|
||
constexpr Key X = SDL_SCANCODE_X;
|
||
constexpr Key Y = SDL_SCANCODE_Y;
|
||
constexpr Key Z = SDL_SCANCODE_Z;
|
||
constexpr Key Num0 = SDL_SCANCODE_0;
|
||
constexpr Key Num1 = SDL_SCANCODE_1;
|
||
constexpr Key Num2 = SDL_SCANCODE_2;
|
||
constexpr Key Num3 = SDL_SCANCODE_3;
|
||
constexpr Key Num4 = SDL_SCANCODE_4;
|
||
constexpr Key Num5 = SDL_SCANCODE_5;
|
||
constexpr Key Num6 = SDL_SCANCODE_6;
|
||
constexpr Key Num7 = SDL_SCANCODE_7;
|
||
constexpr Key Num8 = SDL_SCANCODE_8;
|
||
constexpr Key Num9 = SDL_SCANCODE_9;
|
||
constexpr Key F1 = SDL_SCANCODE_F1;
|
||
constexpr Key F2 = SDL_SCANCODE_F2;
|
||
constexpr Key F3 = SDL_SCANCODE_F3;
|
||
constexpr Key F4 = SDL_SCANCODE_F4;
|
||
constexpr Key F5 = SDL_SCANCODE_F5;
|
||
constexpr Key F6 = SDL_SCANCODE_F6;
|
||
constexpr Key F7 = SDL_SCANCODE_F7;
|
||
constexpr Key F8 = SDL_SCANCODE_F8;
|
||
constexpr Key F9 = SDL_SCANCODE_F9;
|
||
constexpr Key F10 = SDL_SCANCODE_F10;
|
||
constexpr Key F11 = SDL_SCANCODE_F11;
|
||
constexpr Key F12 = SDL_SCANCODE_F12;
|
||
constexpr Key Space = SDL_SCANCODE_SPACE;
|
||
constexpr Key Enter = SDL_SCANCODE_RETURN;
|
||
constexpr Key Escape = SDL_SCANCODE_ESCAPE;
|
||
constexpr Key Tab = SDL_SCANCODE_TAB;
|
||
constexpr Key Backspace = SDL_SCANCODE_BACKSPACE;
|
||
constexpr Key Insert = SDL_SCANCODE_INSERT;
|
||
constexpr Key Delete = SDL_SCANCODE_DELETE;
|
||
constexpr Key Home = SDL_SCANCODE_HOME;
|
||
constexpr Key End = SDL_SCANCODE_END;
|
||
constexpr Key PageUp = SDL_SCANCODE_PAGEUP;
|
||
constexpr Key PageDown = SDL_SCANCODE_PAGEDOWN;
|
||
constexpr Key Left = SDL_SCANCODE_LEFT;
|
||
constexpr Key Right = SDL_SCANCODE_RIGHT;
|
||
constexpr Key Up = SDL_SCANCODE_UP;
|
||
constexpr Key Down = SDL_SCANCODE_DOWN;
|
||
constexpr Key LeftShift = SDL_SCANCODE_LSHIFT;
|
||
constexpr Key RightShift = SDL_SCANCODE_RSHIFT;
|
||
constexpr Key LeftCtrl = SDL_SCANCODE_LCTRL;
|
||
constexpr Key RightCtrl = SDL_SCANCODE_RCTRL;
|
||
constexpr Key LeftAlt = SDL_SCANCODE_LALT;
|
||
constexpr Key RightAlt = SDL_SCANCODE_RALT;
|
||
} // namespace Keys
|
||
|
||
/**
|
||
* @brief 鼠标按键
|
||
*/
|
||
enum class MouseBtn : uint8 {
|
||
Left = 0,
|
||
Middle = 1,
|
||
Right = 2,
|
||
X1 = 3,
|
||
X2 = 4,
|
||
Count = 5
|
||
};
|
||
|
||
/**
|
||
* @brief 游戏手柄按键
|
||
*/
|
||
enum class GamepadBtn : uint8 {
|
||
A = 0,
|
||
B = 1,
|
||
X = 2,
|
||
Y = 3,
|
||
Back = 4,
|
||
Guide = 5,
|
||
Start = 6,
|
||
LeftStick = 7,
|
||
RightStick = 8,
|
||
LeftShoulder = 9,
|
||
RightShoulder = 10,
|
||
DPadUp = 11,
|
||
DPadDown = 12,
|
||
DPadLeft = 13,
|
||
DPadRight = 14,
|
||
Count = 15
|
||
};
|
||
|
||
/**
|
||
* @brief 游戏手柄轴
|
||
*/
|
||
enum class GamepadAxis : uint8 {
|
||
LeftX = 0,
|
||
LeftY = 1,
|
||
RightX = 2,
|
||
RightY = 3,
|
||
TriggerLeft = 4,
|
||
TriggerRight = 5,
|
||
Count = 6
|
||
};
|
||
|
||
/**
|
||
* @brief 触摸状态
|
||
*/
|
||
enum class TouchState : uint8 { None = 0, Began, Moved, Ended, Cancelled };
|
||
|
||
/**
|
||
* @brief 触摸点信息
|
||
*/
|
||
struct TouchPoint {
|
||
int64 id = 0;
|
||
float x = 0.0f;
|
||
float y = 0.0f;
|
||
float prevX = 0.0f;
|
||
float prevY = 0.0f;
|
||
float deltaX = 0.0f;
|
||
float deltaY = 0.0f;
|
||
TouchState state = TouchState::None;
|
||
float pressure = 1.0f;
|
||
};
|
||
|
||
/**
|
||
* @brief 按键回调类型
|
||
*/
|
||
using KeyCb = std::function<void(Key)>;
|
||
using MouseBtnCb = std::function<void(MouseBtn, int32 x, int32 y)>;
|
||
using TouchCb = std::function<void(const TouchPoint &)>;
|
||
|
||
/**
|
||
* @brief 输入模块 - 简化版
|
||
*
|
||
* 管理键盘、鼠标、触摸、游戏手柄输入
|
||
* 使用新的 Module 基类,支持自动注册
|
||
*/
|
||
class InputModule : public Module {
|
||
// 优先级为 7,在 TimerModule (优先级 6) 之后初始化
|
||
E2D_REGISTER_MODULE(InputModule, "Input", 7)
|
||
|
||
public:
|
||
InputModule();
|
||
~InputModule() override;
|
||
|
||
// 禁止拷贝和移动
|
||
InputModule(const InputModule &) = delete;
|
||
InputModule &operator=(const InputModule &) = delete;
|
||
InputModule(InputModule &&) = delete;
|
||
InputModule &operator=(InputModule &&) = delete;
|
||
|
||
// Module 接口实现
|
||
bool init() override;
|
||
void shutdown() override;
|
||
void update(float deltaTime) override;
|
||
|
||
/**
|
||
* @brief 处理输入事件
|
||
*/
|
||
void processEvent(const SDL_Event &evt);
|
||
|
||
// ========== 键盘 ==========
|
||
|
||
/**
|
||
* @brief 检查按键是否按下
|
||
*/
|
||
bool isKeyDown(Key key) const;
|
||
|
||
/**
|
||
* @brief 检查按键是否刚按下
|
||
*/
|
||
bool isKeyPressed(Key key) const;
|
||
|
||
/**
|
||
* @brief 检查按键是否刚释放
|
||
*/
|
||
bool isKeyReleased(Key key) const;
|
||
|
||
// ========== 鼠标 ==========
|
||
|
||
/**
|
||
* @brief 获取鼠标位置
|
||
*/
|
||
void getMousePos(int32 &x, int32 &y) const;
|
||
|
||
/**
|
||
* @brief 获取鼠标位置(浮点)
|
||
*/
|
||
void getMousePos(float &x, float &y) const;
|
||
|
||
/**
|
||
* @brief 检查鼠标按键是否按下
|
||
*/
|
||
bool isMouseBtnDown(MouseBtn btn) const;
|
||
|
||
/**
|
||
* @brief 检查鼠标按键是否刚按下
|
||
*/
|
||
bool isMouseBtnPressed(MouseBtn btn) const;
|
||
|
||
/**
|
||
* @brief 检查鼠标按键是否刚释放
|
||
*/
|
||
bool isMouseBtnReleased(MouseBtn btn) const;
|
||
|
||
/**
|
||
* @brief 获取鼠标滚轮
|
||
*/
|
||
int32 getMouseWheel() const;
|
||
|
||
// ========== 触摸 ==========
|
||
|
||
/**
|
||
* @brief 获取触摸点数量
|
||
*/
|
||
int32 touchCount() const;
|
||
|
||
/**
|
||
* @brief 获取触摸点
|
||
* @param idx 触摸点索引
|
||
* @return 触摸点信息,无效索引返回 nullptr
|
||
*/
|
||
const TouchPoint *getTouch(int32 idx) const;
|
||
|
||
/**
|
||
* @brief 根据 ID 获取触摸点
|
||
*/
|
||
const TouchPoint *getTouchById(int64 id) const;
|
||
|
||
/**
|
||
* @brief 检查是否有触摸
|
||
*/
|
||
bool hasTouch() const { return touchCount() > 0; }
|
||
|
||
/**
|
||
* @brief 获取所有活跃触摸点
|
||
*/
|
||
const std::vector<TouchPoint> &getTouches() const { return activeTouches_; }
|
||
|
||
// ========== 游戏手柄 ==========
|
||
|
||
/**
|
||
* @brief 连接的游戏手柄数量
|
||
*/
|
||
int32 gamepadCount() const;
|
||
|
||
/**
|
||
* @brief 检查手柄按键是否按下
|
||
*/
|
||
bool isGamepadBtnDown(int32 idx, GamepadBtn btn) const;
|
||
|
||
/**
|
||
* @brief 检查手柄按键是否刚按下
|
||
*/
|
||
bool isGamepadBtnPressed(int32 idx, GamepadBtn btn) const;
|
||
|
||
/**
|
||
* @brief 获取手柄轴值 (-1.0 到 1.0)
|
||
*/
|
||
float getGamepadAxis(int32 idx, GamepadAxis axis) const;
|
||
|
||
// ========== 回调设置 ==========
|
||
|
||
/**
|
||
* @brief 设置按键按下回调
|
||
*/
|
||
void setOnKeyDown(KeyCb cb) { onKeyDown_ = std::move(cb); }
|
||
|
||
/**
|
||
* @brief 设置按键释放回调
|
||
*/
|
||
void setOnKeyUp(KeyCb cb) { onKeyUp_ = std::move(cb); }
|
||
|
||
/**
|
||
* @brief 设置鼠标按下回调
|
||
*/
|
||
void setOnMouseDown(MouseBtnCb cb) { onMouseDown_ = std::move(cb); }
|
||
|
||
/**
|
||
* @brief 设置鼠标释放回调
|
||
*/
|
||
void setOnMouseUp(MouseBtnCb cb) { onMouseUp_ = std::move(cb); }
|
||
|
||
/**
|
||
* @brief 设置触摸开始回调
|
||
*/
|
||
void setOnTouchBegan(TouchCb cb) { onTouchBegan_ = std::move(cb); }
|
||
|
||
/**
|
||
* @brief 设置触摸移动回调
|
||
*/
|
||
void setOnTouchMoved(TouchCb cb) { onTouchMoved_ = std::move(cb); }
|
||
|
||
/**
|
||
* @brief 设置触摸结束回调
|
||
*/
|
||
void setOnTouchEnded(TouchCb cb) { onTouchEnded_ = std::move(cb); }
|
||
|
||
private:
|
||
static constexpr int32 KEY_COUNT = SDL_NUM_SCANCODES;
|
||
static constexpr int32 MAX_GAMEPADS = 4;
|
||
static constexpr int32 MAX_TOUCHES = 10;
|
||
|
||
std::array<uint8, KEY_COUNT> keyState_{};
|
||
std::array<uint8, KEY_COUNT> keyPrev_{};
|
||
|
||
int32 mouseX_ = 0;
|
||
int32 mouseY_ = 0;
|
||
int32 mouseWheel_ = 0;
|
||
std::array<uint8, static_cast<size_t>(MouseBtn::Count)> mouseState_{};
|
||
std::array<uint8, static_cast<size_t>(MouseBtn::Count)> mousePrev_{};
|
||
|
||
std::vector<TouchPoint> activeTouches_;
|
||
std::vector<TouchPoint> endedTouches_;
|
||
|
||
SDL_GameController *gamepads_[MAX_GAMEPADS] = {};
|
||
std::array<uint8, static_cast<size_t>(GamepadBtn::Count)>
|
||
padState_[MAX_GAMEPADS];
|
||
std::array<uint8, static_cast<size_t>(GamepadBtn::Count)>
|
||
padPrev_[MAX_GAMEPADS];
|
||
|
||
KeyCb onKeyDown_;
|
||
KeyCb onKeyUp_;
|
||
MouseBtnCb onMouseDown_;
|
||
MouseBtnCb onMouseUp_;
|
||
TouchCb onTouchBegan_;
|
||
TouchCb onTouchMoved_;
|
||
TouchCb onTouchEnded_;
|
||
|
||
void openGamepad(int32 idx);
|
||
void closeGamepad(int32 idx);
|
||
|
||
void processTouchDown(const SDL_TouchFingerEvent &evt);
|
||
void processTouchUp(const SDL_TouchFingerEvent &evt);
|
||
void processTouchMotion(const SDL_TouchFingerEvent &evt);
|
||
};
|
||
|
||
} // namespace extra2d
|