feat(事件系统): 添加SDL事件转换器并重构窗口事件处理
添加EventConverter类用于将SDL事件转换为引擎内部事件格式 重构Window类的事件处理逻辑,支持通过回调函数处理转换后的事件 修改Application类以使用新的事件系统
This commit is contained in:
parent
3cec8ff7ef
commit
137369c37c
|
|
@ -1,6 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <extra2d/core/math_types.h>
|
||||
#include <extra2d/core/types.h>
|
||||
#include <variant>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
|
||||
#include <extra2d/event/event.h>
|
||||
#include <SDL.h>
|
||||
|
||||
namespace extra2d {
|
||||
|
||||
/**
|
||||
* @brief SDL事件转换器
|
||||
*/
|
||||
class EventConverter {
|
||||
public:
|
||||
static Event convert(const SDL_Event& e);
|
||||
|
||||
private:
|
||||
static Event convertKey(const SDL_KeyboardEvent& e, EventType type);
|
||||
static Event convertMouseBtn(const SDL_MouseButtonEvent& e, EventType type);
|
||||
static Event convertMouseMove(const SDL_MouseMotionEvent& e);
|
||||
static Event convertMouseWheel(const SDL_MouseWheelEvent& e);
|
||||
static Event convertWindow(const SDL_WindowEvent& e);
|
||||
static Event convertGamepadBtn(const SDL_ControllerButtonEvent& e, EventType type);
|
||||
static Event convertGamepadAxis(const SDL_ControllerAxisEvent& e);
|
||||
static Event convertTouch(const SDL_TouchFingerEvent& e, EventType type);
|
||||
|
||||
static i32 mapKey(SDL_Keycode key);
|
||||
static i32 mapMouseBtn(u8 btn);
|
||||
static i32 mapGamepadBtn(u8 btn);
|
||||
static i32 mapGamepadAxis(u8 axis);
|
||||
};
|
||||
|
||||
} // namespace extra2d
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <extra2d/core/types.h>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include <SDL.h>
|
||||
|
|
@ -18,25 +19,29 @@ struct WindowConfig {
|
|||
|
||||
class Window {
|
||||
public:
|
||||
using OnEvent = std::function<void(const SDL_Event&)>;
|
||||
|
||||
Window();
|
||||
~Window();
|
||||
|
||||
bool create(const WindowConfig& config);
|
||||
void destroy();
|
||||
|
||||
void pollEvents();
|
||||
void poll();
|
||||
bool shouldClose() const;
|
||||
void setShouldClose(bool close);
|
||||
void close();
|
||||
|
||||
void setTitle(const std::string& title);
|
||||
void setSize(int width, int height);
|
||||
void setFullscreen(bool fullscreen);
|
||||
|
||||
int getWidth() const { return width_; }
|
||||
int getHeight() const { return height_; }
|
||||
bool isFullscreen() const { return fullscreen_; }
|
||||
int width() const { return width_; }
|
||||
int height() const { return height_; }
|
||||
bool fullscreen() const { return fullscreen_; }
|
||||
|
||||
SDL_Window* sdlWindow() const { return sdlWindow_; }
|
||||
void onEvent(OnEvent cb) { onEvent_ = cb; }
|
||||
|
||||
SDL_Window* native() const { return sdlWindow_; }
|
||||
|
||||
private:
|
||||
SDL_Window* sdlWindow_ = nullptr;
|
||||
|
|
@ -44,6 +49,7 @@ private:
|
|||
int height_ = 720;
|
||||
bool fullscreen_ = true;
|
||||
bool shouldClose_ = false;
|
||||
OnEvent onEvent_;
|
||||
};
|
||||
|
||||
} // namespace extra2d
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
#include <extra2d/app/application.h>
|
||||
#include <extra2d/render/render_device.h>
|
||||
#include <extra2d/services/event_service.h>
|
||||
#include <extra2d/services/logger_service.h>
|
||||
#include <extra2d/window/event_converter.h>
|
||||
#include <extra2d/window/window.h>
|
||||
|
||||
#include <SDL.h>
|
||||
|
|
@ -30,8 +32,19 @@ bool Application::init() {
|
|||
return false;
|
||||
}
|
||||
|
||||
// 设置事件回调,将 SDL 事件转换为 Extra2D 事件
|
||||
window_->onEvent([](const SDL_Event &e) {
|
||||
Event event = EventConverter::convert(e);
|
||||
if (event.type != EventType::None) {
|
||||
auto eventService = ServiceLocator::instance().get<IEventService>();
|
||||
if (eventService) {
|
||||
eventService->push(event);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
auto &device = RenderDevice::instance();
|
||||
if (!device.init(window_->sdlWindow())) {
|
||||
if (!device.init(window_->native())) {
|
||||
E2D_ERROR(CAT_APP, "渲染设备初始化失败");
|
||||
window_->destroy();
|
||||
delete window_;
|
||||
|
|
@ -95,7 +108,7 @@ void Application::mainLoop() {
|
|||
fpsTimer_ -= 1.0f;
|
||||
}
|
||||
|
||||
window_->pollEvents();
|
||||
window_->poll();
|
||||
ServiceLocator::instance().update(dt_);
|
||||
RenderDevice::instance().swapBuffers();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,225 @@
|
|||
#include <extra2d/window/event_converter.h>
|
||||
|
||||
namespace extra2d {
|
||||
|
||||
Event EventConverter::convert(const SDL_Event& e) {
|
||||
switch (e.type) {
|
||||
case SDL_KEYDOWN:
|
||||
return convertKey(e.key, EventType::KeyPressed);
|
||||
case SDL_KEYUP:
|
||||
return convertKey(e.key, EventType::KeyReleased);
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
return convertMouseBtn(e.button, EventType::MouseButtonPressed);
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
return convertMouseBtn(e.button, EventType::MouseButtonReleased);
|
||||
case SDL_MOUSEMOTION:
|
||||
return convertMouseMove(e.motion);
|
||||
case SDL_MOUSEWHEEL:
|
||||
return convertMouseWheel(e.wheel);
|
||||
case SDL_WINDOWEVENT:
|
||||
return convertWindow(e.window);
|
||||
case SDL_CONTROLLERBUTTONDOWN:
|
||||
return convertGamepadBtn(e.cbutton, EventType::GamepadButtonPressed);
|
||||
case SDL_CONTROLLERBUTTONUP:
|
||||
return convertGamepadBtn(e.cbutton, EventType::GamepadButtonReleased);
|
||||
case SDL_CONTROLLERAXISMOTION:
|
||||
return convertGamepadAxis(e.caxis);
|
||||
case SDL_FINGERDOWN:
|
||||
return convertTouch(e.tfinger, EventType::TouchBegan);
|
||||
case SDL_FINGERMOTION:
|
||||
return convertTouch(e.tfinger, EventType::TouchMoved);
|
||||
case SDL_FINGERUP:
|
||||
return convertTouch(e.tfinger, EventType::TouchEnded);
|
||||
default:
|
||||
return Event{};
|
||||
}
|
||||
}
|
||||
|
||||
Event EventConverter::convertKey(const SDL_KeyboardEvent& e, EventType type) {
|
||||
Event event;
|
||||
event.type = type;
|
||||
event.data = KeyEvent{mapKey(e.keysym.sym), static_cast<i32>(e.keysym.scancode), e.keysym.mod};
|
||||
return event;
|
||||
}
|
||||
|
||||
Event EventConverter::convertMouseBtn(const SDL_MouseButtonEvent& e, EventType type) {
|
||||
Event event;
|
||||
event.type = type;
|
||||
event.data = MouseButtonEvent{mapMouseBtn(e.button), 0, Vec2{static_cast<f32>(e.x), static_cast<f32>(e.y)}};
|
||||
return event;
|
||||
}
|
||||
|
||||
Event EventConverter::convertMouseMove(const SDL_MouseMotionEvent& e) {
|
||||
Event event;
|
||||
event.type = EventType::MouseMoved;
|
||||
event.data = MouseMoveEvent{Vec2{static_cast<f32>(e.x), static_cast<f32>(e.y)}, Vec2{static_cast<f32>(e.xrel), static_cast<f32>(e.yrel)}};
|
||||
return event;
|
||||
}
|
||||
|
||||
Event EventConverter::convertMouseWheel(const SDL_MouseWheelEvent& e) {
|
||||
Event event;
|
||||
event.type = EventType::MouseScrolled;
|
||||
event.data = MouseScrollEvent{Vec2{static_cast<f32>(e.x), static_cast<f32>(e.y)}, Vec2{}};
|
||||
return event;
|
||||
}
|
||||
|
||||
Event EventConverter::convertWindow(const SDL_WindowEvent& e) {
|
||||
switch (e.event) {
|
||||
case SDL_WINDOWEVENT_CLOSE:
|
||||
return Event::windowClose();
|
||||
case SDL_WINDOWEVENT_RESIZED:
|
||||
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
||||
return Event::windowResize(e.data1, e.data2);
|
||||
default:
|
||||
return Event{};
|
||||
}
|
||||
}
|
||||
|
||||
Event EventConverter::convertGamepadBtn(const SDL_ControllerButtonEvent& e, EventType type) {
|
||||
Event event;
|
||||
event.type = type;
|
||||
event.data = GamepadButtonEvent{static_cast<i32>(e.which), mapGamepadBtn(e.button)};
|
||||
return event;
|
||||
}
|
||||
|
||||
Event EventConverter::convertGamepadAxis(const SDL_ControllerAxisEvent& e) {
|
||||
Event event;
|
||||
event.type = EventType::GamepadAxisMoved;
|
||||
event.data = GamepadAxisEvent{static_cast<i32>(e.which), mapGamepadAxis(e.axis), static_cast<f32>(e.value) / 32767.0f};
|
||||
return event;
|
||||
}
|
||||
|
||||
Event EventConverter::convertTouch(const SDL_TouchFingerEvent& e, EventType type) {
|
||||
Event event;
|
||||
event.type = type;
|
||||
// SDL 触摸坐标是归一化的 (0.0 - 1.0),转换为像素坐标
|
||||
event.data = TouchEvent{
|
||||
static_cast<i32>(e.fingerId),
|
||||
Vec2{e.x, e.y}
|
||||
};
|
||||
return event;
|
||||
}
|
||||
|
||||
i32 EventConverter::mapKey(SDL_Keycode key) {
|
||||
switch (key) {
|
||||
case SDLK_a: return 0;
|
||||
case SDLK_b: return 1;
|
||||
case SDLK_c: return 2;
|
||||
case SDLK_d: return 3;
|
||||
case SDLK_e: return 4;
|
||||
case SDLK_f: return 5;
|
||||
case SDLK_g: return 6;
|
||||
case SDLK_h: return 7;
|
||||
case SDLK_i: return 8;
|
||||
case SDLK_j: return 9;
|
||||
case SDLK_k: return 10;
|
||||
case SDLK_l: return 11;
|
||||
case SDLK_m: return 12;
|
||||
case SDLK_n: return 13;
|
||||
case SDLK_o: return 14;
|
||||
case SDLK_p: return 15;
|
||||
case SDLK_q: return 16;
|
||||
case SDLK_r: return 17;
|
||||
case SDLK_s: return 18;
|
||||
case SDLK_t: return 19;
|
||||
case SDLK_u: return 20;
|
||||
case SDLK_v: return 21;
|
||||
case SDLK_w: return 22;
|
||||
case SDLK_x: return 23;
|
||||
case SDLK_y: return 24;
|
||||
case SDLK_z: return 25;
|
||||
case SDLK_0: return 26;
|
||||
case SDLK_1: return 27;
|
||||
case SDLK_2: return 28;
|
||||
case SDLK_3: return 29;
|
||||
case SDLK_4: return 30;
|
||||
case SDLK_5: return 31;
|
||||
case SDLK_6: return 32;
|
||||
case SDLK_7: return 33;
|
||||
case SDLK_8: return 34;
|
||||
case SDLK_9: return 35;
|
||||
case SDLK_F1: return 36;
|
||||
case SDLK_F2: return 37;
|
||||
case SDLK_F3: return 38;
|
||||
case SDLK_F4: return 39;
|
||||
case SDLK_F5: return 40;
|
||||
case SDLK_F6: return 41;
|
||||
case SDLK_F7: return 42;
|
||||
case SDLK_F8: return 43;
|
||||
case SDLK_F9: return 44;
|
||||
case SDLK_F10: return 45;
|
||||
case SDLK_F11: return 46;
|
||||
case SDLK_F12: return 47;
|
||||
case SDLK_SPACE: return 48;
|
||||
case SDLK_RETURN: return 49;
|
||||
case SDLK_ESCAPE: return 50;
|
||||
case SDLK_TAB: return 51;
|
||||
case SDLK_BACKSPACE: return 52;
|
||||
case SDLK_INSERT: return 53;
|
||||
case SDLK_DELETE: return 54;
|
||||
case SDLK_HOME: return 55;
|
||||
case SDLK_END: return 56;
|
||||
case SDLK_PAGEUP: return 57;
|
||||
case SDLK_PAGEDOWN: return 58;
|
||||
case SDLK_UP: return 59;
|
||||
case SDLK_DOWN: return 60;
|
||||
case SDLK_LEFT: return 61;
|
||||
case SDLK_RIGHT: return 62;
|
||||
case SDLK_LSHIFT: return 63;
|
||||
case SDLK_RSHIFT: return 64;
|
||||
case SDLK_LCTRL: return 65;
|
||||
case SDLK_RCTRL: return 66;
|
||||
case SDLK_LALT: return 67;
|
||||
case SDLK_RALT: return 68;
|
||||
case SDLK_CAPSLOCK: return 69;
|
||||
case SDLK_NUMLOCKCLEAR: return 70;
|
||||
case SDLK_SCROLLLOCK: return 71;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
|
||||
i32 EventConverter::mapMouseBtn(u8 btn) {
|
||||
switch (btn) {
|
||||
case SDL_BUTTON_LEFT: return 0;
|
||||
case SDL_BUTTON_RIGHT: return 1;
|
||||
case SDL_BUTTON_MIDDLE: return 2;
|
||||
case SDL_BUTTON_X1: return 3;
|
||||
case SDL_BUTTON_X2: return 4;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
|
||||
i32 EventConverter::mapGamepadBtn(u8 btn) {
|
||||
switch (btn) {
|
||||
case SDL_CONTROLLER_BUTTON_A: return 0;
|
||||
case SDL_CONTROLLER_BUTTON_B: return 1;
|
||||
case SDL_CONTROLLER_BUTTON_X: return 2;
|
||||
case SDL_CONTROLLER_BUTTON_Y: return 3;
|
||||
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: return 4;
|
||||
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: return 5;
|
||||
case SDL_CONTROLLER_BUTTON_LEFTSTICK: return 6;
|
||||
case SDL_CONTROLLER_BUTTON_RIGHTSTICK: return 7;
|
||||
case SDL_CONTROLLER_BUTTON_BACK: return 8;
|
||||
case SDL_CONTROLLER_BUTTON_START: return 9;
|
||||
case SDL_CONTROLLER_BUTTON_GUIDE: return 10;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_UP: return 11;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_DOWN: return 12;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_LEFT: return 13;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: return 14;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
|
||||
i32 EventConverter::mapGamepadAxis(u8 axis) {
|
||||
switch (axis) {
|
||||
case SDL_CONTROLLER_AXIS_LEFTX: return 0;
|
||||
case SDL_CONTROLLER_AXIS_LEFTY: return 1;
|
||||
case SDL_CONTROLLER_AXIS_RIGHTX: return 2;
|
||||
case SDL_CONTROLLER_AXIS_RIGHTY: return 3;
|
||||
case SDL_CONTROLLER_AXIS_TRIGGERLEFT: return 4;
|
||||
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: return 5;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace extra2d
|
||||
|
|
@ -61,28 +61,28 @@ void Window::destroy() {
|
|||
}
|
||||
}
|
||||
|
||||
void Window::pollEvents() {
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
switch (event.type) {
|
||||
case SDL_QUIT:
|
||||
void Window::poll() {
|
||||
SDL_Event e;
|
||||
while (SDL_PollEvent(&e)) {
|
||||
if (e.type == SDL_QUIT) {
|
||||
shouldClose_ = true;
|
||||
break;
|
||||
|
||||
case SDL_WINDOWEVENT:
|
||||
if (event.window.event == SDL_WINDOWEVENT_RESIZED ||
|
||||
event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
|
||||
width_ = event.window.data1;
|
||||
height_ = event.window.data2;
|
||||
} else if (e.type == SDL_WINDOWEVENT) {
|
||||
if (e.window.event == SDL_WINDOWEVENT_RESIZED ||
|
||||
e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
|
||||
width_ = e.window.data1;
|
||||
height_ = e.window.data2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (onEvent_) {
|
||||
onEvent_(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Window::shouldClose() const { return shouldClose_; }
|
||||
|
||||
void Window::setShouldClose(bool close) { shouldClose_ = close; }
|
||||
void Window::close() { shouldClose_ = true; }
|
||||
|
||||
void Window::setTitle(const std::string &title) {
|
||||
if (sdlWindow_) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue