refactor(渲染): 迁移OpenGL到Vulkan并重构相关模块
- 移除OpenGL相关代码和依赖,添加Vulkan SDK支持 - 重构窗口模块为Vulkan实现,移除GL上下文和VSync相关功能 - 简化配置结构,移除不再需要的OpenGL版本设置 - 重构上下文模块,使用单例模块注册表 - 移动定时器模块到utils目录并优化实现 - 清理废弃代码和头文件引用
This commit is contained in:
parent
f9be301dae
commit
fb11f2a71e
|
|
@ -16,10 +16,7 @@ struct AppConfig {
|
||||||
int32 height = 720; // 窗口高度
|
int32 height = 720; // 窗口高度
|
||||||
bool fullscreen = false; // 是否全屏
|
bool fullscreen = false; // 是否全屏
|
||||||
bool resizable = true; // 是否可调整大小
|
bool resizable = true; // 是否可调整大小
|
||||||
bool vsync = true; // 是否垂直同步
|
|
||||||
int32 fpsLimit = 0; // FPS限制(0表示不限制)
|
int32 fpsLimit = 0; // FPS限制(0表示不限制)
|
||||||
int32 glMajor = 3; // OpenGL主版本
|
|
||||||
int32 glMinor = 3; // OpenGL次版本
|
|
||||||
bool enableCursors = true; // 启用光标
|
bool enableCursors = true; // 启用光标
|
||||||
bool enableDpiScale = false; // 启用DPI缩放
|
bool enableDpiScale = false; // 启用DPI缩放
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,6 @@ struct WindowCfg {
|
||||||
int32 height = 720; // 窗口高度
|
int32 height = 720; // 窗口高度
|
||||||
bool fullscreen = false; // 是否全屏
|
bool fullscreen = false; // 是否全屏
|
||||||
bool resizable = true; // 是否可调整大小
|
bool resizable = true; // 是否可调整大小
|
||||||
bool vsync = true; // 是否垂直同步
|
|
||||||
int32 glMajor = 3; // OpenGL主版本
|
|
||||||
int32 glMinor = 3; // OpenGL次版本
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,6 @@ public:
|
||||||
void stop() { running_ = false; }
|
void stop() { running_ = false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<ModuleRegistry> moduleRegistry_;
|
|
||||||
std::unique_ptr<PluginLoader> pluginLoader_;
|
std::unique_ptr<PluginLoader> pluginLoader_;
|
||||||
std::unique_ptr<TimerModule> timerModule_;
|
std::unique_ptr<TimerModule> timerModule_;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,6 @@
|
||||||
#include <event/event_bus_macros.h>
|
#include <event/event_bus_macros.h>
|
||||||
#include <event/events.h>
|
#include <event/events.h>
|
||||||
|
|
||||||
// Platform
|
|
||||||
#include <platform/sdl2.h>
|
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
#include <utils/logger.h>
|
#include <utils/logger.h>
|
||||||
#include <utils/random.h>
|
#include <utils/random.h>
|
||||||
|
|
@ -47,13 +44,6 @@
|
||||||
// Application
|
// Application
|
||||||
#include <app/application.h>
|
#include <app/application.h>
|
||||||
|
|
||||||
// 兼容层 - 旧的头文件(将在后续版本中移除)
|
|
||||||
// #include <core/director.h> // 已废弃,使用 Context
|
|
||||||
// #include <module/module.h> // 已废弃,使用 imodule.h
|
|
||||||
// #include <module/module_manager.h> // 已废弃,使用 module_registry.h
|
|
||||||
// #include <plugin/plugin.h> // 已废弃,使用 iplugin.h
|
|
||||||
// #include <plugin/plugin_manager.h> // 已废弃,使用 plugin_loader.h
|
|
||||||
|
|
||||||
#ifdef __SWITCH__
|
#ifdef __SWITCH__
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,11 @@
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#include <config/app_config.h>
|
#include <config/app_config.h>
|
||||||
#include <config/window_config.h>
|
#include <config/window_config.h>
|
||||||
|
#include <event/events.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
#include <module/module.h>
|
#include <module/module.h>
|
||||||
#include <module/module_registry.h>
|
#include <module/module_registry.h>
|
||||||
#include <type_traits>
|
|
||||||
#include <types/math/size.h>
|
#include <types/math/size.h>
|
||||||
#include <types/math/vec2.h>
|
#include <types/math/vec2.h>
|
||||||
|
|
||||||
|
|
@ -19,9 +20,9 @@ using ResizeCb = std::function<void(int32 w, int32 h)>;
|
||||||
using CloseCb = std::function<void()>;
|
using CloseCb = std::function<void()>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 窗口模块 - 简化版
|
* @brief 窗口模块 - Vulkan 版本
|
||||||
*
|
*
|
||||||
* 管理 SDL2 窗口和 OpenGL 上下文
|
* 管理 SDL2 窗口,支持 Vulkan 渲染
|
||||||
* 使用新的 Module 基类,支持自动注册
|
* 使用新的 Module 基类,支持自动注册
|
||||||
*/
|
*/
|
||||||
class WindowModule : public Module {
|
class WindowModule : public Module {
|
||||||
|
|
@ -55,21 +56,11 @@ public:
|
||||||
*/
|
*/
|
||||||
bool pollEvents();
|
bool pollEvents();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 交换缓冲区
|
|
||||||
*/
|
|
||||||
void swapBuffers();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取 SDL 窗口句柄
|
* @brief 获取 SDL 窗口句柄
|
||||||
*/
|
*/
|
||||||
SDL_Window *handle() const { return window_; }
|
SDL_Window *handle() const { return window_; }
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 获取 OpenGL 上下文
|
|
||||||
*/
|
|
||||||
SDL_GLContext glContext() const { return glCtx_; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取窗口尺寸
|
* @brief 获取窗口尺寸
|
||||||
*/
|
*/
|
||||||
|
|
@ -100,16 +91,6 @@ public:
|
||||||
*/
|
*/
|
||||||
bool isFullscreen() const;
|
bool isFullscreen() const;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 设置垂直同步
|
|
||||||
*/
|
|
||||||
void setVsync(bool vsync);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 检查是否垂直同步
|
|
||||||
*/
|
|
||||||
bool isVsync() const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 显示/隐藏窗口
|
* @brief 显示/隐藏窗口
|
||||||
*/
|
*/
|
||||||
|
|
@ -140,42 +121,39 @@ public:
|
||||||
*/
|
*/
|
||||||
bool shouldClose() const { return shouldClose_; }
|
bool shouldClose() const { return shouldClose_; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取 Vulkan 所需的窗口扩展
|
||||||
|
* @return 扩展名称列表
|
||||||
|
*/
|
||||||
|
std::vector<const char *> getVulkanExtensions() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建 Vulkan 表面
|
||||||
|
* @param instance Vulkan 实例
|
||||||
|
* @param surface 输出的表面句柄
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
bool createVulkanSurface(void *instance, void **surface) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleWindowEvent(const SDL_WindowEvent &evt);
|
void handleWindowEvent(const SDL_WindowEvent &evt);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 监听模块配置事件
|
* @brief 监听模块配置事件
|
||||||
* @tparam ConfigT 配置类型
|
* @param config 应用配置对象
|
||||||
* @param config 配置对象
|
|
||||||
*
|
*
|
||||||
* 只处理 AppConfig 类型的配置
|
* 处理 AppConfig 类型的配置,创建窗口
|
||||||
*/
|
*/
|
||||||
template <typename ConfigT> void onModuleConfig(const ConfigT &config) {
|
void onModuleConfig(const AppConfig &config);
|
||||||
// 只处理 AppConfig 类型
|
|
||||||
if constexpr (std::is_same_v<ConfigT, AppConfig>) {
|
|
||||||
WindowCfg cfg;
|
|
||||||
cfg.title = config.title;
|
|
||||||
cfg.width = config.width;
|
|
||||||
cfg.height = config.height;
|
|
||||||
cfg.fullscreen = config.fullscreen;
|
|
||||||
cfg.resizable = config.resizable;
|
|
||||||
cfg.vsync = config.vsync;
|
|
||||||
cfg.glMajor = config.glMajor;
|
|
||||||
cfg.glMinor = config.glMinor;
|
|
||||||
|
|
||||||
if (create(cfg)) {
|
|
||||||
setVisible(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_Window *window_ = nullptr;
|
SDL_Window *window_ = nullptr;
|
||||||
SDL_GLContext glCtx_ = nullptr;
|
|
||||||
bool shouldClose_ = false;
|
bool shouldClose_ = false;
|
||||||
bool vsync_ = true;
|
|
||||||
|
|
||||||
CloseCb onClose_;
|
CloseCb onClose_;
|
||||||
ResizeCb onResize_;
|
ResizeCb onResize_;
|
||||||
|
|
||||||
|
// 模块配置事件监听器
|
||||||
|
std::unique_ptr<events::OnModuleConfig<AppConfig>::Listener> configListener_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <plugin\iplugin.h>
|
#include <plugin\iplugin.h>
|
||||||
#include <vector>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
|
|
@ -20,51 +19,51 @@ public:
|
||||||
~PluginLoader();
|
~PluginLoader();
|
||||||
|
|
||||||
// 禁止拷贝
|
// 禁止拷贝
|
||||||
PluginLoader(const PluginLoader&) = delete;
|
PluginLoader(const PluginLoader &) = delete;
|
||||||
PluginLoader& operator=(const PluginLoader&) = delete;
|
PluginLoader &operator=(const PluginLoader &) = delete;
|
||||||
|
|
||||||
// 允许移动
|
// 允许移动
|
||||||
PluginLoader(PluginLoader&&) noexcept;
|
PluginLoader(PluginLoader &&) noexcept;
|
||||||
PluginLoader& operator=(PluginLoader&&) noexcept;
|
PluginLoader &operator=(PluginLoader &&) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 从动态库加载插件
|
* @brief 从动态库加载插件
|
||||||
* @param path 插件动态库路径
|
* @param path 插件动态库路径
|
||||||
* @return 是否加载成功
|
* @return 是否加载成功
|
||||||
*/
|
*/
|
||||||
bool loadFromLibrary(const char* path);
|
bool loadFromLibrary(const char *path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 注册内置插件(静态链接)
|
* @brief 注册内置插件(静态链接)
|
||||||
* @param plugin 插件实例指针(不由加载器管理生命周期)
|
* @param plugin 插件实例指针(不由加载器管理生命周期)
|
||||||
*/
|
*/
|
||||||
void registerPlugin(IPlugin* plugin);
|
void registerPlugin(IPlugin *plugin);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 卸载插件
|
* @brief 卸载插件
|
||||||
* @param name 插件名称
|
* @param name 插件名称
|
||||||
*/
|
*/
|
||||||
void unloadPlugin(const char* name);
|
void unloadPlugin(const char *name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取插件
|
* @brief 获取插件
|
||||||
* @param name 插件名称
|
* @param name 插件名称
|
||||||
* @return 插件指针,不存在返回 nullptr
|
* @return 插件指针,不存在返回 nullptr
|
||||||
*/
|
*/
|
||||||
IPlugin* getPlugin(const char* name) const;
|
IPlugin *getPlugin(const char *name) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 检查插件是否存在
|
* @brief 检查插件是否存在
|
||||||
* @param name 插件名称
|
* @param name 插件名称
|
||||||
* @return 是否存在
|
* @return 是否存在
|
||||||
*/
|
*/
|
||||||
bool hasPlugin(const char* name) const;
|
bool hasPlugin(const char *name) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取所有插件
|
* @brief 获取所有插件
|
||||||
* @return 插件列表
|
* @return 插件列表
|
||||||
*/
|
*/
|
||||||
std::vector<IPlugin*> getAllPlugins() const;
|
std::vector<IPlugin *> getAllPlugins() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 初始化所有插件(自动处理依赖)
|
* @brief 初始化所有插件(自动处理依赖)
|
||||||
|
|
@ -87,22 +86,22 @@ public:
|
||||||
* @brief 添加插件搜索路径
|
* @brief 添加插件搜索路径
|
||||||
* @param path 搜索路径
|
* @param path 搜索路径
|
||||||
*/
|
*/
|
||||||
void addSearchPath(const char* path);
|
void addSearchPath(const char *path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 从目录加载所有插件
|
* @brief 从目录加载所有插件
|
||||||
* @param directory 目录路径
|
* @param directory 目录路径
|
||||||
* @return 加载成功的插件数量
|
* @return 加载成功的插件数量
|
||||||
*/
|
*/
|
||||||
size_t loadPluginsFromDirectory(const char* directory);
|
size_t loadPluginsFromDirectory(const char *directory);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* @brief 插件条目结构
|
* @brief 插件条目结构
|
||||||
*/
|
*/
|
||||||
struct PluginEntry {
|
struct PluginEntry {
|
||||||
IPlugin* plugin = nullptr; // 插件实例
|
IPlugin *plugin = nullptr; // 插件实例
|
||||||
void* handle = nullptr; // 动态库句柄
|
void *handle = nullptr; // 动态库句柄
|
||||||
bool isDynamic = false; // 是否为动态加载
|
bool isDynamic = false; // 是否为动态加载
|
||||||
bool owned = false; // 是否由加载器管理生命周期
|
bool owned = false; // 是否由加载器管理生命周期
|
||||||
};
|
};
|
||||||
|
|
@ -112,14 +111,14 @@ private:
|
||||||
* @param plugin 插件
|
* @param plugin 插件
|
||||||
* @return 依赖是否满足
|
* @return 依赖是否满足
|
||||||
*/
|
*/
|
||||||
bool resolveDependencies(IPlugin* plugin);
|
bool resolveDependencies(IPlugin *plugin);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 检查依赖是否满足
|
* @brief 检查依赖是否满足
|
||||||
* @param dependencies 依赖列表
|
* @param dependencies 依赖列表
|
||||||
* @return 是否满足
|
* @return 是否满足
|
||||||
*/
|
*/
|
||||||
bool checkDependencies(const std::vector<std::string>& dependencies);
|
bool checkDependencies(const std::vector<std::string> &dependencies);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 按依赖顺序排序插件
|
* @brief 按依赖顺序排序插件
|
||||||
|
|
@ -131,13 +130,13 @@ private:
|
||||||
* @param path 库路径
|
* @param path 库路径
|
||||||
* @return 库句柄
|
* @return 库句柄
|
||||||
*/
|
*/
|
||||||
void* loadDynamicLibrary(const char* path);
|
void *loadDynamicLibrary(const char *path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 卸载动态库
|
* @brief 卸载动态库
|
||||||
* @param handle 库句柄
|
* @param handle 库句柄
|
||||||
*/
|
*/
|
||||||
void unloadDynamicLibrary(void* handle);
|
void unloadDynamicLibrary(void *handle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 获取动态库符号
|
* @brief 获取动态库符号
|
||||||
|
|
@ -145,11 +144,11 @@ private:
|
||||||
* @param name 符号名称
|
* @param name 符号名称
|
||||||
* @return 符号地址
|
* @return 符号地址
|
||||||
*/
|
*/
|
||||||
void* getSymbol(void* handle, const char* name);
|
void *getSymbol(void *handle, const char *name);
|
||||||
|
|
||||||
std::unordered_map<std::string, PluginEntry> plugins_;
|
std::unordered_map<std::string, PluginEntry> plugins_;
|
||||||
std::vector<std::string> searchPaths_;
|
std::vector<std::string> searchPaths_;
|
||||||
std::vector<IPlugin*> sortedPlugins_; // 按依赖排序的插件列表
|
std::vector<IPlugin *> sortedPlugins_; // 按依赖排序的插件列表
|
||||||
bool inited_ = false;
|
bool inited_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,8 +54,8 @@ bool Application::init(const AppConfig &config) {
|
||||||
events::OnInit::emit();
|
events::OnInit::emit();
|
||||||
|
|
||||||
E2D_LOG_INFO("Application initialized successfully");
|
E2D_LOG_INFO("Application initialized successfully");
|
||||||
E2D_LOG_INFO("Window: {}x{}, Fullscreen: {}, VSync: {}", config.width,
|
E2D_LOG_INFO("Window: {}x{}, Fullscreen: {}", config.width,
|
||||||
config.height, config.fullscreen, config.vsync);
|
config.height, config.fullscreen);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -132,13 +132,8 @@ void Application::run() {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 交换缓冲区
|
|
||||||
if (window) {
|
|
||||||
window->swapBuffers();
|
|
||||||
}
|
|
||||||
|
|
||||||
// FPS 限制 - 使用 SDL_Delay
|
// FPS 限制 - 使用 SDL_Delay
|
||||||
if (!config_.vsync && config_.fpsLimit > 0) {
|
if (config_.fpsLimit > 0) {
|
||||||
Uint64 frameEndCounter = SDL_GetPerformanceCounter();
|
Uint64 frameEndCounter = SDL_GetPerformanceCounter();
|
||||||
float frameTime =
|
float frameTime =
|
||||||
static_cast<float>(frameEndCounter - currentPerfCounter) / perfFreq;
|
static_cast<float>(frameEndCounter - currentPerfCounter) / perfFreq;
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,14 @@
|
||||||
#include <context/context.h>
|
#include <context/context.h>
|
||||||
#include <module/module_registry.h>
|
|
||||||
#include <module/timer_module.h>
|
|
||||||
#include <plugin/plugin_loader.h>
|
|
||||||
#include <event/events.h>
|
#include <event/events.h>
|
||||||
#include <algorithm>
|
#include <module/module_registry.h>
|
||||||
|
#include <plugin/plugin_loader.h>
|
||||||
|
#include <utils/timer_module.h>
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
Context::Context()
|
Context::Context()
|
||||||
: moduleRegistry_(std::make_unique<ModuleRegistry>())
|
: pluginLoader_(std::make_unique<PluginLoader>()),
|
||||||
, pluginLoader_(std::make_unique<PluginLoader>())
|
timerModule_(std::make_unique<TimerModule>()) {}
|
||||||
, timerModule_(std::make_unique<TimerModule>())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Context::~Context() {
|
Context::~Context() {
|
||||||
if (inited_) {
|
if (inited_) {
|
||||||
|
|
@ -20,8 +16,8 @@ Context::~Context() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Context::Context(Context&&) noexcept = default;
|
Context::Context(Context &&) noexcept = default;
|
||||||
Context& Context::operator=(Context&&) noexcept = default;
|
Context &Context::operator=(Context &&) noexcept = default;
|
||||||
|
|
||||||
std::unique_ptr<Context> Context::create() {
|
std::unique_ptr<Context> Context::create() {
|
||||||
return std::make_unique<Context>();
|
return std::make_unique<Context>();
|
||||||
|
|
@ -35,11 +31,8 @@ bool Context::init() {
|
||||||
// 发送引擎初始化事件
|
// 发送引擎初始化事件
|
||||||
events::OnInit::emit();
|
events::OnInit::emit();
|
||||||
|
|
||||||
// 注册核心模块
|
// 初始化定时器模块
|
||||||
moduleRegistry_->registerModule(timerModule_.get());
|
if (!timerModule_->init()) {
|
||||||
|
|
||||||
// 初始化所有模块
|
|
||||||
if (!moduleRegistry_->initAll()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -63,8 +56,8 @@ void Context::shutdown() {
|
||||||
// 关闭所有插件
|
// 关闭所有插件
|
||||||
pluginLoader_->shutdownAll();
|
pluginLoader_->shutdownAll();
|
||||||
|
|
||||||
// 关闭所有模块
|
// 关闭定时器模块
|
||||||
moduleRegistry_->shutdownAll();
|
timerModule_->shutdown();
|
||||||
|
|
||||||
// 发送引擎关闭事件
|
// 发送引擎关闭事件
|
||||||
events::OnShutdown::emit();
|
events::OnShutdown::emit();
|
||||||
|
|
@ -91,16 +84,10 @@ void Context::tick(float dt) {
|
||||||
events::OnLateUpdate::emit(dt);
|
events::OnLateUpdate::emit(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleRegistry& Context::modules() {
|
ModuleRegistry &Context::modules() { return ModuleRegistry::instance(); }
|
||||||
return *moduleRegistry_;
|
|
||||||
}
|
|
||||||
|
|
||||||
PluginLoader& Context::plugins() {
|
PluginLoader &Context::plugins() { return *pluginLoader_; }
|
||||||
return *pluginLoader_;
|
|
||||||
}
|
|
||||||
|
|
||||||
TimerModule& Context::timer() {
|
TimerModule &Context::timer() { return *timerModule_; }
|
||||||
return *timerModule_;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -1,221 +0,0 @@
|
||||||
#include <module/timer_module.h>
|
|
||||||
#include <event/events.h>
|
|
||||||
|
|
||||||
namespace extra2d {
|
|
||||||
|
|
||||||
TimerModule::TimerModule() = default;
|
|
||||||
|
|
||||||
TimerModule::~TimerModule() {
|
|
||||||
shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
TimerModule::TimerModule(TimerModule&& other) noexcept
|
|
||||||
: timers_(std::move(other.timers_))
|
|
||||||
, pendingRemove_(std::move(other.pendingRemove_))
|
|
||||||
, nextId_(other.nextId_)
|
|
||||||
, timeScale_(other.timeScale_)
|
|
||||||
, inUpdate_(other.inUpdate_) {
|
|
||||||
}
|
|
||||||
|
|
||||||
TimerModule& TimerModule::operator=(TimerModule&& other) noexcept {
|
|
||||||
if (this != &other) {
|
|
||||||
shutdown();
|
|
||||||
|
|
||||||
timers_ = std::move(other.timers_);
|
|
||||||
pendingRemove_ = std::move(other.pendingRemove_);
|
|
||||||
nextId_ = other.nextId_;
|
|
||||||
timeScale_ = other.timeScale_;
|
|
||||||
inUpdate_ = other.inUpdate_;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TimerModule::init() {
|
|
||||||
// 初始化完成,等待 OnUpdate 事件
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerModule::shutdown() {
|
|
||||||
cancelAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
TimerId TimerModule::scheduleOnce(float delay, TimerCallback callback) {
|
|
||||||
if (delay < 0.0f) delay = 0.0f;
|
|
||||||
|
|
||||||
TimerId id = generateId();
|
|
||||||
auto info = std::make_unique<TimerInfo>();
|
|
||||||
info->id = id;
|
|
||||||
info->interval = delay;
|
|
||||||
info->elapsed = 0.0f;
|
|
||||||
info->repeat = 1;
|
|
||||||
info->executed = 0;
|
|
||||||
info->paused = false;
|
|
||||||
info->cancelled = false;
|
|
||||||
info->callback = std::move(callback);
|
|
||||||
|
|
||||||
timers_[id] = std::move(info);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
TimerId TimerModule::scheduleRepeat(float interval, uint32 repeat, TimerCallback callback) {
|
|
||||||
if (interval < 0.0f) interval = 0.0f;
|
|
||||||
|
|
||||||
TimerId id = generateId();
|
|
||||||
auto info = std::make_unique<TimerInfo>();
|
|
||||||
info->id = id;
|
|
||||||
info->interval = interval;
|
|
||||||
info->elapsed = 0.0f;
|
|
||||||
info->repeat = repeat;
|
|
||||||
info->executed = 0;
|
|
||||||
info->paused = false;
|
|
||||||
info->cancelled = false;
|
|
||||||
info->callback = std::move(callback);
|
|
||||||
|
|
||||||
timers_[id] = std::move(info);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
TimerId TimerModule::scheduleUpdate(TimerUpdateCallback callback) {
|
|
||||||
TimerId id = generateId();
|
|
||||||
auto info = std::make_unique<TimerInfo>();
|
|
||||||
info->id = id;
|
|
||||||
info->interval = 0.0f;
|
|
||||||
info->elapsed = 0.0f;
|
|
||||||
info->repeat = 0;
|
|
||||||
info->executed = 0;
|
|
||||||
info->paused = false;
|
|
||||||
info->cancelled = false;
|
|
||||||
info->updateCallback = std::move(callback);
|
|
||||||
|
|
||||||
timers_[id] = std::move(info);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerModule::cancel(TimerId id) {
|
|
||||||
if (id == INVALID_TIMER_ID) return;
|
|
||||||
|
|
||||||
auto it = timers_.find(id);
|
|
||||||
if (it != timers_.end()) {
|
|
||||||
if (inUpdate_) {
|
|
||||||
// 如果在更新中,标记为待删除
|
|
||||||
it->second->cancelled = true;
|
|
||||||
pendingRemove_.push_back(id);
|
|
||||||
} else {
|
|
||||||
// 直接删除
|
|
||||||
timers_.erase(it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerModule::pause(TimerId id) {
|
|
||||||
if (id == INVALID_TIMER_ID) return;
|
|
||||||
|
|
||||||
auto it = timers_.find(id);
|
|
||||||
if (it != timers_.end()) {
|
|
||||||
it->second->paused = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerModule::resume(TimerId id) {
|
|
||||||
if (id == INVALID_TIMER_ID) return;
|
|
||||||
|
|
||||||
auto it = timers_.find(id);
|
|
||||||
if (it != timers_.end()) {
|
|
||||||
it->second->paused = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerModule::cancelAll() {
|
|
||||||
if (inUpdate_) {
|
|
||||||
// 如果在更新中,标记所有为待删除
|
|
||||||
for (auto& pair : timers_) {
|
|
||||||
pair.second->cancelled = true;
|
|
||||||
pendingRemove_.push_back(pair.first);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 直接清空
|
|
||||||
timers_.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t TimerModule::getActiveCount() const {
|
|
||||||
size_t count = 0;
|
|
||||||
for (const auto& pair : timers_) {
|
|
||||||
if (!pair.second->cancelled) {
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerModule::update(float dt) {
|
|
||||||
if (timers_.empty()) return;
|
|
||||||
|
|
||||||
// 应用时间缩放
|
|
||||||
dt *= timeScale_;
|
|
||||||
|
|
||||||
inUpdate_ = true;
|
|
||||||
|
|
||||||
// 收集需要执行的定时器
|
|
||||||
std::vector<TimerInfo*> toExecute;
|
|
||||||
std::vector<TimerId> toRemove;
|
|
||||||
|
|
||||||
for (auto& pair : timers_) {
|
|
||||||
TimerInfo* info = pair.second.get();
|
|
||||||
|
|
||||||
if (info->cancelled || info->paused) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新任务(每帧执行)
|
|
||||||
if (info->updateCallback) {
|
|
||||||
toExecute.push_back(info);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 定时任务
|
|
||||||
info->elapsed += dt;
|
|
||||||
|
|
||||||
if (info->elapsed >= info->interval) {
|
|
||||||
toExecute.push_back(info);
|
|
||||||
|
|
||||||
// 重置计时器
|
|
||||||
info->elapsed = 0.0f;
|
|
||||||
info->executed++;
|
|
||||||
|
|
||||||
// 检查是否需要移除
|
|
||||||
if (info->repeat > 0 && info->executed >= info->repeat) {
|
|
||||||
toRemove.push_back(info->id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 执行回调
|
|
||||||
for (TimerInfo* info : toExecute) {
|
|
||||||
if (info->callback) {
|
|
||||||
info->callback();
|
|
||||||
}
|
|
||||||
if (info->updateCallback) {
|
|
||||||
info->updateCallback(dt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inUpdate_ = false;
|
|
||||||
|
|
||||||
// 移除已完成的定时器
|
|
||||||
for (TimerId id : toRemove) {
|
|
||||||
timers_.erase(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理待删除列表
|
|
||||||
for (TimerId id : pendingRemove_) {
|
|
||||||
timers_.erase(id);
|
|
||||||
}
|
|
||||||
pendingRemove_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
TimerId TimerModule::generateId() {
|
|
||||||
return nextId_++;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace extra2d
|
|
||||||
|
|
@ -1,9 +1,15 @@
|
||||||
#include <platform/window_module.h>
|
#include <platform/window_module.h>
|
||||||
#include <platform/sdl2.h>
|
|
||||||
#include <config/app_config.h>
|
#include <config/app_config.h>
|
||||||
#include <event/events.h>
|
#include <event/events.h>
|
||||||
|
#include <memory>
|
||||||
#include <utils/logger.h>
|
#include <utils/logger.h>
|
||||||
|
|
||||||
|
// SDL Vulkan support
|
||||||
|
#include <SDL_vulkan.h>
|
||||||
|
|
||||||
|
// Vulkan
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
namespace extra2d {
|
namespace extra2d {
|
||||||
|
|
||||||
WindowModule::WindowModule() = default;
|
WindowModule::WindowModule() = default;
|
||||||
|
|
@ -14,53 +20,42 @@ WindowModule::~WindowModule() {
|
||||||
|
|
||||||
WindowModule::WindowModule(WindowModule&& other) noexcept
|
WindowModule::WindowModule(WindowModule&& other) noexcept
|
||||||
: window_(other.window_)
|
: window_(other.window_)
|
||||||
, glCtx_(other.glCtx_)
|
|
||||||
, shouldClose_(other.shouldClose_)
|
, shouldClose_(other.shouldClose_)
|
||||||
, vsync_(other.vsync_)
|
|
||||||
, onClose_(std::move(other.onClose_))
|
, onClose_(std::move(other.onClose_))
|
||||||
, onResize_(std::move(other.onResize_)) {
|
, onResize_(std::move(other.onResize_))
|
||||||
|
, configListener_(std::move(other.configListener_)) {
|
||||||
other.window_ = nullptr;
|
other.window_ = nullptr;
|
||||||
other.glCtx_ = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowModule& WindowModule::operator=(WindowModule&& other) noexcept {
|
WindowModule& WindowModule::operator=(WindowModule&& other) noexcept {
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
shutdown();
|
shutdown();
|
||||||
window_ = other.window_;
|
window_ = other.window_;
|
||||||
glCtx_ = other.glCtx_;
|
|
||||||
shouldClose_ = other.shouldClose_;
|
shouldClose_ = other.shouldClose_;
|
||||||
vsync_ = other.vsync_;
|
|
||||||
onClose_ = std::move(other.onClose_);
|
onClose_ = std::move(other.onClose_);
|
||||||
onResize_ = std::move(other.onResize_);
|
onResize_ = std::move(other.onResize_);
|
||||||
|
configListener_ = std::move(other.configListener_);
|
||||||
other.window_ = nullptr;
|
other.window_ = nullptr;
|
||||||
other.glCtx_ = nullptr;
|
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WindowModule::init() {
|
bool WindowModule::init() {
|
||||||
if (!Sdl2::initVideo()) {
|
if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) {
|
||||||
|
E2D_LOG_ERROR("Failed to initialize SDL video: {}", SDL_GetError());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
|
|
||||||
|
|
||||||
// 监听模块配置事件
|
// 监听模块配置事件
|
||||||
events::OnModuleConfig<AppConfig>::subscribe(this, &WindowModule::onModuleConfig<AppConfig>);
|
configListener_ = std::make_unique<events::OnModuleConfig<AppConfig>::Listener>();
|
||||||
|
configListener_->bind([this](const AppConfig& config) {
|
||||||
|
this->onModuleConfig(config);
|
||||||
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowModule::shutdown() {
|
void WindowModule::shutdown() {
|
||||||
if (glCtx_) {
|
|
||||||
SDL_GL_DeleteContext(glCtx_);
|
|
||||||
glCtx_ = nullptr;
|
|
||||||
}
|
|
||||||
if (window_) {
|
if (window_) {
|
||||||
SDL_DestroyWindow(window_);
|
SDL_DestroyWindow(window_);
|
||||||
window_ = nullptr;
|
window_ = nullptr;
|
||||||
|
|
@ -71,7 +66,7 @@ bool WindowModule::create(const WindowCfg& cfg) {
|
||||||
if (window_)
|
if (window_)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;
|
uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_VULKAN;
|
||||||
if (cfg.resizable) {
|
if (cfg.resizable) {
|
||||||
flags |= SDL_WINDOW_RESIZABLE;
|
flags |= SDL_WINDOW_RESIZABLE;
|
||||||
}
|
}
|
||||||
|
|
@ -79,9 +74,6 @@ bool WindowModule::create(const WindowCfg& cfg) {
|
||||||
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, cfg.glMajor);
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, cfg.glMinor);
|
|
||||||
|
|
||||||
window_ = SDL_CreateWindow(cfg.title.c_str(), SDL_WINDOWPOS_CENTERED,
|
window_ = SDL_CreateWindow(cfg.title.c_str(), SDL_WINDOWPOS_CENTERED,
|
||||||
SDL_WINDOWPOS_CENTERED, cfg.width, cfg.height, flags);
|
SDL_WINDOWPOS_CENTERED, cfg.width, cfg.height, flags);
|
||||||
|
|
||||||
|
|
@ -90,20 +82,10 @@ bool WindowModule::create(const WindowCfg& cfg) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
glCtx_ = SDL_GL_CreateContext(window_);
|
|
||||||
if (!glCtx_) {
|
|
||||||
E2D_LOG_ERROR("Failed to create OpenGL context: {}", SDL_GetError());
|
|
||||||
SDL_DestroyWindow(window_);
|
|
||||||
window_ = nullptr;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
setVsync(cfg.vsync);
|
|
||||||
vsync_ = cfg.vsync;
|
|
||||||
|
|
||||||
// 发送窗口显示事件
|
// 发送窗口显示事件
|
||||||
events::OnShow::emit();
|
events::OnShow::emit();
|
||||||
|
|
||||||
|
E2D_LOG_INFO("Window created: {}x{}", cfg.width, cfg.height);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -164,9 +146,16 @@ void WindowModule::handleWindowEvent(const SDL_WindowEvent& evt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowModule::swapBuffers() {
|
void WindowModule::onModuleConfig(const AppConfig &config) {
|
||||||
if (window_ && glCtx_) {
|
WindowCfg cfg;
|
||||||
SDL_GL_SwapWindow(window_);
|
cfg.title = config.title;
|
||||||
|
cfg.width = config.width;
|
||||||
|
cfg.height = config.height;
|
||||||
|
cfg.fullscreen = config.fullscreen;
|
||||||
|
cfg.resizable = config.resizable;
|
||||||
|
|
||||||
|
if (create(cfg)) {
|
||||||
|
setVisible(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -212,15 +201,6 @@ bool WindowModule::isFullscreen() const {
|
||||||
return (flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0;
|
return (flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowModule::setVsync(bool vsync) {
|
|
||||||
SDL_GL_SetSwapInterval(vsync ? 1 : 0);
|
|
||||||
vsync_ = vsync;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WindowModule::isVsync() const {
|
|
||||||
return vsync_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowModule::setVisible(bool visible) {
|
void WindowModule::setVisible(bool visible) {
|
||||||
if (window_) {
|
if (window_) {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
|
|
@ -242,4 +222,25 @@ bool WindowModule::isVisible() const {
|
||||||
return (flags & SDL_WINDOW_SHOWN) != 0;
|
return (flags & SDL_WINDOW_SHOWN) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<const char*> WindowModule::getVulkanExtensions() const {
|
||||||
|
std::vector<const char*> extensions;
|
||||||
|
if (!window_) {
|
||||||
|
return extensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 count = 0;
|
||||||
|
SDL_Vulkan_GetInstanceExtensions(window_, &count, nullptr);
|
||||||
|
extensions.resize(count);
|
||||||
|
SDL_Vulkan_GetInstanceExtensions(window_, &count, extensions.data());
|
||||||
|
|
||||||
|
return extensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WindowModule::createVulkanSurface(void* instance, void** surface) const {
|
||||||
|
if (!window_ || !instance || !surface) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return SDL_Vulkan_CreateSurface(window_, static_cast<VkInstance>(instance), reinterpret_cast<VkSurfaceKHR*>(surface));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace extra2d
|
} // namespace extra2d
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,219 @@
|
||||||
|
#include <event/events.h>
|
||||||
|
#include <utils/timer_module.h>
|
||||||
|
|
||||||
|
namespace extra2d {
|
||||||
|
|
||||||
|
TimerModule::TimerModule() = default;
|
||||||
|
|
||||||
|
TimerModule::~TimerModule() { shutdown(); }
|
||||||
|
|
||||||
|
TimerModule::TimerModule(TimerModule &&other) noexcept
|
||||||
|
: timers_(std::move(other.timers_)),
|
||||||
|
pendingRemove_(std::move(other.pendingRemove_)), nextId_(other.nextId_),
|
||||||
|
timeScale_(other.timeScale_), inUpdate_(other.inUpdate_) {}
|
||||||
|
|
||||||
|
TimerModule &TimerModule::operator=(TimerModule &&other) noexcept {
|
||||||
|
if (this != &other) {
|
||||||
|
shutdown();
|
||||||
|
|
||||||
|
timers_ = std::move(other.timers_);
|
||||||
|
pendingRemove_ = std::move(other.pendingRemove_);
|
||||||
|
nextId_ = other.nextId_;
|
||||||
|
timeScale_ = other.timeScale_;
|
||||||
|
inUpdate_ = other.inUpdate_;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TimerModule::init() {
|
||||||
|
// 初始化完成,等待 OnUpdate 事件
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimerModule::shutdown() { cancelAll(); }
|
||||||
|
|
||||||
|
TimerId TimerModule::scheduleOnce(float delay, TimerCallback callback) {
|
||||||
|
if (delay < 0.0f)
|
||||||
|
delay = 0.0f;
|
||||||
|
|
||||||
|
TimerId id = generateId();
|
||||||
|
auto info = std::make_unique<TimerInfo>();
|
||||||
|
info->id = id;
|
||||||
|
info->interval = delay;
|
||||||
|
info->elapsed = 0.0f;
|
||||||
|
info->repeat = 1;
|
||||||
|
info->executed = 0;
|
||||||
|
info->paused = false;
|
||||||
|
info->cancelled = false;
|
||||||
|
info->callback = std::move(callback);
|
||||||
|
|
||||||
|
timers_[id] = std::move(info);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
TimerId TimerModule::scheduleRepeat(float interval, uint32 repeat,
|
||||||
|
TimerCallback callback) {
|
||||||
|
if (interval < 0.0f)
|
||||||
|
interval = 0.0f;
|
||||||
|
|
||||||
|
TimerId id = generateId();
|
||||||
|
auto info = std::make_unique<TimerInfo>();
|
||||||
|
info->id = id;
|
||||||
|
info->interval = interval;
|
||||||
|
info->elapsed = 0.0f;
|
||||||
|
info->repeat = repeat;
|
||||||
|
info->executed = 0;
|
||||||
|
info->paused = false;
|
||||||
|
info->cancelled = false;
|
||||||
|
info->callback = std::move(callback);
|
||||||
|
|
||||||
|
timers_[id] = std::move(info);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
TimerId TimerModule::scheduleUpdate(TimerUpdateCallback callback) {
|
||||||
|
TimerId id = generateId();
|
||||||
|
auto info = std::make_unique<TimerInfo>();
|
||||||
|
info->id = id;
|
||||||
|
info->interval = 0.0f;
|
||||||
|
info->elapsed = 0.0f;
|
||||||
|
info->repeat = 0;
|
||||||
|
info->executed = 0;
|
||||||
|
info->paused = false;
|
||||||
|
info->cancelled = false;
|
||||||
|
info->updateCallback = std::move(callback);
|
||||||
|
|
||||||
|
timers_[id] = std::move(info);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimerModule::cancel(TimerId id) {
|
||||||
|
if (id == INVALID_TIMER_ID)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto it = timers_.find(id);
|
||||||
|
if (it != timers_.end()) {
|
||||||
|
if (inUpdate_) {
|
||||||
|
// 如果在更新中,标记为待删除
|
||||||
|
it->second->cancelled = true;
|
||||||
|
pendingRemove_.push_back(id);
|
||||||
|
} else {
|
||||||
|
// 直接删除
|
||||||
|
timers_.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimerModule::pause(TimerId id) {
|
||||||
|
if (id == INVALID_TIMER_ID)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto it = timers_.find(id);
|
||||||
|
if (it != timers_.end()) {
|
||||||
|
it->second->paused = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimerModule::resume(TimerId id) {
|
||||||
|
if (id == INVALID_TIMER_ID)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto it = timers_.find(id);
|
||||||
|
if (it != timers_.end()) {
|
||||||
|
it->second->paused = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimerModule::cancelAll() {
|
||||||
|
if (inUpdate_) {
|
||||||
|
// 如果在更新中,标记所有为待删除
|
||||||
|
for (auto &pair : timers_) {
|
||||||
|
pair.second->cancelled = true;
|
||||||
|
pendingRemove_.push_back(pair.first);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 直接清空
|
||||||
|
timers_.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t TimerModule::getActiveCount() const {
|
||||||
|
size_t count = 0;
|
||||||
|
for (const auto &pair : timers_) {
|
||||||
|
if (!pair.second->cancelled) {
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimerModule::update(float dt) {
|
||||||
|
if (timers_.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 应用时间缩放
|
||||||
|
dt *= timeScale_;
|
||||||
|
|
||||||
|
inUpdate_ = true;
|
||||||
|
|
||||||
|
// 收集需要执行的定时器
|
||||||
|
std::vector<TimerInfo *> toExecute;
|
||||||
|
std::vector<TimerId> toRemove;
|
||||||
|
|
||||||
|
for (auto &pair : timers_) {
|
||||||
|
TimerInfo *info = pair.second.get();
|
||||||
|
|
||||||
|
if (info->cancelled || info->paused) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新任务(每帧执行)
|
||||||
|
if (info->updateCallback) {
|
||||||
|
toExecute.push_back(info);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定时任务
|
||||||
|
info->elapsed += dt;
|
||||||
|
|
||||||
|
if (info->elapsed >= info->interval) {
|
||||||
|
toExecute.push_back(info);
|
||||||
|
|
||||||
|
// 重置计时器
|
||||||
|
info->elapsed = 0.0f;
|
||||||
|
info->executed++;
|
||||||
|
|
||||||
|
// 检查是否需要移除
|
||||||
|
if (info->repeat > 0 && info->executed >= info->repeat) {
|
||||||
|
toRemove.push_back(info->id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行回调
|
||||||
|
for (TimerInfo *info : toExecute) {
|
||||||
|
if (info->callback) {
|
||||||
|
info->callback();
|
||||||
|
}
|
||||||
|
if (info->updateCallback) {
|
||||||
|
info->updateCallback(dt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inUpdate_ = false;
|
||||||
|
|
||||||
|
// 移除已完成的定时器
|
||||||
|
for (TimerId id : toRemove) {
|
||||||
|
timers_.erase(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理待删除列表
|
||||||
|
for (TimerId id : pendingRemove_) {
|
||||||
|
timers_.erase(id);
|
||||||
|
}
|
||||||
|
pendingRemove_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
TimerId TimerModule::generateId() { return nextId_++; }
|
||||||
|
|
||||||
|
} // namespace extra2d
|
||||||
|
|
@ -78,7 +78,7 @@ end
|
||||||
-- ==============================================
|
-- ==============================================
|
||||||
|
|
||||||
if target_plat == "mingw" then
|
if target_plat == "mingw" then
|
||||||
add_requires("glm", "libsdl2", "libsdl2_mixer")
|
add_requires("glm", "libsdl2", "libsdl2_mixer", "vulkansdk")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ==============================================
|
-- ==============================================
|
||||||
|
|
|
||||||
|
|
@ -14,23 +14,23 @@ function define_extra2d_engine()
|
||||||
set_kind("static")
|
set_kind("static")
|
||||||
|
|
||||||
add_files("src/**.cpp|core/*.cpp|module/module_manager.cpp|plugin/plugin_manager.cpp|platform/window.cpp|platform/input.cpp")
|
add_files("src/**.cpp|core/*.cpp|module/module_manager.cpp|plugin/plugin_manager.cpp|platform/window.cpp|platform/input.cpp")
|
||||||
add_files("third_party/glad/src/glad.c")
|
|
||||||
|
|
||||||
add_includedirs("include", {public = true})
|
add_includedirs("include", {public = true})
|
||||||
add_includedirs("third_party/glad/include", {public = true})
|
|
||||||
add_includedirs("third_party", {public = true})
|
add_includedirs("third_party", {public = true})
|
||||||
|
|
||||||
local plat = get_current_plat()
|
local plat = get_current_plat()
|
||||||
if plat == "mingw" then
|
if plat == "mingw" then
|
||||||
add_defines("_UNICODE", "UNICODE")
|
add_defines("_UNICODE", "UNICODE")
|
||||||
add_packages("glm", "libsdl2", "libsdl2_mixer", {public = true})
|
-- 使用 xmake 官方包
|
||||||
add_syslinks("opengl32", "glu32", "winmm", "imm32", "version", "setupapi", {public = true})
|
add_packages("glm", "libsdl2", "libsdl2_mixer", "vulkansdk", {public = true})
|
||||||
|
add_syslinks("winmm", "imm32", "version", "setupapi", {public = true})
|
||||||
elseif plat == "switch" then
|
elseif plat == "switch" then
|
||||||
local devkitPro = os.getenv("DEVKITPRO") or "C:/devkitPro"
|
local devkitPro = os.getenv("DEVKITPRO") or "C:/devkitPro"
|
||||||
add_includedirs(devkitPro .. "/portlibs/switch/include", {public = true})
|
add_includedirs(devkitPro .. "/portlibs/switch/include", {public = true})
|
||||||
add_linkdirs(devkitPro .. "/portlibs/switch/lib")
|
add_linkdirs(devkitPro .. "/portlibs/switch/lib")
|
||||||
|
-- Switch 平台可能需要不同的图形库
|
||||||
add_syslinks("SDL2_mixer", "SDL2", "opusfile", "opus", "vorbisidec", "ogg",
|
add_syslinks("SDL2_mixer", "SDL2", "opusfile", "opus", "vorbisidec", "ogg",
|
||||||
"modplug", "mpg123", "FLAC", "GLESv2", "EGL", "glapi", "drm_nouveau",
|
"modplug", "mpg123", "FLAC", "drm_nouveau",
|
||||||
{public = true})
|
{public = true})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue