Extra2D/include/platform/input_module.h

375 lines
8.8 KiB
C
Raw Normal View History

#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 {
// 自动注册到模块系统,优先级为 10
E2D_REGISTER_MODULE(InputModule, "Input", 10)
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