diff --git a/Extra2D/include/extra2d/app/application.h b/Extra2D/include/extra2d/app/application.h index 2e11d4d..1ea91d9 100644 --- a/Extra2D/include/extra2d/app/application.h +++ b/Extra2D/include/extra2d/app/application.h @@ -22,10 +22,10 @@ class InputModule; class Application { public: static Application& get(); - + Application(const Application&) = delete; Application& operator=(const Application&) = delete; - + /** * @brief 注册模块 * @tparam T 模块类型 diff --git a/Extra2D/include/extra2d/graphics/core/render_module.h b/Extra2D/include/extra2d/graphics/core/render_module.h index bb848bf..cee6bdd 100644 --- a/Extra2D/include/extra2d/graphics/core/render_module.h +++ b/Extra2D/include/extra2d/graphics/core/render_module.h @@ -3,10 +3,30 @@ #include #include #include +#include #include namespace extra2d { +/** + * @brief 渲染模块配置结构 + */ +struct RenderCfg { + BackendType backend; + int targetFPS; + bool vsync; + int multisamples; + int priority; + + RenderCfg() + : backend(BackendType::OpenGL) + , targetFPS(60) + , vsync(true) + , multisamples(0) + , priority(10) + {} +}; + /** * @brief 渲染模块 * 管理渲染后端 @@ -14,41 +34,22 @@ namespace extra2d { class RenderModule : public Module { public: /** - * @brief 配置结构 + * @brief 构造函数(Lambda 配置) + * @param configFn 配置函数 */ - struct Cfg { - BackendType backend; - int targetFPS; - bool vsync; - int multisamples; - int priority; - - Cfg() - : backend(BackendType::OpenGL) - , targetFPS(60) - , vsync(true) - , multisamples(0) - , priority(10) - {} - }; - - /** - * @brief 构造函数 - * @param cfg 配置 - */ - explicit RenderModule(const Cfg& cfg = Cfg{}); - + explicit RenderModule(std::function configFn); + /** * @brief 析构函数 */ ~RenderModule() override; - + bool init() override; void shutdown() override; bool ok() const override { return initialized_; } const char* name() const override { return "render"; } int priority() const override { return cfg_.priority; } - + /** * @brief 获取依赖 * @return 依赖模块类型列表 @@ -56,7 +57,7 @@ public: std::vector deps() const override { return {std::type_index(typeid(WindowModule))}; } - + /** * @brief 获取渲染器 * @return 渲染后端指针 @@ -64,7 +65,7 @@ public: RenderBackend* renderer() const { return renderer_.get(); } private: - Cfg cfg_; + RenderCfg cfg_; UniquePtr renderer_; bool initialized_ = false; }; diff --git a/Extra2D/include/extra2d/platform/input_module.h b/Extra2D/include/extra2d/platform/input_module.h index cbba615..2cdbc4b 100644 --- a/Extra2D/include/extra2d/platform/input_module.h +++ b/Extra2D/include/extra2d/platform/input_module.h @@ -3,10 +3,30 @@ #include #include #include +#include #include namespace extra2d { +/** + * @brief 输入模块配置结构 + */ +struct InputCfg { + float deadzone; + float mouseSensitivity; + bool enableVibration; + int maxGamepads; + int priority; + + InputCfg() + : deadzone(0.15f) + , mouseSensitivity(1.0f) + , enableVibration(true) + , maxGamepads(4) + , priority(20) + {} +}; + /** * @brief 输入模块 * 管理输入设备 @@ -14,41 +34,22 @@ namespace extra2d { class InputModule : public Module { public: /** - * @brief 配置结构 + * @brief 构造函数(Lambda 配置) + * @param configFn 配置函数 */ - struct Cfg { - float deadzone; - float mouseSensitivity; - bool enableVibration; - int maxGamepads; - int priority; - - Cfg() - : deadzone(0.15f) - , mouseSensitivity(1.0f) - , enableVibration(true) - , maxGamepads(4) - , priority(20) - {} - }; - - /** - * @brief 构造函数 - * @param cfg 配置 - */ - explicit InputModule(const Cfg& cfg = Cfg{}); - + explicit InputModule(std::function configFn); + /** * @brief 析构函数 */ ~InputModule() override; - + bool init() override; void shutdown() override; bool ok() const override { return initialized_; } const char* name() const override { return "input"; } int priority() const override { return cfg_.priority; } - + /** * @brief 获取依赖 * @return 依赖模块类型列表 @@ -56,20 +57,20 @@ public: std::vector deps() const override { return {std::type_index(typeid(WindowModule))}; } - + /** * @brief 获取输入接口 * @return 输入接口指针 */ IInput* input() const { return input_; } - + /** * @brief 更新输入状态 */ void update(); private: - Cfg cfg_; + InputCfg cfg_; IInput* input_ = nullptr; bool initialized_ = false; }; diff --git a/Extra2D/include/extra2d/platform/window_module.h b/Extra2D/include/extra2d/platform/window_module.h index ed5f69b..bb952bd 100644 --- a/Extra2D/include/extra2d/platform/window_module.h +++ b/Extra2D/include/extra2d/platform/window_module.h @@ -1,67 +1,64 @@ #pragma once #include -#include #include +#include +#include +#include namespace extra2d { +/** + * @brief 窗口模块配置结构 + */ +struct WindowCfg { + std::string title; + int w; + int h; + WindowMode mode; + bool vsync; + int priority; + std::string backend; + + WindowCfg() + : title("Extra2D"), w(1280), h(720), mode(WindowMode::Windowed), + vsync(true), priority(0), backend("sdl2") {} +}; + /** * @brief 窗口模块 * 管理窗口创建和生命周期 */ class WindowModule : public Module { public: - /** - * @brief 配置结构 - */ - struct Cfg { - std::string title; - int w; - int h; - WindowMode mode; - bool vsync; - int priority; - std::string backend; - - Cfg() - : title("Extra2D") - , w(1280) - , h(720) - , mode(WindowMode::Windowed) - , vsync(true) - , priority(0) - , backend("sdl2") {} - }; - - /** - * @brief 构造函数 - * @param cfg 配置 - */ - explicit WindowModule(const Cfg& cfg = Cfg()); - - /** - * @brief 析构函数 - */ - ~WindowModule() override; - - bool init() override; - void shutdown() override; - bool ok() const override { return initialized_; } - const char* name() const override { return "window"; } - int priority() const override { return cfg_.priority; } - - /** - * @brief 获取窗口 - * @return 窗口指针 - */ - IWindow* win() const { return win_.get(); } + /** + * @brief 构造函数(Lambda 配置) + * @param configFn 配置函数 + */ + explicit WindowModule(std::function configFn); + + /** + * @brief 析构函数 + */ + ~WindowModule() override; + + bool init() override; + void shutdown() override; + bool ok() const override { return initialized_; } + const char *name() const override { return "window"; } + int priority() const override { return cfg_.priority; } + + /** + * @brief 获取窗口 + * @return 窗口指针 + */ + IWindow *win() const { return win_.get(); } private: - Cfg cfg_; - UniquePtr win_; - bool initialized_ = false; - bool sdlInited_ = false; + WindowCfg cfg_; + UniquePtr win_; + bool initialized_ = false; + bool sdlInited_ = false; }; } // namespace extra2d diff --git a/Extra2D/src/graphics/core/render_module.cpp b/Extra2D/src/graphics/core/render_module.cpp index 4e5826e..7d3b19a 100644 --- a/Extra2D/src/graphics/core/render_module.cpp +++ b/Extra2D/src/graphics/core/render_module.cpp @@ -11,7 +11,9 @@ namespace extra2d { -RenderModule::RenderModule(const Cfg& cfg) : cfg_(cfg) {} +RenderModule::RenderModule(std::function configFn) { + configFn(cfg_); +} RenderModule::~RenderModule() { if (initialized_) { diff --git a/Extra2D/src/platform/backends/glfw/glfw_window.cpp b/Extra2D/src/platform/backends/glfw/glfw_window.cpp index 44f01b3..de95e3e 100644 --- a/Extra2D/src/platform/backends/glfw/glfw_window.cpp +++ b/Extra2D/src/platform/backends/glfw/glfw_window.cpp @@ -74,6 +74,23 @@ bool GLFWWindow::create(const WindowConfigData& cfg) { return false; } + // 窗口居中(非全屏模式下) +#ifndef __SWITCH__ + if (!fullscreen_ && !monitor) { + GLFWmonitor* primaryMonitor = glfwGetPrimaryMonitor(); + if (primaryMonitor) { + const GLFWvidmode* mode = glfwGetVideoMode(primaryMonitor); + if (mode) { + int screenWidth = mode->width; + int screenHeight = mode->height; + int windowX = (screenWidth - cfg.width) / 2; + int windowY = (screenHeight - cfg.height) / 2; + glfwSetWindowPos(glfwWindow_, windowX, windowY); + } + } + } +#endif + glfwMakeContextCurrent(glfwWindow_); // 初始化 GLAD diff --git a/Extra2D/src/platform/input_module.cpp b/Extra2D/src/platform/input_module.cpp index db46bf1..4a3bceb 100644 --- a/Extra2D/src/platform/input_module.cpp +++ b/Extra2D/src/platform/input_module.cpp @@ -6,7 +6,9 @@ namespace extra2d { -InputModule::InputModule(const Cfg& cfg) : cfg_(cfg) {} +InputModule::InputModule(std::function configFn) { + configFn(cfg_); +} InputModule::~InputModule() { if (initialized_) { diff --git a/Extra2D/src/platform/window_module.cpp b/Extra2D/src/platform/window_module.cpp index 7c8a23f..b9645c7 100644 --- a/Extra2D/src/platform/window_module.cpp +++ b/Extra2D/src/platform/window_module.cpp @@ -16,7 +16,9 @@ void initSDL2Backend(); void initGLFWBackend(); #endif -WindowModule::WindowModule(const Cfg& cfg) : cfg_(cfg) {} +WindowModule::WindowModule(std::function configFn) { + configFn(cfg_); +} WindowModule::~WindowModule() { if (initialized_) { diff --git a/docs/module_system.md b/docs/module_system.md index f79b3a4..31a3e4d 100644 --- a/docs/module_system.md +++ b/docs/module_system.md @@ -462,13 +462,14 @@ if (caps.supportsGamepad) { **配置**: ```cpp -WindowModule::Cfg cfg; -cfg.title = "My App"; -cfg.w = 1280; -cfg.h = 720; -cfg.mode = WindowMode::Windowed; -cfg.vsync = true; -cfg.backend = "sdl2"; // 可选:"sdl2" 或 "glfw" +app.use([](auto& cfg) { + cfg.title = "My App"; + cfg.w = 1280; + cfg.h = 720; + cfg.mode = WindowMode::Windowed; + cfg.vsync = true; + cfg.backend = "sdl2"; // 可选:"sdl2" 或 "glfw" +}); ``` **构建时选择后端**: @@ -491,10 +492,11 @@ xmake f --window_backend=glfw -y **配置**: ```cpp -InputModule::Cfg cfg; -cfg.deadzone = 0.15f; -cfg.mouseSensitivity = 1.0f; -cfg.enableVibration = true; +app.use([](auto& cfg) { + cfg.deadzone = 0.15f; + cfg.mouseSensitivity = 1.0f; + cfg.enableVibration = true; +}); ``` **使用示例**: @@ -528,11 +530,12 @@ if (input->gamepad()) { **配置**: ```cpp -RenderModule::Cfg cfg; -cfg.backend = BackendType::OpenGL; -cfg.vsync = true; -cfg.targetFPS = 60; -cfg.multisamples = 4; +app.use([](auto& cfg) { + cfg.backend = BackendType::OpenGL; + cfg.vsync = true; + cfg.targetFPS = 60; + cfg.multisamples = 4; +}); ``` --- @@ -723,20 +726,31 @@ if (caps.supportsTouch) { /* 支持触摸 */ } ### 1. 模块配置独立化 ```cpp -// 好的做法:模块管理自己的配置 -class WindowModule : public Module { - Cfg cfg_; // 模块内部配置 -public: - struct Cfg { - std::string title = "Extra2D"; - int w = 1280; - int h = 720; - WindowMode mode = WindowMode::Windowed; - bool vsync = true; - int priority = 0; - }; +// 好的做法:模块管理自己的配置,使用 Lambda 配置 +struct WindowCfg { + std::string title = "Extra2D"; + int w = 1280; + int h = 720; + WindowMode mode = WindowMode::Windowed; + bool vsync = true; + int priority = 0; }; +class WindowModule : public Module { + WindowCfg cfg_; // 模块内部配置 +public: + explicit WindowModule(std::function configFn) { + configFn(cfg_); + } +}; + +// 使用 Lambda 配置模块 +app.use([](auto& cfg) { + cfg.w = 1920; + cfg.h = 1080; + cfg.backend = "glfw"; +}); + // 不好的做法:所有配置放在 AppConfig struct AppConfig { WindowConfig window; // 耦合度高 diff --git a/examples/basic/main.cpp b/examples/basic/main.cpp index ed5b72e..84b2dd7 100644 --- a/examples/basic/main.cpp +++ b/examples/basic/main.cpp @@ -12,7 +12,6 @@ #include #include - using namespace extra2d; void createSceneGraph(Scene *scene) { @@ -103,20 +102,16 @@ int main(int argc, char *argv[]) { Application &app = Application::get(); // 注册模块(按优先级顺序) - WindowModule::Cfg winCfg; - winCfg.w = 1280; - winCfg.h = 720; - winCfg.priority = 0; - winCfg.backend = "glfw"; - app.use(winCfg); + app.use([](auto &cfg) { + cfg.w = 1280; + cfg.h = 720; + cfg.priority = 0; + cfg.backend = "glfw"; + }); - RenderModule::Cfg renderCfg; - renderCfg.priority = 10; - app.use(renderCfg); + app.use([](auto &cfg) { cfg.priority = 10; }); - InputModule::Cfg inputCfg; - inputCfg.priority = 20; - app.use(inputCfg); + app.use([](auto &cfg) { cfg.priority = 20; }); std::cout << "Initializing application..." << std::endl; if (!app.init()) { diff --git a/examples/hello_module/hello_module.cpp b/examples/hello_module/hello_module.cpp index 6bb6172..3ddb514 100644 --- a/examples/hello_module/hello_module.cpp +++ b/examples/hello_module/hello_module.cpp @@ -3,7 +3,11 @@ namespace extra2d { -HelloModule::HelloModule(const Cfg& cfg) : cfg_(cfg) {} +HelloModule::HelloModule(const HelloCfg& cfg) : cfg_(cfg) {} + +HelloModule::HelloModule(std::function configFn) { + configFn(cfg_); +} HelloModule::~HelloModule() { if (initialized_) { diff --git a/examples/hello_module/hello_module.h b/examples/hello_module/hello_module.h index 253e910..abe1353 100644 --- a/examples/hello_module/hello_module.h +++ b/examples/hello_module/hello_module.h @@ -2,9 +2,24 @@ #include #include +#include namespace extra2d { +/** + * @brief Hello模块配置结构 + */ +struct HelloCfg { + std::string greeting; + int repeatCount; + int priority; + + HelloCfg() + : greeting("Hello, Extra2D!") + , repeatCount(1) + , priority(100) {} +}; + /** * @brief Hello模块示例 * 展示如何创建自定义模块 @@ -12,19 +27,21 @@ namespace extra2d { class HelloModule : public Module { public: /** - * @brief 配置结构 + * @brief 配置类型别名(向后兼容) */ - struct Cfg { - std::string greeting = "Hello, Extra2D!"; - int repeatCount = 1; - int priority = 100; - }; - + using Cfg = HelloCfg; + /** * @brief 构造函数 * @param cfg 配置 */ - explicit HelloModule(const Cfg& cfg = Cfg{}); + explicit HelloModule(const HelloCfg& cfg = HelloCfg{}); + + /** + * @brief 构造函数(Lambda 配置) + * @param configFn 配置函数 + */ + explicit HelloModule(std::function configFn); /** * @brief 析构函数 @@ -43,7 +60,7 @@ public: void sayHello() const; private: - Cfg cfg_; + HelloCfg cfg_; bool initialized_ = false; }; diff --git a/examples/hello_module/main.cpp b/examples/hello_module/main.cpp index 8d1a649..0dea10b 100644 --- a/examples/hello_module/main.cpp +++ b/examples/hello_module/main.cpp @@ -1,11 +1,12 @@ #include "hello_module.h" #include -#include #include +#include #include #include #include + using namespace extra2d; class HelloScene : public Scene { @@ -17,7 +18,7 @@ public: std::cout << "HelloScene entered" << std::endl; setBackgroundColor(Color(0.1f, 0.1f, 0.2f, 1.0f)); - auto* hello = Application::get().get(); + auto *hello = Application::get().get(); if (hello) { std::cout << "Scene calling HelloModule from onEnter..." << std::endl; hello->sayHello(); @@ -29,7 +30,7 @@ public: time_ += dt; if (time_ >= 5.0f) { - auto* hello = Application::get().get(); + auto *hello = Application::get().get(); if (hello) { std::cout << "Scene calling HelloModule from onUpdate..." << std::endl; hello->sayHello(); @@ -47,15 +48,23 @@ int main(int argc, char *argv[]) { (void)argv; std::cout << "=== Hello Module Example ===" << std::endl; - std::cout << "This example demonstrates how to create a custom module" << std::endl; + std::cout << "This example demonstrates how to create a custom module" + << std::endl; std::cout << "" << std::endl; Application &app = Application::get(); // 注册模块 - app.use(WindowModule::Cfg{.w = 800, .h = 600}); - app.use(); - app.use(HelloModule::Cfg{.greeting = "Hello from custom module!", .repeatCount = 3}); + app.use([](auto &cfg) { + cfg.w = 800; + cfg.h = 600; + cfg.backend = "glfw"; + }); + app.use([](auto &cfg) { cfg.priority = 10; }); + app.use([](auto &cfg) { + cfg.greeting = "Hello from custom module!"; + cfg.repeatCount = 3; + }); if (!app.init()) { std::cerr << "Failed to initialize application" << std::endl;