refactor(模块系统): 重构模块配置方式为lambda函数
将InputModule、WindowModule、RenderModule等核心模块的配置方式从结构体改为lambda函数 添加独立的配置结构体(InputCfg/WindowCfg/RenderCfg)并更新文档 实现GLFW窗口居中功能 更新示例代码使用新的配置方式
This commit is contained in:
parent
4b1de5e36a
commit
4f02ad0e39
|
|
@ -3,10 +3,30 @@
|
|||
#include <extra2d/core/module.h>
|
||||
#include <extra2d/graphics/core/render_backend.h>
|
||||
#include <extra2d/platform/window_module.h>
|
||||
#include <functional>
|
||||
#include <typeindex>
|
||||
|
||||
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,29 +34,10 @@ 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<void(RenderCfg&)> configFn);
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
|
|
@ -64,7 +65,7 @@ public:
|
|||
RenderBackend* renderer() const { return renderer_.get(); }
|
||||
|
||||
private:
|
||||
Cfg cfg_;
|
||||
RenderCfg cfg_;
|
||||
UniquePtr<RenderBackend> renderer_;
|
||||
bool initialized_ = false;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,10 +3,30 @@
|
|||
#include <extra2d/core/module.h>
|
||||
#include <extra2d/platform/iinput.h>
|
||||
#include <extra2d/platform/window_module.h>
|
||||
#include <functional>
|
||||
#include <typeindex>
|
||||
|
||||
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,29 +34,10 @@ 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<void(InputCfg&)> configFn);
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
|
|
@ -69,7 +70,7 @@ public:
|
|||
void update();
|
||||
|
||||
private:
|
||||
Cfg cfg_;
|
||||
InputCfg cfg_;
|
||||
IInput* input_ = nullptr;
|
||||
bool initialized_ = false;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,67 +1,64 @@
|
|||
#pragma once
|
||||
|
||||
#include <extra2d/core/module.h>
|
||||
#include <extra2d/platform/window_config.h>
|
||||
#include <extra2d/platform/iwindow.h>
|
||||
#include <extra2d/platform/window_config.h>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
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;
|
||||
/**
|
||||
* @brief 构造函数(Lambda 配置)
|
||||
* @param configFn 配置函数
|
||||
*/
|
||||
explicit WindowModule(std::function<void(WindowCfg &)> configFn);
|
||||
|
||||
Cfg()
|
||||
: title("Extra2D")
|
||||
, w(1280)
|
||||
, h(720)
|
||||
, mode(WindowMode::Windowed)
|
||||
, vsync(true)
|
||||
, priority(0)
|
||||
, backend("sdl2") {}
|
||||
};
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
~WindowModule() override;
|
||||
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param cfg 配置
|
||||
*/
|
||||
explicit WindowModule(const Cfg& cfg = Cfg());
|
||||
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 析构函数
|
||||
*/
|
||||
~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 获取窗口
|
||||
* @return 窗口指针
|
||||
*/
|
||||
IWindow *win() const { return win_.get(); }
|
||||
|
||||
private:
|
||||
Cfg cfg_;
|
||||
UniquePtr<IWindow> win_;
|
||||
bool initialized_ = false;
|
||||
bool sdlInited_ = false;
|
||||
WindowCfg cfg_;
|
||||
UniquePtr<IWindow> win_;
|
||||
bool initialized_ = false;
|
||||
bool sdlInited_ = false;
|
||||
};
|
||||
|
||||
} // namespace extra2d
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@
|
|||
|
||||
namespace extra2d {
|
||||
|
||||
RenderModule::RenderModule(const Cfg& cfg) : cfg_(cfg) {}
|
||||
RenderModule::RenderModule(std::function<void(RenderCfg&)> configFn) {
|
||||
configFn(cfg_);
|
||||
}
|
||||
|
||||
RenderModule::~RenderModule() {
|
||||
if (initialized_) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@
|
|||
|
||||
namespace extra2d {
|
||||
|
||||
InputModule::InputModule(const Cfg& cfg) : cfg_(cfg) {}
|
||||
InputModule::InputModule(std::function<void(InputCfg&)> configFn) {
|
||||
configFn(cfg_);
|
||||
}
|
||||
|
||||
InputModule::~InputModule() {
|
||||
if (initialized_) {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,9 @@ void initSDL2Backend();
|
|||
void initGLFWBackend();
|
||||
#endif
|
||||
|
||||
WindowModule::WindowModule(const Cfg& cfg) : cfg_(cfg) {}
|
||||
WindowModule::WindowModule(std::function<void(WindowCfg&)> configFn) {
|
||||
configFn(cfg_);
|
||||
}
|
||||
|
||||
WindowModule::~WindowModule() {
|
||||
if (initialized_) {
|
||||
|
|
|
|||
|
|
@ -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<WindowModule>([](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<InputModule>([](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<RenderModule>([](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<void(WindowCfg&)> configFn) {
|
||||
configFn(cfg_);
|
||||
}
|
||||
};
|
||||
|
||||
// 使用 Lambda 配置模块
|
||||
app.use<WindowModule>([](auto& cfg) {
|
||||
cfg.w = 1920;
|
||||
cfg.h = 1080;
|
||||
cfg.backend = "glfw";
|
||||
});
|
||||
|
||||
// 不好的做法:所有配置放在 AppConfig
|
||||
struct AppConfig {
|
||||
WindowConfig window; // 耦合度高
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
#include <extra2d/services/event_service.h>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
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<WindowModule>(winCfg);
|
||||
app.use<WindowModule>([](auto &cfg) {
|
||||
cfg.w = 1280;
|
||||
cfg.h = 720;
|
||||
cfg.priority = 0;
|
||||
cfg.backend = "glfw";
|
||||
});
|
||||
|
||||
RenderModule::Cfg renderCfg;
|
||||
renderCfg.priority = 10;
|
||||
app.use<RenderModule>(renderCfg);
|
||||
app.use<RenderModule>([](auto &cfg) { cfg.priority = 10; });
|
||||
|
||||
InputModule::Cfg inputCfg;
|
||||
inputCfg.priority = 20;
|
||||
app.use<InputModule>(inputCfg);
|
||||
app.use<InputModule>([](auto &cfg) { cfg.priority = 20; });
|
||||
|
||||
std::cout << "Initializing application..." << std::endl;
|
||||
if (!app.init()) {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@
|
|||
|
||||
namespace extra2d {
|
||||
|
||||
HelloModule::HelloModule(const Cfg& cfg) : cfg_(cfg) {}
|
||||
HelloModule::HelloModule(const HelloCfg& cfg) : cfg_(cfg) {}
|
||||
|
||||
HelloModule::HelloModule(std::function<void(HelloCfg&)> configFn) {
|
||||
configFn(cfg_);
|
||||
}
|
||||
|
||||
HelloModule::~HelloModule() {
|
||||
if (initialized_) {
|
||||
|
|
|
|||
|
|
@ -2,9 +2,24 @@
|
|||
|
||||
#include <extra2d/core/module.h>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
|
||||
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<void(HelloCfg&)> configFn);
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
|
|
@ -43,7 +60,7 @@ public:
|
|||
void sayHello() const;
|
||||
|
||||
private:
|
||||
Cfg cfg_;
|
||||
HelloCfg cfg_;
|
||||
bool initialized_ = false;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
#include "hello_module.h"
|
||||
#include <extra2d/app/application.h>
|
||||
#include <extra2d/platform/window_module.h>
|
||||
#include <extra2d/graphics/core/render_module.h>
|
||||
#include <extra2d/platform/window_module.h>
|
||||
#include <extra2d/scene/scene.h>
|
||||
#include <extra2d/services/scene_service.h>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
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<HelloModule>();
|
||||
auto *hello = Application::get().get<HelloModule>();
|
||||
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<HelloModule>();
|
||||
auto *hello = Application::get().get<HelloModule>();
|
||||
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>(WindowModule::Cfg{.w = 800, .h = 600});
|
||||
app.use<RenderModule>();
|
||||
app.use<HelloModule>(HelloModule::Cfg{.greeting = "Hello from custom module!", .repeatCount = 3});
|
||||
app.use<WindowModule>([](auto &cfg) {
|
||||
cfg.w = 800;
|
||||
cfg.h = 600;
|
||||
cfg.backend = "glfw";
|
||||
});
|
||||
app.use<RenderModule>([](auto &cfg) { cfg.priority = 10; });
|
||||
app.use<HelloModule>([](auto &cfg) {
|
||||
cfg.greeting = "Hello from custom module!";
|
||||
cfg.repeatCount = 3;
|
||||
});
|
||||
|
||||
if (!app.init()) {
|
||||
std::cerr << "Failed to initialize application" << std::endl;
|
||||
|
|
|
|||
Loading…
Reference in New Issue