543 lines
13 KiB
C++
543 lines
13 KiB
C++
#pragma once
|
|
|
|
#include <extra2d/base/Types.h>
|
|
#include <extra2d/math/Math.h>
|
|
#include <vector>
|
|
#include <array>
|
|
|
|
struct SDL_GameController;
|
|
|
|
namespace extra2d {
|
|
|
|
/**
|
|
* @brief 触摸点信息
|
|
*/
|
|
struct Touch {
|
|
i64 id{-1};
|
|
Vec2 position{0, 0};
|
|
Vec2 startPosition{0, 0};
|
|
Vec2 delta{0, 0};
|
|
float pressure{1.0f};
|
|
float timestamp{0};
|
|
};
|
|
|
|
/**
|
|
* @brief 按键码常量
|
|
*/
|
|
namespace KeyCode {
|
|
constexpr i32 A = 4;
|
|
constexpr i32 B = 5;
|
|
constexpr i32 C = 6;
|
|
constexpr i32 D = 7;
|
|
constexpr i32 E = 8;
|
|
constexpr i32 F = 9;
|
|
constexpr i32 G = 10;
|
|
constexpr i32 H = 11;
|
|
constexpr i32 I = 12;
|
|
constexpr i32 J = 13;
|
|
constexpr i32 K = 14;
|
|
constexpr i32 L = 15;
|
|
constexpr i32 M = 16;
|
|
constexpr i32 N = 17;
|
|
constexpr i32 O = 18;
|
|
constexpr i32 P = 19;
|
|
constexpr i32 Q = 20;
|
|
constexpr i32 R = 21;
|
|
constexpr i32 S = 22;
|
|
constexpr i32 T = 23;
|
|
constexpr i32 U = 24;
|
|
constexpr i32 V = 25;
|
|
constexpr i32 W = 26;
|
|
constexpr i32 X = 27;
|
|
constexpr i32 Y = 28;
|
|
constexpr i32 Z = 29;
|
|
|
|
constexpr i32 Num1 = 30;
|
|
constexpr i32 Num2 = 31;
|
|
constexpr i32 Num3 = 32;
|
|
constexpr i32 Num4 = 33;
|
|
constexpr i32 Num5 = 34;
|
|
constexpr i32 Num6 = 35;
|
|
constexpr i32 Num7 = 36;
|
|
constexpr i32 Num8 = 37;
|
|
constexpr i32 Num9 = 38;
|
|
constexpr i32 Num0 = 39;
|
|
|
|
constexpr i32 Return = 40;
|
|
constexpr i32 Escape = 41;
|
|
constexpr i32 Backspace = 42;
|
|
constexpr i32 Tab = 43;
|
|
constexpr i32 Space = 44;
|
|
|
|
constexpr i32 Minus = 45;
|
|
constexpr i32 Equals = 46;
|
|
constexpr i32 LeftBracket = 47;
|
|
constexpr i32 RightBracket = 48;
|
|
constexpr i32 Backslash = 49;
|
|
constexpr i32 Semicolon = 51;
|
|
constexpr i32 Quote = 52;
|
|
constexpr i32 Grave = 53;
|
|
constexpr i32 Comma = 54;
|
|
constexpr i32 Period = 55;
|
|
constexpr i32 Slash = 56;
|
|
|
|
constexpr i32 CapsLock = 57;
|
|
|
|
constexpr i32 F1 = 58;
|
|
constexpr i32 F2 = 59;
|
|
constexpr i32 F3 = 60;
|
|
constexpr i32 F4 = 61;
|
|
constexpr i32 F5 = 62;
|
|
constexpr i32 F6 = 63;
|
|
constexpr i32 F7 = 64;
|
|
constexpr i32 F8 = 65;
|
|
constexpr i32 F9 = 66;
|
|
constexpr i32 F10 = 67;
|
|
constexpr i32 F11 = 68;
|
|
constexpr i32 F12 = 69;
|
|
|
|
constexpr i32 PrintScreen = 70;
|
|
constexpr i32 ScrollLock = 71;
|
|
constexpr i32 Pause = 72;
|
|
constexpr i32 Insert = 73;
|
|
constexpr i32 Home = 74;
|
|
constexpr i32 PageUp = 75;
|
|
constexpr i32 Delete = 76;
|
|
constexpr i32 End = 77;
|
|
constexpr i32 PageDown = 78;
|
|
|
|
constexpr i32 Right = 79;
|
|
constexpr i32 Left = 80;
|
|
constexpr i32 Down = 81;
|
|
constexpr i32 Up = 82;
|
|
|
|
constexpr i32 NumLockClear = 83;
|
|
constexpr i32 KPDivide = 84;
|
|
constexpr i32 KPMultiply = 85;
|
|
constexpr i32 KPMinus = 86;
|
|
constexpr i32 KPPlus = 87;
|
|
constexpr i32 KPEnter = 88;
|
|
constexpr i32 KP1 = 89;
|
|
constexpr i32 KP2 = 90;
|
|
constexpr i32 KP3 = 91;
|
|
constexpr i32 KP4 = 92;
|
|
constexpr i32 KP5 = 93;
|
|
constexpr i32 KP6 = 94;
|
|
constexpr i32 KP7 = 95;
|
|
constexpr i32 KP8 = 96;
|
|
constexpr i32 KP9 = 97;
|
|
constexpr i32 KP0 = 98;
|
|
constexpr i32 KPPeriod = 99;
|
|
|
|
constexpr i32 LCtrl = 224;
|
|
constexpr i32 LShift = 225;
|
|
constexpr i32 LAlt = 226;
|
|
constexpr i32 LGUI = 227;
|
|
constexpr i32 RCtrl = 228;
|
|
constexpr i32 RShift = 229;
|
|
constexpr i32 RAlt = 230;
|
|
constexpr i32 RGUI = 231;
|
|
}
|
|
|
|
/**
|
|
* @brief 鼠标按钮常量
|
|
*/
|
|
namespace MouseButton {
|
|
constexpr i32 Left = 1;
|
|
constexpr i32 Middle = 2;
|
|
constexpr i32 Right = 3;
|
|
constexpr i32 X1 = 4;
|
|
constexpr i32 X2 = 5;
|
|
}
|
|
|
|
/**
|
|
* @brief 手柄按钮常量
|
|
*/
|
|
namespace GamepadButton {
|
|
constexpr i32 A = 0;
|
|
constexpr i32 B = 1;
|
|
constexpr i32 X = 2;
|
|
constexpr i32 Y = 3;
|
|
constexpr i32 Back = 4;
|
|
constexpr i32 Guide = 5;
|
|
constexpr i32 Start = 6;
|
|
constexpr i32 LeftStick = 7;
|
|
constexpr i32 RightStick = 8;
|
|
constexpr i32 LeftShoulder = 9;
|
|
constexpr i32 RightShoulder = 10;
|
|
constexpr i32 DPadUp = 11;
|
|
constexpr i32 DPadDown = 12;
|
|
constexpr i32 DPadLeft = 13;
|
|
constexpr i32 DPadRight = 14;
|
|
}
|
|
|
|
/**
|
|
* @brief 手柄轴常量
|
|
*/
|
|
namespace GamepadAxis {
|
|
constexpr i32 LeftX = 0;
|
|
constexpr i32 LeftY = 1;
|
|
constexpr i32 RightX = 2;
|
|
constexpr i32 RightY = 3;
|
|
constexpr i32 LeftTrigger = 4;
|
|
constexpr i32 RightTrigger = 5;
|
|
}
|
|
|
|
/**
|
|
* @brief 输入管理类
|
|
*
|
|
* 管理键盘、鼠标、触摸和手柄输入状态。
|
|
*/
|
|
class Input {
|
|
public:
|
|
/**
|
|
* @brief 获取单例实例
|
|
* @return 输入实例
|
|
*/
|
|
static Input* getInstance();
|
|
|
|
/**
|
|
* @brief 每帧更新
|
|
*/
|
|
void update();
|
|
|
|
/**
|
|
* @brief 重置帧状态
|
|
*/
|
|
void resetFrameState();
|
|
|
|
// ==================== 键盘输入 ====================
|
|
|
|
/**
|
|
* @brief 检查按键是否刚按下
|
|
* @param keycode 按键码
|
|
* @return 如果刚按下返回 true
|
|
*/
|
|
bool isKeyDown(i32 keycode) const;
|
|
|
|
/**
|
|
* @brief 检查按键是否刚释放
|
|
* @param keycode 按键码
|
|
* @return 如果刚释放返回 true
|
|
*/
|
|
bool isKeyUp(i32 keycode) const;
|
|
|
|
/**
|
|
* @brief 检查按键是否按住
|
|
* @param keycode 按键码
|
|
* @return 如果按住返回 true
|
|
*/
|
|
bool isKeyPressed(i32 keycode) const;
|
|
|
|
/**
|
|
* @brief 获取任意按键是否按下
|
|
* @return 如果有任意按键按下返回 true
|
|
*/
|
|
bool isAnyKeyPressed() const;
|
|
|
|
// ==================== 鼠标输入 ====================
|
|
|
|
/**
|
|
* @brief 获取鼠标位置
|
|
* @return 鼠标位置
|
|
*/
|
|
Vec2 getMousePosition() const;
|
|
|
|
/**
|
|
* @brief 获取鼠标移动增量
|
|
* @return 鼠标移动增量
|
|
*/
|
|
Vec2 getMouseDelta() const;
|
|
|
|
/**
|
|
* @brief 检查鼠标按钮是否刚按下
|
|
* @param button 鼠标按钮
|
|
* @return 如果刚按下返回 true
|
|
*/
|
|
bool isMouseButtonDown(i32 button) const;
|
|
|
|
/**
|
|
* @brief 检查鼠标按钮是否刚释放
|
|
* @param button 鼠标按钮
|
|
* @return 如果刚释放返回 true
|
|
*/
|
|
bool isMouseButtonUp(i32 button) const;
|
|
|
|
/**
|
|
* @brief 检查鼠标按钮是否按住
|
|
* @param button 鼠标按钮
|
|
* @return 如果按住返回 true
|
|
*/
|
|
bool isMouseButtonPressed(i32 button) const;
|
|
|
|
/**
|
|
* @brief 获取鼠标滚轮增量
|
|
* @return 鼠标滚轮增量
|
|
*/
|
|
Vec2 getMouseWheelDelta() const;
|
|
|
|
/**
|
|
* @brief 设置鼠标锁定模式
|
|
* @param locked 是否锁定
|
|
*/
|
|
void setMouseLocked(bool locked);
|
|
|
|
/**
|
|
* @brief 检查鼠标是否锁定
|
|
* @return 如果锁定返回 true
|
|
*/
|
|
bool isMouseLocked() const;
|
|
|
|
// ==================== 触摸输入 ====================
|
|
|
|
/**
|
|
* @brief 检查是否有触摸输入
|
|
* @return 如果有触摸返回 true
|
|
*/
|
|
bool hasTouch() const;
|
|
|
|
/**
|
|
* @brief 获取当前触摸点数量
|
|
* @return 触摸点数量
|
|
*/
|
|
i32 getTouchCount() const;
|
|
|
|
/**
|
|
* @brief 获取指定 ID 的触摸点
|
|
* @param id 触摸点 ID
|
|
* @return 触摸点指针,如果不存在返回 nullptr
|
|
*/
|
|
const Touch* getTouch(i64 id) const;
|
|
|
|
/**
|
|
* @brief 按索引获取触摸点
|
|
* @param index 索引
|
|
* @return 触摸点指针
|
|
*/
|
|
const Touch* getTouchByIndex(i32 index) const;
|
|
|
|
/**
|
|
* @brief 获取所有触摸点
|
|
* @return 触摸点列表
|
|
*/
|
|
const std::vector<Touch>& getTouches() const;
|
|
|
|
/**
|
|
* @brief 检查触摸点是否刚按下
|
|
* @param id 触摸点 ID
|
|
* @return 如果刚按下返回 true
|
|
*/
|
|
bool isTouchDown(i64 id) const;
|
|
|
|
/**
|
|
* @brief 检查触摸点是否刚抬起
|
|
* @param id 触摸点 ID
|
|
* @return 如果刚抬起返回 true
|
|
*/
|
|
bool isTouchUp(i64 id) const;
|
|
|
|
/**
|
|
* @brief 检查触摸点是否移动中
|
|
* @param id 触摸点 ID
|
|
* @return 如果移动中返回 true
|
|
*/
|
|
bool isTouchMoving(i64 id) const;
|
|
|
|
// ==================== 多点触控手势 ====================
|
|
|
|
/**
|
|
* @brief 检查是否正在双指缩放
|
|
* @return 如果正在缩放返回 true
|
|
*/
|
|
bool isPinching() const;
|
|
|
|
/**
|
|
* @brief 获取缩放比例
|
|
* @return 缩放比例
|
|
*/
|
|
float getPinchScale() const;
|
|
|
|
/**
|
|
* @brief 获取缩放中心点
|
|
* @return 缩放中心点
|
|
*/
|
|
Vec2 getPinchCenter() const;
|
|
|
|
/**
|
|
* @brief 检查是否正在双指旋转
|
|
* @return 如果正在旋转返回 true
|
|
*/
|
|
bool isRotating() const;
|
|
|
|
/**
|
|
* @brief 获取旋转角度
|
|
* @return 旋转角度(度数)
|
|
*/
|
|
float getRotationAngle() const;
|
|
|
|
// ==================== 手柄输入 ====================
|
|
|
|
/**
|
|
* @brief 获取已连接手柄数量
|
|
* @return 手柄数量
|
|
*/
|
|
i32 getConnectedGamepadCount() const;
|
|
|
|
/**
|
|
* @brief 检查手柄是否已连接
|
|
* @param id 手柄 ID
|
|
* @return 如果已连接返回 true
|
|
*/
|
|
bool isGamepadConnected(i32 id) const;
|
|
|
|
/**
|
|
* @brief 获取手柄名称
|
|
* @param id 手柄 ID
|
|
* @return 手柄名称
|
|
*/
|
|
std::string getGamepadName(i32 id) const;
|
|
|
|
/**
|
|
* @brief 检查手柄按钮是否按下
|
|
* @param id 手柄 ID
|
|
* @param button 按钮索引
|
|
* @return 如果按下返回 true
|
|
*/
|
|
bool isGamepadButtonDown(i32 id, i32 button) const;
|
|
|
|
/**
|
|
* @brief 获取手柄轴值
|
|
* @param id 手柄 ID
|
|
* @param axis 轴索引
|
|
* @return 轴值 (-1.0 到 1.0)
|
|
*/
|
|
float getGamepadAxis(i32 id, i32 axis) const;
|
|
|
|
/**
|
|
* @brief 设置手柄震动
|
|
* @param id 手柄 ID
|
|
* @param lowFreq 低频震动强度 (0.0 到 1.0)
|
|
* @param highFreq 高频震动强度 (0.0 到 1.0)
|
|
* @param durationMs 震动持续时间(毫秒)
|
|
*/
|
|
void setGamepadRumble(i32 id, float lowFreq, float highFreq, u32 durationMs);
|
|
|
|
// ==================== 内部方法 ====================
|
|
|
|
/**
|
|
* @brief 处理键盘按下事件
|
|
*/
|
|
void handleKeyDown(i32 keycode);
|
|
|
|
/**
|
|
* @brief 处理键盘释放事件
|
|
*/
|
|
void handleKeyUp(i32 keycode);
|
|
|
|
/**
|
|
* @brief 处理鼠标移动事件
|
|
*/
|
|
void handleMouseMove(float x, float y, float dx, float dy);
|
|
|
|
/**
|
|
* @brief 处理鼠标按钮按下事件
|
|
*/
|
|
void handleMouseButtonDown(i32 button);
|
|
|
|
/**
|
|
* @brief 处理鼠标按钮释放事件
|
|
*/
|
|
void handleMouseButtonUp(i32 button);
|
|
|
|
/**
|
|
* @brief 处理鼠标滚轮事件
|
|
*/
|
|
void handleMouseWheel(float dx, float dy);
|
|
|
|
/**
|
|
* @brief 处理触摸开始事件
|
|
*/
|
|
void handleTouchDown(i64 id, float x, float y, float pressure);
|
|
|
|
/**
|
|
* @brief 处理触摸移动事件
|
|
*/
|
|
void handleTouchMove(i64 id, float x, float y, float dx, float dy, float pressure);
|
|
|
|
/**
|
|
* @brief 处理触摸结束事件
|
|
*/
|
|
void handleTouchUp(i64 id);
|
|
|
|
/**
|
|
* @brief 处理手柄连接事件
|
|
*/
|
|
void handleGamepadConnected(i32 id);
|
|
|
|
/**
|
|
* @brief 处理手柄断开事件
|
|
*/
|
|
void handleGamepadDisconnected(i32 id);
|
|
|
|
/**
|
|
* @brief 处理手柄按钮事件
|
|
*/
|
|
void handleGamepadButton(i32 id, i32 button, bool pressed);
|
|
|
|
/**
|
|
* @brief 处理手柄轴事件
|
|
*/
|
|
void handleGamepadAxis(i32 id, i32 axis, float value);
|
|
|
|
private:
|
|
Input();
|
|
~Input();
|
|
|
|
Input(const Input&) = delete;
|
|
Input& operator=(const Input&) = delete;
|
|
|
|
void updateGestures();
|
|
|
|
static Input* instance_;
|
|
|
|
static constexpr size_t KEY_COUNT = 512;
|
|
static constexpr size_t MOUSE_BUTTON_COUNT = 8;
|
|
static constexpr size_t GAMEPAD_COUNT = 4;
|
|
static constexpr size_t GAMEPAD_BUTTON_COUNT = 32;
|
|
static constexpr size_t GAMEPAD_AXIS_COUNT = 8;
|
|
|
|
std::array<bool, KEY_COUNT> currentKeyState_{};
|
|
std::array<bool, KEY_COUNT> previousKeyState_{};
|
|
|
|
Vec2 mousePosition_{0, 0};
|
|
Vec2 mouseDelta_{0, 0};
|
|
Vec2 mouseWheelDelta_{0, 0};
|
|
std::array<bool, MOUSE_BUTTON_COUNT> currentMouseState_{};
|
|
std::array<bool, MOUSE_BUTTON_COUNT> previousMouseState_{};
|
|
bool mouseLocked_{false};
|
|
|
|
std::vector<Touch> activeTouches_;
|
|
std::vector<i64> beganTouchIds_;
|
|
std::vector<i64> endedTouchIds_;
|
|
|
|
float lastPinchDistance_{0};
|
|
float pinchScale_{1.0f};
|
|
Vec2 pinchCenter_{0, 0};
|
|
bool pinching_{false};
|
|
|
|
float lastRotationAngle_{0};
|
|
float rotationAngle_{0};
|
|
bool rotating_{false};
|
|
|
|
struct GamepadState {
|
|
SDL_GameController* controller{nullptr};
|
|
std::array<bool, GAMEPAD_BUTTON_COUNT> buttonState_{};
|
|
std::array<float, GAMEPAD_AXIS_COUNT> axisState_{};
|
|
bool connected{false};
|
|
std::string name;
|
|
};
|
|
std::array<GamepadState, GAMEPAD_COUNT> gamepads_;
|
|
};
|
|
|
|
} // namespace extra2d
|