From 137369c37c5caf08c01fe1d8c1577888c04abd6e Mon Sep 17 00:00:00 2001 From: ChestnutYueyue <952134128@qq.com> Date: Mon, 23 Feb 2026 03:13:00 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E4=BA=8B=E4=BB=B6=E7=B3=BB=E7=BB=9F):=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0SDL=E4=BA=8B=E4=BB=B6=E8=BD=AC=E6=8D=A2?= =?UTF-8?q?=E5=99=A8=E5=B9=B6=E9=87=8D=E6=9E=84=E7=AA=97=E5=8F=A3=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加EventConverter类用于将SDL事件转换为引擎内部事件格式 重构Window类的事件处理逻辑,支持通过回调函数处理转换后的事件 修改Application类以使用新的事件系统 --- Extra2D/include/extra2d/event/event.h | 1 - .../include/extra2d/window/event_converter.h | 31 +++ Extra2D/include/extra2d/window/window.h | 18 +- Extra2D/src/app/application.cpp | 17 +- Extra2D/src/window/event_converter.cpp | 225 ++++++++++++++++++ Extra2D/src/window/window.cpp | 28 +-- 6 files changed, 297 insertions(+), 23 deletions(-) create mode 100644 Extra2D/include/extra2d/window/event_converter.h create mode 100644 Extra2D/src/window/event_converter.cpp diff --git a/Extra2D/include/extra2d/event/event.h b/Extra2D/include/extra2d/event/event.h index 92e00a6..0783c3d 100644 --- a/Extra2D/include/extra2d/event/event.h +++ b/Extra2D/include/extra2d/event/event.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include diff --git a/Extra2D/include/extra2d/window/event_converter.h b/Extra2D/include/extra2d/window/event_converter.h new file mode 100644 index 0000000..6437584 --- /dev/null +++ b/Extra2D/include/extra2d/window/event_converter.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +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 diff --git a/Extra2D/include/extra2d/window/window.h b/Extra2D/include/extra2d/window/window.h index d6bae4f..6236a3b 100644 --- a/Extra2D/include/extra2d/window/window.h +++ b/Extra2D/include/extra2d/window/window.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -18,25 +19,29 @@ struct WindowConfig { class Window { public: + using OnEvent = std::function; + 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 diff --git a/Extra2D/src/app/application.cpp b/Extra2D/src/app/application.cpp index 2c7ee19..f2f8622 100644 --- a/Extra2D/src/app/application.cpp +++ b/Extra2D/src/app/application.cpp @@ -1,6 +1,8 @@ #include #include +#include #include +#include #include #include @@ -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(); + 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(); } diff --git a/Extra2D/src/window/event_converter.cpp b/Extra2D/src/window/event_converter.cpp new file mode 100644 index 0000000..574e49e --- /dev/null +++ b/Extra2D/src/window/event_converter.cpp @@ -0,0 +1,225 @@ +#include + +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(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(e.x), static_cast(e.y)}}; + return event; +} + +Event EventConverter::convertMouseMove(const SDL_MouseMotionEvent& e) { + Event event; + event.type = EventType::MouseMoved; + event.data = MouseMoveEvent{Vec2{static_cast(e.x), static_cast(e.y)}, Vec2{static_cast(e.xrel), static_cast(e.yrel)}}; + return event; +} + +Event EventConverter::convertMouseWheel(const SDL_MouseWheelEvent& e) { + Event event; + event.type = EventType::MouseScrolled; + event.data = MouseScrollEvent{Vec2{static_cast(e.x), static_cast(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(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(e.which), mapGamepadAxis(e.axis), static_cast(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(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 diff --git a/Extra2D/src/window/window.cpp b/Extra2D/src/window/window.cpp index df32381..02b3e74 100644 --- a/Extra2D/src/window/window.cpp +++ b/Extra2D/src/window/window.cpp @@ -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_) {