feat(窗口/事件): 添加窗口事件处理并统一键盘映射
为 SDL2 和 GLFW 窗口后端添加完整的事件处理,包括窗口关闭、大小调整、键盘、鼠标等事件 添加键盘扫描码到引擎 Key 枚举的映射功能 优化相机服务,支持通过 Lambda 配置视口 统一日志输出语言为英文
This commit is contained in:
parent
e9bd44b63e
commit
b794221d49
|
|
@ -4,6 +4,7 @@
|
||||||
#include <extra2d/core/service_locator.h>
|
#include <extra2d/core/service_locator.h>
|
||||||
#include <extra2d/graphics/camera/camera.h>
|
#include <extra2d/graphics/camera/camera.h>
|
||||||
#include <extra2d/graphics/camera/viewport_adapter.h>
|
#include <extra2d/graphics/camera/viewport_adapter.h>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
|
@ -43,6 +44,13 @@ public:
|
||||||
virtual void lookAt(const Vec2& target) = 0;
|
virtual void lookAt(const Vec2& target) = 0;
|
||||||
|
|
||||||
virtual void setViewportConfig(const ViewportConfig& config) = 0;
|
virtual void setViewportConfig(const ViewportConfig& config) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 使用 Lambda 配置视口
|
||||||
|
* @param configFn 配置函数,接收 ViewportConfig 引用进行修改
|
||||||
|
*/
|
||||||
|
virtual void setViewportConfig(std::function<void(ViewportConfig&)> configFn) = 0;
|
||||||
|
|
||||||
virtual const ViewportConfig& getViewportConfig() const = 0;
|
virtual const ViewportConfig& getViewportConfig() const = 0;
|
||||||
virtual void updateViewport(int screenWidth, int screenHeight) = 0;
|
virtual void updateViewport(int screenWidth, int screenHeight) = 0;
|
||||||
virtual const ViewportResult& getViewportResult() const = 0;
|
virtual const ViewportResult& getViewportResult() const = 0;
|
||||||
|
|
@ -93,6 +101,7 @@ public:
|
||||||
void lookAt(const Vec2& target) override;
|
void lookAt(const Vec2& target) override;
|
||||||
|
|
||||||
void setViewportConfig(const ViewportConfig& config) override;
|
void setViewportConfig(const ViewportConfig& config) override;
|
||||||
|
void setViewportConfig(std::function<void(ViewportConfig&)> configFn) override;
|
||||||
const ViewportConfig& getViewportConfig() const override;
|
const ViewportConfig& getViewportConfig() const override;
|
||||||
void updateViewport(int screenWidth, int screenHeight) override;
|
void updateViewport(int screenWidth, int screenHeight) override;
|
||||||
const ViewportResult& getViewportResult() const override;
|
const ViewportResult& getViewportResult() const override;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
#include <extra2d/services/logger_service.h>
|
#include <extra2d/services/logger_service.h>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
@ -112,7 +111,7 @@ void ShaderHotReloader::update() {
|
||||||
*/
|
*/
|
||||||
void ShaderHotReloader::setEnabled(bool enabled) {
|
void ShaderHotReloader::setEnabled(bool enabled) {
|
||||||
enabled_ = enabled;
|
enabled_ = enabled;
|
||||||
E2D_LOG_DEBUG("热重载已{}", enabled ? "启用" : "禁用");
|
E2D_LOG_DEBUG("热重载已{}", enabled ? "Enable" : "Disable");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -98,8 +98,7 @@ bool ShaderManager::init(const std::string &shaderDir,
|
||||||
E2D_LOG_INFO("ShaderManager 初始化成功");
|
E2D_LOG_INFO("ShaderManager 初始化成功");
|
||||||
E2D_LOG_INFO(" 着色器目录: {}", shaderDir_);
|
E2D_LOG_INFO(" 着色器目录: {}", shaderDir_);
|
||||||
E2D_LOG_INFO(" 缓存目录: {}", cacheDir_);
|
E2D_LOG_INFO(" 缓存目录: {}", cacheDir_);
|
||||||
E2D_LOG_INFO(" 热重载: {}",
|
E2D_LOG_INFO(" 热重载: {}", hotReloadSupported_ ? "支持" : "不支持");
|
||||||
hotReloadSupported_ ? "支持" : "不支持");
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -157,8 +156,7 @@ Ptr<IShader> ShaderManager::loadFromFiles(const std::string &name,
|
||||||
loadFromCache(name, sourceHash, result.vertSource, result.fragSource);
|
loadFromCache(name, sourceHash, result.vertSource, result.fragSource);
|
||||||
|
|
||||||
if (!shader) {
|
if (!shader) {
|
||||||
E2D_LOG_DEBUG("未找到有效缓存,从源码编译着色器: {}",
|
E2D_LOG_DEBUG("未找到有效缓存,从源码编译着色器: {}", name);
|
||||||
name);
|
|
||||||
shader =
|
shader =
|
||||||
factory_->createFromSource(name, result.vertSource, result.fragSource);
|
factory_->createFromSource(name, result.vertSource, result.fragSource);
|
||||||
if (!shader) {
|
if (!shader) {
|
||||||
|
|
@ -394,7 +392,7 @@ void ShaderManager::setHotReloadEnabled(bool enabled) {
|
||||||
}
|
}
|
||||||
hotReloadEnabled_ = enabled;
|
hotReloadEnabled_ = enabled;
|
||||||
ShaderHotReloader::getInstance().setEnabled(enabled);
|
ShaderHotReloader::getInstance().setEnabled(enabled);
|
||||||
E2D_LOG_INFO("热重载已{}", enabled ? "启用" : "禁用");
|
E2D_LOG_INFO("热重载已{}", enabled ? "Enable" : "Disable");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -591,8 +589,7 @@ Ptr<IShader> ShaderManager::loadFromMetadata(const std::string &jsonPath,
|
||||||
|
|
||||||
auto &opengl = j["backends"]["opengl"];
|
auto &opengl = j["backends"]["opengl"];
|
||||||
if (!opengl.contains("vertex") || !opengl.contains("fragment")) {
|
if (!opengl.contains("vertex") || !opengl.contains("fragment")) {
|
||||||
E2D_LOG_ERROR("着色器元数据中缺少顶点或片段路径: {}",
|
E2D_LOG_ERROR("着色器元数据中缺少顶点或片段路径: {}", jsonPath);
|
||||||
jsonPath);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -603,8 +600,8 @@ Ptr<IShader> ShaderManager::loadFromMetadata(const std::string &jsonPath,
|
||||||
fs::path vertPath = fs::path(shaderDir_) / vertRelativePath;
|
fs::path vertPath = fs::path(shaderDir_) / vertRelativePath;
|
||||||
fs::path fragPath = fs::path(shaderDir_) / fragRelativePath;
|
fs::path fragPath = fs::path(shaderDir_) / fragRelativePath;
|
||||||
|
|
||||||
E2D_LOG_DEBUG("从元数据加载着色器: {} -> 顶点: {}, 片段: {}",
|
E2D_LOG_DEBUG("从元数据加载着色器: {} -> 顶点: {}, 片段: {}", name,
|
||||||
name, vertPath.string(), fragPath.string());
|
vertPath.string(), fragPath.string());
|
||||||
|
|
||||||
// 使用分离文件加载
|
// 使用分离文件加载
|
||||||
Ptr<IShader> shader =
|
Ptr<IShader> shader =
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
#include "glfw_window.h"
|
#include "glfw_window.h"
|
||||||
#include "glfw_input.h"
|
#include "glfw_input.h"
|
||||||
#include <extra2d/core/service_locator.h>
|
#include <extra2d/core/service_locator.h>
|
||||||
|
#include <extra2d/event/event.h>
|
||||||
|
#include <extra2d/platform/keys.h>
|
||||||
|
#include <extra2d/services/event_service.h>
|
||||||
#include <extra2d/services/logger_service.h>
|
#include <extra2d/services/logger_service.h>
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
|
@ -362,6 +365,13 @@ void GLFWWindow::framebufferSizeCallback(GLFWwindow *window, int width,
|
||||||
self->resizeCb_(width, height);
|
self->resizeCb_(width, height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 将事件推送到事件服务
|
||||||
|
auto eventService = ServiceLocator::instance().getService<IEventService>();
|
||||||
|
if (eventService) {
|
||||||
|
Event e = Event::createWindowResize(width, height);
|
||||||
|
eventService->pushEvent(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLFWWindow::windowCloseCallback(GLFWwindow *window) {
|
void GLFWWindow::windowCloseCallback(GLFWwindow *window) {
|
||||||
|
|
@ -373,6 +383,13 @@ void GLFWWindow::windowCloseCallback(GLFWwindow *window) {
|
||||||
self->closeCb_();
|
self->closeCb_();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 将事件推送到事件服务
|
||||||
|
auto eventService = ServiceLocator::instance().getService<IEventService>();
|
||||||
|
if (eventService) {
|
||||||
|
Event e = Event::createWindowClose();
|
||||||
|
eventService->pushEvent(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLFWWindow::windowFocusCallback(GLFWwindow *window, int focused) {
|
void GLFWWindow::windowFocusCallback(GLFWwindow *window, int focused) {
|
||||||
|
|
@ -401,6 +418,15 @@ void GLFWWindow::cursorPosCallback(GLFWwindow *window, double xpos,
|
||||||
if (self && self->input_) {
|
if (self && self->input_) {
|
||||||
self->input_->handleCursorPosEvent(xpos, ypos);
|
self->input_->handleCursorPosEvent(xpos, ypos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 将事件推送到事件服务
|
||||||
|
auto eventService = ServiceLocator::instance().getService<IEventService>();
|
||||||
|
if (eventService) {
|
||||||
|
Vec2 pos{static_cast<float>(xpos), static_cast<float>(ypos)};
|
||||||
|
Vec2 delta{0.0f, 0.0f}; // GLFW 回调中没有增量,需要在其他地方计算
|
||||||
|
Event e = Event::createMouseMove(pos, delta);
|
||||||
|
eventService->pushEvent(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLFWWindow::mouseButtonCallback(GLFWwindow *window, int button, int action,
|
void GLFWWindow::mouseButtonCallback(GLFWwindow *window, int button, int action,
|
||||||
|
|
@ -410,6 +436,22 @@ void GLFWWindow::mouseButtonCallback(GLFWwindow *window, int button, int action,
|
||||||
if (self && self->input_) {
|
if (self && self->input_) {
|
||||||
self->input_->handleMouseButtonEvent(button, action, mods);
|
self->input_->handleMouseButtonEvent(button, action, mods);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 将事件推送到事件服务
|
||||||
|
auto eventService = ServiceLocator::instance().getService<IEventService>();
|
||||||
|
if (eventService) {
|
||||||
|
double x, y;
|
||||||
|
glfwGetCursorPos(window, &x, &y);
|
||||||
|
Vec2 pos{static_cast<float>(x), static_cast<float>(y)};
|
||||||
|
|
||||||
|
if (action == GLFW_PRESS) {
|
||||||
|
Event e = Event::createMouseButtonPress(button, mods, pos);
|
||||||
|
eventService->pushEvent(e);
|
||||||
|
} else if (action == GLFW_RELEASE) {
|
||||||
|
Event e = Event::createMouseButtonRelease(button, mods, pos);
|
||||||
|
eventService->pushEvent(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLFWWindow::scrollCallback(GLFWwindow *window, double xoffset,
|
void GLFWWindow::scrollCallback(GLFWwindow *window, double xoffset,
|
||||||
|
|
@ -419,6 +461,17 @@ void GLFWWindow::scrollCallback(GLFWwindow *window, double xoffset,
|
||||||
if (self && self->input_) {
|
if (self && self->input_) {
|
||||||
self->input_->handleScrollEvent(xoffset, yoffset);
|
self->input_->handleScrollEvent(xoffset, yoffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 将事件推送到事件服务
|
||||||
|
auto eventService = ServiceLocator::instance().getService<IEventService>();
|
||||||
|
if (eventService) {
|
||||||
|
double x, y;
|
||||||
|
glfwGetCursorPos(window, &x, &y);
|
||||||
|
Vec2 offset{static_cast<float>(xoffset), static_cast<float>(yoffset)};
|
||||||
|
Vec2 pos{static_cast<float>(x), static_cast<float>(y)};
|
||||||
|
Event e = Event::createMouseScroll(offset, pos);
|
||||||
|
eventService->pushEvent(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLFWWindow::keyCallback(GLFWwindow *window, int key, int scancode,
|
void GLFWWindow::keyCallback(GLFWwindow *window, int key, int scancode,
|
||||||
|
|
@ -428,6 +481,99 @@ void GLFWWindow::keyCallback(GLFWwindow *window, int key, int scancode,
|
||||||
if (self && self->input_) {
|
if (self && self->input_) {
|
||||||
self->input_->handleKeyEvent(key, scancode, action, mods);
|
self->input_->handleKeyEvent(key, scancode, action, mods);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 将事件推送到事件服务
|
||||||
|
auto eventService = ServiceLocator::instance().getService<IEventService>();
|
||||||
|
if (eventService) {
|
||||||
|
// 将 GLFW key code 转换为引擎 Key 枚举值
|
||||||
|
Key eKey = Key::None;
|
||||||
|
switch (key) {
|
||||||
|
case GLFW_KEY_A: eKey = Key::A; break;
|
||||||
|
case GLFW_KEY_B: eKey = Key::B; break;
|
||||||
|
case GLFW_KEY_C: eKey = Key::C; break;
|
||||||
|
case GLFW_KEY_D: eKey = Key::D; break;
|
||||||
|
case GLFW_KEY_E: eKey = Key::E; break;
|
||||||
|
case GLFW_KEY_F: eKey = Key::F; break;
|
||||||
|
case GLFW_KEY_G: eKey = Key::G; break;
|
||||||
|
case GLFW_KEY_H: eKey = Key::H; break;
|
||||||
|
case GLFW_KEY_I: eKey = Key::I; break;
|
||||||
|
case GLFW_KEY_J: eKey = Key::J; break;
|
||||||
|
case GLFW_KEY_K: eKey = Key::K; break;
|
||||||
|
case GLFW_KEY_L: eKey = Key::L; break;
|
||||||
|
case GLFW_KEY_M: eKey = Key::M; break;
|
||||||
|
case GLFW_KEY_N: eKey = Key::N; break;
|
||||||
|
case GLFW_KEY_O: eKey = Key::O; break;
|
||||||
|
case GLFW_KEY_P: eKey = Key::P; break;
|
||||||
|
case GLFW_KEY_Q: eKey = Key::Q; break;
|
||||||
|
case GLFW_KEY_R: eKey = Key::R; break;
|
||||||
|
case GLFW_KEY_S: eKey = Key::S; break;
|
||||||
|
case GLFW_KEY_T: eKey = Key::T; break;
|
||||||
|
case GLFW_KEY_U: eKey = Key::U; break;
|
||||||
|
case GLFW_KEY_V: eKey = Key::V; break;
|
||||||
|
case GLFW_KEY_W: eKey = Key::W; break;
|
||||||
|
case GLFW_KEY_X: eKey = Key::X; break;
|
||||||
|
case GLFW_KEY_Y: eKey = Key::Y; break;
|
||||||
|
case GLFW_KEY_Z: eKey = Key::Z; break;
|
||||||
|
case GLFW_KEY_0: eKey = Key::Num0; break;
|
||||||
|
case GLFW_KEY_1: eKey = Key::Num1; break;
|
||||||
|
case GLFW_KEY_2: eKey = Key::Num2; break;
|
||||||
|
case GLFW_KEY_3: eKey = Key::Num3; break;
|
||||||
|
case GLFW_KEY_4: eKey = Key::Num4; break;
|
||||||
|
case GLFW_KEY_5: eKey = Key::Num5; break;
|
||||||
|
case GLFW_KEY_6: eKey = Key::Num6; break;
|
||||||
|
case GLFW_KEY_7: eKey = Key::Num7; break;
|
||||||
|
case GLFW_KEY_8: eKey = Key::Num8; break;
|
||||||
|
case GLFW_KEY_9: eKey = Key::Num9; break;
|
||||||
|
case GLFW_KEY_F1: eKey = Key::F1; break;
|
||||||
|
case GLFW_KEY_F2: eKey = Key::F2; break;
|
||||||
|
case GLFW_KEY_F3: eKey = Key::F3; break;
|
||||||
|
case GLFW_KEY_F4: eKey = Key::F4; break;
|
||||||
|
case GLFW_KEY_F5: eKey = Key::F5; break;
|
||||||
|
case GLFW_KEY_F6: eKey = Key::F6; break;
|
||||||
|
case GLFW_KEY_F7: eKey = Key::F7; break;
|
||||||
|
case GLFW_KEY_F8: eKey = Key::F8; break;
|
||||||
|
case GLFW_KEY_F9: eKey = Key::F9; break;
|
||||||
|
case GLFW_KEY_F10: eKey = Key::F10; break;
|
||||||
|
case GLFW_KEY_F11: eKey = Key::F11; break;
|
||||||
|
case GLFW_KEY_F12: eKey = Key::F12; break;
|
||||||
|
case GLFW_KEY_SPACE: eKey = Key::Space; break;
|
||||||
|
case GLFW_KEY_ENTER: eKey = Key::Enter; break;
|
||||||
|
case GLFW_KEY_ESCAPE: eKey = Key::Escape; break;
|
||||||
|
case GLFW_KEY_TAB: eKey = Key::Tab; break;
|
||||||
|
case GLFW_KEY_BACKSPACE: eKey = Key::Backspace; break;
|
||||||
|
case GLFW_KEY_INSERT: eKey = Key::Insert; break;
|
||||||
|
case GLFW_KEY_DELETE: eKey = Key::Delete; break;
|
||||||
|
case GLFW_KEY_HOME: eKey = Key::Home; break;
|
||||||
|
case GLFW_KEY_END: eKey = Key::End; break;
|
||||||
|
case GLFW_KEY_PAGE_UP: eKey = Key::PageUp; break;
|
||||||
|
case GLFW_KEY_PAGE_DOWN: eKey = Key::PageDown; break;
|
||||||
|
case GLFW_KEY_UP: eKey = Key::Up; break;
|
||||||
|
case GLFW_KEY_DOWN: eKey = Key::Down; break;
|
||||||
|
case GLFW_KEY_LEFT: eKey = Key::Left; break;
|
||||||
|
case GLFW_KEY_RIGHT: eKey = Key::Right; break;
|
||||||
|
case GLFW_KEY_LEFT_SHIFT: eKey = Key::LShift; break;
|
||||||
|
case GLFW_KEY_RIGHT_SHIFT: eKey = Key::RShift; break;
|
||||||
|
case GLFW_KEY_LEFT_CONTROL: eKey = Key::LCtrl; break;
|
||||||
|
case GLFW_KEY_RIGHT_CONTROL: eKey = Key::RCtrl; break;
|
||||||
|
case GLFW_KEY_LEFT_ALT: eKey = Key::LAlt; break;
|
||||||
|
case GLFW_KEY_RIGHT_ALT: eKey = Key::RAlt; break;
|
||||||
|
case GLFW_KEY_CAPS_LOCK: eKey = Key::CapsLock; break;
|
||||||
|
case GLFW_KEY_NUM_LOCK: eKey = Key::NumLock; break;
|
||||||
|
case GLFW_KEY_SCROLL_LOCK: eKey = Key::ScrollLock; break;
|
||||||
|
default: eKey = Key::None; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eKey != Key::None) {
|
||||||
|
int keyCode = static_cast<int>(eKey);
|
||||||
|
if (action == GLFW_PRESS) {
|
||||||
|
Event e = Event::createKeyPress(keyCode, scancode, mods);
|
||||||
|
eventService->pushEvent(e);
|
||||||
|
} else if (action == GLFW_RELEASE) {
|
||||||
|
Event e = Event::createKeyRelease(keyCode, scancode, mods);
|
||||||
|
eventService->pushEvent(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLFWWindow::joystickCallback(int jid, int event) {
|
void GLFWWindow::joystickCallback(int jid, int event) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
#include "sdl2_window.h"
|
#include "sdl2_window.h"
|
||||||
#include "sdl2_input.h"
|
#include "sdl2_input.h"
|
||||||
#include <extra2d/core/service_locator.h>
|
#include <extra2d/core/service_locator.h>
|
||||||
|
#include <extra2d/event/event.h>
|
||||||
|
#include <extra2d/platform/keys.h>
|
||||||
|
#include <extra2d/services/event_service.h>
|
||||||
#include <extra2d/services/logger_service.h>
|
#include <extra2d/services/logger_service.h>
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
|
@ -322,11 +325,18 @@ void SDL2Window::handleEvent(const SDL_Event &event) {
|
||||||
input_->handleSDLEvent(event);
|
input_->handleSDLEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 将事件推送到事件服务
|
||||||
|
auto eventService = ServiceLocator::instance().getService<IEventService>();
|
||||||
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case SDL_QUIT:
|
case SDL_QUIT:
|
||||||
shouldClose_ = true;
|
shouldClose_ = true;
|
||||||
if (closeCb_)
|
if (closeCb_)
|
||||||
closeCb_();
|
closeCb_();
|
||||||
|
if (eventService) {
|
||||||
|
Event e = Event::createWindowClose();
|
||||||
|
eventService->pushEvent(e);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_WINDOWEVENT:
|
case SDL_WINDOWEVENT:
|
||||||
|
|
@ -338,6 +348,10 @@ void SDL2Window::handleEvent(const SDL_Event &event) {
|
||||||
updateContentScale();
|
updateContentScale();
|
||||||
if (resizeCb_)
|
if (resizeCb_)
|
||||||
resizeCb_(width_, height_);
|
resizeCb_(width_, height_);
|
||||||
|
if (eventService) {
|
||||||
|
Event e = Event::createWindowResize(width_, height_);
|
||||||
|
eventService->pushEvent(e);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||||
|
|
@ -364,9 +378,237 @@ void SDL2Window::handleEvent(const SDL_Event &event) {
|
||||||
shouldClose_ = true;
|
shouldClose_ = true;
|
||||||
if (closeCb_)
|
if (closeCb_)
|
||||||
closeCb_();
|
closeCb_();
|
||||||
|
if (eventService) {
|
||||||
|
Event e = Event::createWindowClose();
|
||||||
|
eventService->pushEvent(e);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SDL_KEYDOWN: {
|
||||||
|
if (event.key.repeat == 0 && eventService) {
|
||||||
|
// 将 SDL scancode 转换为 Key 枚举
|
||||||
|
Key key = sdlScancodeToKey(event.key.keysym.scancode);
|
||||||
|
if (key != Key::None) {
|
||||||
|
int keyCode = static_cast<int>(key);
|
||||||
|
Event e = Event::createKeyPress(keyCode, event.key.keysym.scancode,
|
||||||
|
event.key.keysym.mod);
|
||||||
|
eventService->pushEvent(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SDL_KEYUP: {
|
||||||
|
if (eventService) {
|
||||||
|
Key key = sdlScancodeToKey(event.key.keysym.scancode);
|
||||||
|
if (key != Key::None) {
|
||||||
|
int keyCode = static_cast<int>(key);
|
||||||
|
Event e = Event::createKeyRelease(keyCode, event.key.keysym.scancode,
|
||||||
|
event.key.keysym.mod);
|
||||||
|
eventService->pushEvent(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SDL_MOUSEBUTTONDOWN: {
|
||||||
|
if (eventService) {
|
||||||
|
Vec2 pos{static_cast<float>(event.button.x),
|
||||||
|
static_cast<float>(event.button.y)};
|
||||||
|
Event e = Event::createMouseButtonPress(event.button.button - 1, 0, pos);
|
||||||
|
eventService->pushEvent(e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SDL_MOUSEBUTTONUP: {
|
||||||
|
if (eventService) {
|
||||||
|
Vec2 pos{static_cast<float>(event.button.x),
|
||||||
|
static_cast<float>(event.button.y)};
|
||||||
|
Event e =
|
||||||
|
Event::createMouseButtonRelease(event.button.button - 1, 0, pos);
|
||||||
|
eventService->pushEvent(e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SDL_MOUSEMOTION: {
|
||||||
|
if (eventService) {
|
||||||
|
Vec2 pos{static_cast<float>(event.motion.x),
|
||||||
|
static_cast<float>(event.motion.y)};
|
||||||
|
Vec2 delta{static_cast<float>(event.motion.xrel),
|
||||||
|
static_cast<float>(event.motion.yrel)};
|
||||||
|
Event e = Event::createMouseMove(pos, delta);
|
||||||
|
eventService->pushEvent(e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SDL_MOUSEWHEEL: {
|
||||||
|
if (eventService) {
|
||||||
|
int x, y;
|
||||||
|
SDL_GetMouseState(&x, &y);
|
||||||
|
Vec2 offset{static_cast<float>(event.wheel.x),
|
||||||
|
static_cast<float>(event.wheel.y)};
|
||||||
|
Vec2 pos{static_cast<float>(x), static_cast<float>(y)};
|
||||||
|
Event e = Event::createMouseScroll(offset, pos);
|
||||||
|
eventService->pushEvent(e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Key SDL2Window::sdlScancodeToKey(int scancode) {
|
||||||
|
switch (scancode) {
|
||||||
|
case SDL_SCANCODE_A:
|
||||||
|
return Key::A;
|
||||||
|
case SDL_SCANCODE_B:
|
||||||
|
return Key::B;
|
||||||
|
case SDL_SCANCODE_C:
|
||||||
|
return Key::C;
|
||||||
|
case SDL_SCANCODE_D:
|
||||||
|
return Key::D;
|
||||||
|
case SDL_SCANCODE_E:
|
||||||
|
return Key::E;
|
||||||
|
case SDL_SCANCODE_F:
|
||||||
|
return Key::F;
|
||||||
|
case SDL_SCANCODE_G:
|
||||||
|
return Key::G;
|
||||||
|
case SDL_SCANCODE_H:
|
||||||
|
return Key::H;
|
||||||
|
case SDL_SCANCODE_I:
|
||||||
|
return Key::I;
|
||||||
|
case SDL_SCANCODE_J:
|
||||||
|
return Key::J;
|
||||||
|
case SDL_SCANCODE_K:
|
||||||
|
return Key::K;
|
||||||
|
case SDL_SCANCODE_L:
|
||||||
|
return Key::L;
|
||||||
|
case SDL_SCANCODE_M:
|
||||||
|
return Key::M;
|
||||||
|
case SDL_SCANCODE_N:
|
||||||
|
return Key::N;
|
||||||
|
case SDL_SCANCODE_O:
|
||||||
|
return Key::O;
|
||||||
|
case SDL_SCANCODE_P:
|
||||||
|
return Key::P;
|
||||||
|
case SDL_SCANCODE_Q:
|
||||||
|
return Key::Q;
|
||||||
|
case SDL_SCANCODE_R:
|
||||||
|
return Key::R;
|
||||||
|
case SDL_SCANCODE_S:
|
||||||
|
return Key::S;
|
||||||
|
case SDL_SCANCODE_T:
|
||||||
|
return Key::T;
|
||||||
|
case SDL_SCANCODE_U:
|
||||||
|
return Key::U;
|
||||||
|
case SDL_SCANCODE_V:
|
||||||
|
return Key::V;
|
||||||
|
case SDL_SCANCODE_W:
|
||||||
|
return Key::W;
|
||||||
|
case SDL_SCANCODE_X:
|
||||||
|
return Key::X;
|
||||||
|
case SDL_SCANCODE_Y:
|
||||||
|
return Key::Y;
|
||||||
|
case SDL_SCANCODE_Z:
|
||||||
|
return Key::Z;
|
||||||
|
case SDL_SCANCODE_0:
|
||||||
|
return Key::Num0;
|
||||||
|
case SDL_SCANCODE_1:
|
||||||
|
return Key::Num1;
|
||||||
|
case SDL_SCANCODE_2:
|
||||||
|
return Key::Num2;
|
||||||
|
case SDL_SCANCODE_3:
|
||||||
|
return Key::Num3;
|
||||||
|
case SDL_SCANCODE_4:
|
||||||
|
return Key::Num4;
|
||||||
|
case SDL_SCANCODE_5:
|
||||||
|
return Key::Num5;
|
||||||
|
case SDL_SCANCODE_6:
|
||||||
|
return Key::Num6;
|
||||||
|
case SDL_SCANCODE_7:
|
||||||
|
return Key::Num7;
|
||||||
|
case SDL_SCANCODE_8:
|
||||||
|
return Key::Num8;
|
||||||
|
case SDL_SCANCODE_9:
|
||||||
|
return Key::Num9;
|
||||||
|
case SDL_SCANCODE_F1:
|
||||||
|
return Key::F1;
|
||||||
|
case SDL_SCANCODE_F2:
|
||||||
|
return Key::F2;
|
||||||
|
case SDL_SCANCODE_F3:
|
||||||
|
return Key::F3;
|
||||||
|
case SDL_SCANCODE_F4:
|
||||||
|
return Key::F4;
|
||||||
|
case SDL_SCANCODE_F5:
|
||||||
|
return Key::F5;
|
||||||
|
case SDL_SCANCODE_F6:
|
||||||
|
return Key::F6;
|
||||||
|
case SDL_SCANCODE_F7:
|
||||||
|
return Key::F7;
|
||||||
|
case SDL_SCANCODE_F8:
|
||||||
|
return Key::F8;
|
||||||
|
case SDL_SCANCODE_F9:
|
||||||
|
return Key::F9;
|
||||||
|
case SDL_SCANCODE_F10:
|
||||||
|
return Key::F10;
|
||||||
|
case SDL_SCANCODE_F11:
|
||||||
|
return Key::F11;
|
||||||
|
case SDL_SCANCODE_F12:
|
||||||
|
return Key::F12;
|
||||||
|
case SDL_SCANCODE_SPACE:
|
||||||
|
return Key::Space;
|
||||||
|
case SDL_SCANCODE_RETURN:
|
||||||
|
return Key::Enter;
|
||||||
|
case SDL_SCANCODE_ESCAPE:
|
||||||
|
return Key::Escape;
|
||||||
|
case SDL_SCANCODE_TAB:
|
||||||
|
return Key::Tab;
|
||||||
|
case SDL_SCANCODE_BACKSPACE:
|
||||||
|
return Key::Backspace;
|
||||||
|
case SDL_SCANCODE_INSERT:
|
||||||
|
return Key::Insert;
|
||||||
|
case SDL_SCANCODE_DELETE:
|
||||||
|
return Key::Delete;
|
||||||
|
case SDL_SCANCODE_HOME:
|
||||||
|
return Key::Home;
|
||||||
|
case SDL_SCANCODE_END:
|
||||||
|
return Key::End;
|
||||||
|
case SDL_SCANCODE_PAGEUP:
|
||||||
|
return Key::PageUp;
|
||||||
|
case SDL_SCANCODE_PAGEDOWN:
|
||||||
|
return Key::PageDown;
|
||||||
|
case SDL_SCANCODE_UP:
|
||||||
|
return Key::Up;
|
||||||
|
case SDL_SCANCODE_DOWN:
|
||||||
|
return Key::Down;
|
||||||
|
case SDL_SCANCODE_LEFT:
|
||||||
|
return Key::Left;
|
||||||
|
case SDL_SCANCODE_RIGHT:
|
||||||
|
return Key::Right;
|
||||||
|
case SDL_SCANCODE_LSHIFT:
|
||||||
|
return Key::LShift;
|
||||||
|
case SDL_SCANCODE_RSHIFT:
|
||||||
|
return Key::RShift;
|
||||||
|
case SDL_SCANCODE_LCTRL:
|
||||||
|
return Key::LCtrl;
|
||||||
|
case SDL_SCANCODE_RCTRL:
|
||||||
|
return Key::RCtrl;
|
||||||
|
case SDL_SCANCODE_LALT:
|
||||||
|
return Key::LAlt;
|
||||||
|
case SDL_SCANCODE_RALT:
|
||||||
|
return Key::RAlt;
|
||||||
|
case SDL_SCANCODE_CAPSLOCK:
|
||||||
|
return Key::CapsLock;
|
||||||
|
case SDL_SCANCODE_NUMLOCKCLEAR:
|
||||||
|
return Key::NumLock;
|
||||||
|
case SDL_SCANCODE_SCROLLLOCK:
|
||||||
|
return Key::ScrollLock;
|
||||||
|
default:
|
||||||
|
return Key::None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <extra2d/platform/iwindow.h>
|
#include <extra2d/platform/iwindow.h>
|
||||||
|
#include <extra2d/platform/keys.h>
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
@ -71,6 +72,7 @@ private:
|
||||||
void deinitCursors();
|
void deinitCursors();
|
||||||
void updateContentScale();
|
void updateContentScale();
|
||||||
void handleEvent(const SDL_Event& event);
|
void handleEvent(const SDL_Event& event);
|
||||||
|
Key sdlScancodeToKey(int scancode);
|
||||||
|
|
||||||
SDL_Window* sdlWindow_ = nullptr;
|
SDL_Window* sdlWindow_ = nullptr;
|
||||||
SDL_GLContext glContext_ = nullptr;
|
SDL_GLContext glContext_ = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,12 @@ void CameraService::setViewportConfig(const ViewportConfig &config) {
|
||||||
viewportAdapter_.setConfig(config);
|
viewportAdapter_.setConfig(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CameraService::setViewportConfig(std::function<void(ViewportConfig&)> configFn) {
|
||||||
|
ViewportConfig config = viewportAdapter_.getConfig();
|
||||||
|
configFn(config);
|
||||||
|
viewportAdapter_.setConfig(config);
|
||||||
|
}
|
||||||
|
|
||||||
const ViewportConfig &CameraService::getViewportConfig() const {
|
const ViewportConfig &CameraService::getViewportConfig() const {
|
||||||
return viewportAdapter_.getConfig();
|
return viewportAdapter_.getConfig();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@
|
||||||
* 此示例不依赖任何特定渲染后端(如 OpenGL)
|
* 此示例不依赖任何特定渲染后端(如 OpenGL)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "extra2d/core/service_interface.h"
|
||||||
|
#include "extra2d/core/service_locator.h"
|
||||||
#include <extra2d/extra2d.h>
|
#include <extra2d/extra2d.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
@ -97,28 +99,24 @@ int main(int argc, char *argv[]) {
|
||||||
app.use<WindowModule>([](auto &cfg) {
|
app.use<WindowModule>([](auto &cfg) {
|
||||||
cfg.w = 1280;
|
cfg.w = 1280;
|
||||||
cfg.h = 720;
|
cfg.h = 720;
|
||||||
cfg.title = "Extra2D Image Display Demo";
|
cfg.title = "Extra2D 图片显示示例";
|
||||||
cfg.priority = 0;
|
cfg.priority = 0;
|
||||||
cfg.backend = "glfw";
|
cfg.backend = "sdl2";
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use<RenderModule>([](auto &cfg) { cfg.priority = 10; });
|
app.use<RenderModule>([](auto &cfg) {
|
||||||
|
cfg.priority = 10;
|
||||||
|
cfg.backend = "opengl";
|
||||||
|
});
|
||||||
|
|
||||||
app.use<InputModule>([](auto &cfg) { cfg.priority = 20; });
|
app.use<InputModule>([](auto &cfg) { cfg.priority = 20; });
|
||||||
|
|
||||||
std::cout << "Initializing application..." << std::endl;
|
|
||||||
if (!app.init()) {
|
if (!app.init()) {
|
||||||
std::cerr << "Failed to initialize application!" << std::endl;
|
std::cerr << "Failed to initialize application!" << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Application initialized successfully!" << std::endl;
|
auto win = app.window();
|
||||||
|
|
||||||
auto *win = app.window();
|
|
||||||
if (win) {
|
|
||||||
std::cout << "Window: " << win->width() << "x" << win->height()
|
|
||||||
<< std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置事件监听
|
// 设置事件监听
|
||||||
auto eventService = ServiceLocator::instance().getService<IEventService>();
|
auto eventService = ServiceLocator::instance().getService<IEventService>();
|
||||||
|
|
@ -148,26 +146,20 @@ int main(int argc, char *argv[]) {
|
||||||
// 配置相机
|
// 配置相机
|
||||||
auto cameraService = ServiceLocator::instance().getService<ICameraService>();
|
auto cameraService = ServiceLocator::instance().getService<ICameraService>();
|
||||||
if (cameraService && win) {
|
if (cameraService && win) {
|
||||||
ViewportConfig vpConfig;
|
cameraService->setViewportConfig([&](auto &cfg) {
|
||||||
vpConfig.logicWidth = static_cast<float>(win->width());
|
cfg.logicWidth = static_cast<float>(win->width());
|
||||||
vpConfig.logicHeight = static_cast<float>(win->height());
|
cfg.logicHeight = static_cast<float>(win->height());
|
||||||
vpConfig.mode = ViewportMode::AspectRatio;
|
cfg.mode = ViewportMode::AspectRatio;
|
||||||
cameraService->setViewportConfig(vpConfig);
|
});
|
||||||
cameraService->updateViewport(win->width(), win->height());
|
cameraService->updateViewport(win->width(), win->height());
|
||||||
cameraService->applyViewportAdapter();
|
cameraService->applyViewportAdapter();
|
||||||
}
|
}
|
||||||
|
|
||||||
app.enterScene(scene);
|
app.enterScene(scene);
|
||||||
|
|
||||||
std::cout << "\nControls:" << std::endl;
|
|
||||||
std::cout << " ESC - Exit" << std::endl;
|
|
||||||
std::cout << "\nRunning main loop...\n" << std::endl;
|
|
||||||
|
|
||||||
app.run();
|
app.run();
|
||||||
|
|
||||||
std::cout << "Shutting down..." << std::endl;
|
|
||||||
app.shutdown();
|
app.shutdown();
|
||||||
|
|
||||||
std::cout << "Goodbye!" << std::endl;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue