From 174d7327efce3010ed9818e6d4855395740cf3ce Mon Sep 17 00:00:00 2001 From: ChestnutYueyue <952134128@qq.com> Date: Mon, 23 Feb 2026 06:00:35 +0800 Subject: [PATCH] =?UTF-8?q?refactor(core):=20=E9=87=8D=E6=9E=84=E7=94=9F?= =?UTF-8?q?=E5=91=BD=E5=91=A8=E6=9C=9F=E7=AE=A1=E7=90=86=EF=BC=8C=E5=BC=95?= =?UTF-8?q?=E5=85=A5Lifecycle=E7=BB=9F=E4=B8=80=E7=AE=A1=E7=90=86=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E5=92=8C=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 重构模块和服务初始化流程,使用Lifecycle类统一管理依赖和生命周期 移除旧的ServiceLocator和Registry,简化架构 添加模块和服务依赖声明功能,支持自动拓扑排序 优化初始化顺序,支持并行初始化独立模块 更新相关模块和服务以适配新生命周期管理接口 --- Extra2D/include/extra2d/app/application.h | 102 +++-- Extra2D/include/extra2d/core/lifecycle.h | 350 +++++++++++++++ Extra2D/include/extra2d/core/module.h | 101 ++--- Extra2D/include/extra2d/core/registry.h | 166 -------- Extra2D/include/extra2d/core/result.h | 398 ------------------ .../include/extra2d/core/service_interface.h | 15 + .../include/extra2d/core/service_locator.h | 307 -------------- .../include/extra2d/core/service_registry.h | 137 ------ Extra2D/include/extra2d/extra2d.h | 4 +- .../include/extra2d/render/render_module.h | 129 ++++++ .../include/extra2d/services/asset_service.h | 11 +- .../include/extra2d/services/event_service.h | 99 +++-- .../include/extra2d/services/logger_service.h | 17 +- .../include/extra2d/services/timer_service.h | 15 +- Extra2D/include/extra2d/window/window.h | 3 + .../include/extra2d/window/window_module.h | 164 ++++++++ Extra2D/src/app/application.cpp | 75 ++-- Extra2D/src/core/lifecycle.cpp | 329 +++++++++++++++ Extra2D/src/core/registry.cpp | 224 ---------- Extra2D/src/core/service_locator.cpp | 110 ----- Extra2D/src/core/service_registry.cpp | 37 -- Extra2D/src/render/render_module.cpp | 91 ++++ Extra2D/src/services/logger_service.cpp | 7 +- Extra2D/src/window/window_module.cpp | 156 +++++++ examples/hello_world/main.cpp | 84 ++-- 25 files changed, 1537 insertions(+), 1594 deletions(-) create mode 100644 Extra2D/include/extra2d/core/lifecycle.h delete mode 100644 Extra2D/include/extra2d/core/registry.h delete mode 100644 Extra2D/include/extra2d/core/result.h delete mode 100644 Extra2D/include/extra2d/core/service_locator.h delete mode 100644 Extra2D/include/extra2d/core/service_registry.h create mode 100644 Extra2D/include/extra2d/render/render_module.h create mode 100644 Extra2D/include/extra2d/window/window_module.h create mode 100644 Extra2D/src/core/lifecycle.cpp delete mode 100644 Extra2D/src/core/registry.cpp delete mode 100644 Extra2D/src/core/service_locator.cpp delete mode 100644 Extra2D/src/core/service_registry.cpp create mode 100644 Extra2D/src/render/render_module.cpp create mode 100644 Extra2D/src/window/window_module.cpp diff --git a/Extra2D/include/extra2d/app/application.h b/Extra2D/include/extra2d/app/application.h index ca3e549..70696fe 100644 --- a/Extra2D/include/extra2d/app/application.h +++ b/Extra2D/include/extra2d/app/application.h @@ -1,56 +1,98 @@ #pragma once -#include +#include #include #include namespace extra2d { -class Window; +class WindowModule; /** * @brief 应用程序类 */ class Application { public: - static Application& instance(); + static Application &instance(); - Application(const Application&) = delete; - Application& operator=(const Application&) = delete; + Application(const Application &) = delete; + Application &operator=(const Application &) = delete; - std::string name = "Extra2D App"; - std::string version = "1.0.0"; + std::string name = "Extra2D App"; + std::string version = "1.0.0"; - bool init(); - void shutdown(); - void run(); - void quit(); + /** + * @brief 创建并注册模块 + * @tparam T 模块类型 + * @tparam Args 构造函数参数类型 + * @param args 构造函数参数 + * @return 模块指针 + */ + template T *useModule(Args &&...args) { + return Lifecycle::instance().createModule(std::forward(args)...); + } - bool paused() const { return paused_; } - bool running() const { return running_; } - Window* window() const { return window_; } + /** + * @brief 获取模块 + * @tparam T 模块类型 + * @return 模块指针 + */ + template T *module() const { + return Lifecycle::instance().module(); + } - f32 dt() const { return dt_; } - f32 totalTime() const { return totalTime_; } - int fps() const { return fps_; } + /** + * @brief 创建并注册服务 + * @tparam T 服务接口类型 + * @tparam Impl 服务实现类型 + * @tparam Args 构造函数参数类型 + * @param args 构造函数参数 + * @return 服务实例 + */ + template + Ref useService(Args &&...args) { + return Lifecycle::instance().createService( + std::forward(args)...); + } + + /** + * @brief 获取服务 + * @tparam T 服务接口类型 + * @return 服务实例 + */ + template Ref service() const { + return Lifecycle::instance().service(); + } + + bool init(); + void shutdown(); + void run(); + void quit(); + + bool paused() const { return paused_; } + bool running() const { return running_; } + WindowModule *windowModule() const; + + f32 dt() const { return dt_; } + f32 totalTime() const { return totalTime_; } + int fps() const { return fps_; } private: - Application() = default; - ~Application(); + Application(); + ~Application(); - void mainLoop(); + void mainLoop(); - bool initialized_ = false; - bool running_ = false; - bool paused_ = false; - Window* window_ = nullptr; + bool initialized_ = false; + bool running_ = false; + bool paused_ = false; - f32 dt_ = 0.0f; - f32 totalTime_ = 0.0f; - u64 lastFrameTime_ = 0; - int frameCount_ = 0; - f32 fpsTimer_ = 0.0f; - int fps_ = 0; + f32 dt_ = 0.0f; + f32 totalTime_ = 0.0f; + u64 lastFrameTime_ = 0; + int frameCount_ = 0; + f32 fpsTimer_ = 0.0f; + int fps_ = 0; }; #define E2D_APP() ::extra2d::Application::instance() diff --git a/Extra2D/include/extra2d/core/lifecycle.h b/Extra2D/include/extra2d/core/lifecycle.h new file mode 100644 index 0000000..14a3beb --- /dev/null +++ b/Extra2D/include/extra2d/core/lifecycle.h @@ -0,0 +1,350 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace extra2d { + +class Application; + +/** + * @brief 编译期类型ID + */ +using TypeId = size_t; + +namespace detail { +inline TypeId nextTypeId() { + static TypeId id = 0; + return ++id; +} + +template +inline TypeId getTypeId() { + static TypeId id = nextTypeId(); + return id; +} +} // namespace detail + +/** + * @brief 生命周期单元类型 + */ +enum class UnitType : u8 { + Module, + Service +}; + +/** + * @brief 生命周期管理器 + * 统一管理模块和服务的初始化、更新和销毁 + */ +class Lifecycle { +public: + /** + * @brief 获取单例实例 + * @return Lifecycle 实例引用 + */ + static Lifecycle& instance(); + + Lifecycle(const Lifecycle&) = delete; + Lifecycle& operator=(const Lifecycle&) = delete; + + // ========== 注册接口 ========== + + /** + * @brief 注册模块 + * @tparam T 模块类型 + * @param module 模块实例 + */ + template + void addModule(Unique module) { + static_assert(std::is_base_of_v, "T must derive from Module"); + + std::unique_lock lock(mutex_); + + auto typeId = detail::getTypeId(); + + for (const auto& entry : modules_) { + if (entry.id == typeId) { + return; + } + } + + ModuleEntry entry; + entry.id = typeId; + entry.module = std::move(module); + modules_.push_back(std::move(entry)); + } + + /** + * @brief 创建并注册模块 + * @tparam T 模块类型 + * @tparam Args 构造函数参数类型 + * @param args 构造函数参数 + * @return 模块指针 + */ + template + T* createModule(Args&&... args) { + static_assert(std::is_base_of_v, "T must derive from Module"); + + auto module = ptr::unique(std::forward(args)...); + T* ptr = module.get(); + module->setApp(app_); + addModule(std::move(module)); + return ptr; + } + + /** + * @brief 注册服务 + * @tparam T 服务接口类型 + * @param service 服务实例 + */ + template + void addService(Ref service) { + static_assert(std::is_base_of_v, "T must derive from IService"); + + std::unique_lock lock(mutex_); + + auto typeId = std::type_index(typeid(T)); + + for (const auto& entry : services_) { + if (entry.id == typeId) { + return; + } + } + + ServiceEntry entry; + entry.id = typeId; + entry.service = std::static_pointer_cast(service); + services_.push_back(std::move(entry)); + } + + /** + * @brief 创建并注册服务 + * @tparam T 服务接口类型 + * @tparam Impl 服务实现类型 + * @tparam Args 构造函数参数类型 + * @param args 构造函数参数 + * @return 服务实例 + */ + template + Ref createService(Args&&... args) { + static_assert(std::is_base_of_v, "T must derive from IService"); + static_assert(std::is_base_of_v, "Impl must derive from T"); + + auto service = ptr::make(std::forward(args)...); + auto result = std::static_pointer_cast(service); + addService(result); + return result; + } + + // ========== 获取接口 ========== + + /** + * @brief 获取模块 + * @tparam T 模块类型 + * @return 模块指针,不存在返回 nullptr + */ + template + T* module() const { + static_assert(std::is_base_of_v, "T must derive from Module"); + + std::shared_lock lock(mutex_); + auto typeId = detail::getTypeId(); + + for (const auto& entry : modules_) { + if (entry.id == typeId && entry.module) { + return static_cast(entry.module.get()); + } + } + return nullptr; + } + + /** + * @brief 获取服务 + * @tparam T 服务接口类型 + * @return 服务实例,不存在返回 nullptr + */ + template + Ref service() const { + static_assert(std::is_base_of_v, "T must derive from IService"); + + std::shared_lock lock(mutex_); + auto typeId = std::type_index(typeid(T)); + + for (const auto& entry : services_) { + if (entry.id == typeId && entry.service) { + return std::static_pointer_cast(entry.service); + } + } + return nullptr; + } + + /** + * @brief 检查模块是否存在 + * @tparam T 模块类型 + * @return 存在返回 true + */ + template + bool hasModule() const { + std::shared_lock lock(mutex_); + auto typeId = detail::getTypeId(); + + for (const auto& entry : modules_) { + if (entry.id == typeId) { + return true; + } + } + return false; + } + + /** + * @brief 检查服务是否存在 + * @tparam T 服务接口类型 + * @return 存在返回 true + */ + template + bool hasService() const { + std::shared_lock lock(mutex_); + auto typeId = std::type_index(typeid(T)); + + for (const auto& entry : services_) { + if (entry.id == typeId) { + return true; + } + } + return false; + } + + // ========== 生命周期控制 ========== + + /** + * @brief 初始化所有单元(按依赖拓扑排序) + * @return 全部成功返回 true + */ + bool init(); + + /** + * @brief 更新所有单元 + * @param dt 帧间隔时间 + */ + void update(f32 dt); + + /** + * @brief 暂停所有单元 + */ + void pause(); + + /** + * @brief 恢复所有单元 + */ + void resume(); + + /** + * @brief 关闭所有单元(逆拓扑排序) + */ + void shutdown(); + + /** + * @brief 清空所有单元 + */ + void clear(); + + // ========== 配置接口 ========== + + /** + * @brief 设置 Application + * @param app Application 指针 + */ + void setApp(Application* app) { app_ = app; } + + // ========== 查询接口 ========== + + /** + * @brief 获取单元总数 + * @return 单元数量 + */ + size_t size() const { + std::shared_lock lock(mutex_); + return modules_.size() + services_.size(); + } + + /** + * @brief 获取模块数量 + * @return 模块数量 + */ + size_t moduleCount() const { + std::shared_lock lock(mutex_); + return modules_.size(); + } + + /** + * @brief 获取服务数量 + * @return 服务数量 + */ + size_t serviceCount() const { + std::shared_lock lock(mutex_); + return services_.size(); + } + +private: + Lifecycle() = default; + ~Lifecycle() = default; + + /** + * @brief 单元索引(用于依赖图) + */ + struct UnitIndex { + UnitType type; + size_t index; + }; + + /** + * @brief 模块条目 + */ + struct ModuleEntry { + TypeId id = 0; + Unique module; + }; + + /** + * @brief 服务条目 + */ + struct ServiceEntry { + std::type_index id; + Ref service; + + ServiceEntry() : id(typeid(void)) {} + }; + + /** + * @brief 按层级分组结果 + */ + std::vector> groupByLevel(); + + /** + * @brief 查找模块索引 + * @param type 类型索引 + * @return 模块索引,不存在返回 SIZE_MAX + */ + size_t findModuleIndex(std::type_index type) const; + + /** + * @brief 查找服务索引 + * @param type 类型索引 + * @return 服务索引,不存在返回 SIZE_MAX + */ + size_t findServiceIndex(std::type_index type) const; + + std::vector modules_; + std::vector services_; + mutable std::shared_mutex mutex_; + Application* app_ = nullptr; +}; + +} // namespace extra2d diff --git a/Extra2D/include/extra2d/core/module.h b/Extra2D/include/extra2d/core/module.h index 8eb5b17..a597034 100644 --- a/Extra2D/include/extra2d/core/module.h +++ b/Extra2D/include/extra2d/core/module.h @@ -1,9 +1,8 @@ #pragma once #include -#include -#include #include +#include namespace extra2d { @@ -15,63 +14,69 @@ class Application; */ class Module { public: - virtual ~Module() = default; + virtual ~Module() = default; - /** - * @brief 初始化模块 - * @return 初始化成功返回 true - */ - virtual bool init() = 0; + /** + * @brief 初始化模块 + * @return 初始化成功返回 true + */ + virtual bool init() = 0; - /** - * @brief 关闭模块 - */ - virtual void shutdown() = 0; + /** + * @brief 关闭模块 + */ + virtual void shutdown() = 0; - /** - * @brief 检查模块是否已初始化 - * @return 已初始化返回 true - */ - virtual bool ok() const = 0; + /** + * @brief 检查模块是否已初始化 + * @return 已初始化返回 true + */ + virtual bool ok() const = 0; - /** - * @brief 获取模块名称 - * @return 模块名称 - */ - virtual const char* name() const = 0; + /** + * @brief 获取模块名称 + * @return 模块名称 + */ + virtual const char *name() const = 0; - /** - * @brief 获取模块优先级(数值越小越优先) - * @return 优先级值 - */ - virtual int priority() const { return 100; } + /** + * @brief 获取模块优先级(数值越小越优先) + * @return 优先级值 + */ + virtual int priority() const { return 100; } - /** - * @brief 获取模块依赖列表 - * @return 依赖模块类型列表 - */ - virtual std::vector deps() const { return {}; } + /** + * @brief 获取模块依赖列表 + * @return 依赖模块类型列表 + */ + virtual std::vector deps() const { return {}; } - /** - * @brief 检查模块是否支持并行初始化 - * @return 支持并行初始化返回 true - */ - virtual bool parallel() const { return true; } + /** + * @brief 获取服务依赖列表 + * @return 依赖服务类型列表 + */ + virtual std::vector needsServices() const { return {}; } - /** - * @brief 设置所属Application - * @param app Application指针 - */ - void setApp(class Application* app) { app_ = app; } + /** + * @brief 检查模块是否支持并行初始化 + * @return 支持并行初始化返回 true + */ + virtual bool parallel() const { return true; } - /** - * @brief 获取Application - * @return Application指针 - */ - class Application* app() const { return app_; } + /** + * @brief 设置所属Application + * @param app Application指针 + */ + void setApp(class Application *app) { app_ = app; } + + /** + * @brief 获取Application + * @return Application指针 + */ + class Application *app() const { return app_; } protected: - class Application* app_ = nullptr; + class Application *app_ = nullptr; }; /** diff --git a/Extra2D/include/extra2d/core/registry.h b/Extra2D/include/extra2d/core/registry.h deleted file mode 100644 index 51818df..0000000 --- a/Extra2D/include/extra2d/core/registry.h +++ /dev/null @@ -1,166 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -namespace extra2d { - -class Application; - -/** - * @brief 编译期类型ID生成器 - */ -using TypeId = size_t; - -namespace detail { -inline TypeId nextTypeId() { - static TypeId id = 0; - return ++id; -} - -template inline TypeId getTypeId() { - static TypeId id = nextTypeId(); - return id; -} -} // namespace detail - -/** - * @brief 模块注册表 - * 管理模块的注册、拓扑排序和生命周期 - */ -class Registry { -public: - static constexpr size_t MAX_MODULES = 64; - - static Registry &instance(); - - Registry(const Registry &) = delete; - Registry &operator=(const Registry &) = delete; - - /** - * @brief 注册模块 - * @tparam T 模块类型 - * @tparam Args 构造函数参数类型 - * @param args 构造函数参数 - * @return 模块指针 - */ - template T *use(Args &&...args) { - static_assert(std::is_base_of_v, "T must derive from Module"); - - TypeId typeId = detail::getTypeId(); - - // 数组查找,O(n) 但 n 很小,缓存友好 - for (size_t i = 0; i < moduleCount_; ++i) { - if (modules_[i].id == typeId) { - return static_cast(modules_[i].module.get()); - } - } - - // 添加新模块 - if (moduleCount_ >= MAX_MODULES) { - return nullptr; // 模块数量超过上限 - } - - auto module = ptr::unique(std::forward(args)...); - T *ptr = module.get(); - module->setApp(app_); - - modules_[moduleCount_].id = typeId; - modules_[moduleCount_].module = std::move(module); - modules_[moduleCount_].valid = true; - ++moduleCount_; - - return ptr; - } - - /** - * @brief 获取模块 - * @tparam T 模块类型 - * @return 模块指针,不存在返回 nullptr - */ - template T *get() const { - TypeId typeId = detail::getTypeId(); - - for (size_t i = 0; i < moduleCount_; ++i) { - if (modules_[i].id == typeId && modules_[i].valid) { - return static_cast(modules_[i].module.get()); - } - } - return nullptr; - } - - /** - * @brief 获取模块(基类版本) - * @param typeIdx 类型索引 - * @return 模块指针 - */ - Module *get(std::type_index typeIdx) const { - for (size_t i = 0; i < moduleCount_; ++i) { - if (modules_[i].valid) { - Module *mod = modules_[i].module.get(); - if (std::type_index(typeid(*mod)) == typeIdx) { - return mod; - } - } - } - return nullptr; - } - - /** - * @brief 设置Application - */ - void setApp(Application *app) { app_ = app; } - - /** - * @brief 初始化所有模块(按优先级拓扑排序,支持并行初始化) - * @return 初始化成功返回 true - */ - bool init(); - - /** - * @brief 关闭所有模块 - */ - void shutdown(); - - /** - * @brief 清空所有模块 - */ - void clear(); - - /** - * @brief 获取模块数量 - */ - size_t size() const { return moduleCount_; } - -private: - Registry() = default; - ~Registry() = default; - - struct ModuleEntry { - TypeId id = 0; - Unique module; - bool valid = false; - }; - - /** - * @brief 拓扑排序模块 - * @return 排序后的模块列表 - */ - std::vector sort(); - - /** - * @brief 按层级对模块进行分组 - * 同一层级的模块没有相互依赖,可以并行初始化 - * @return 按层级分组的模块列表 - */ - std::vector> group(); - - std::array modules_; - size_t moduleCount_ = 0; - Application *app_ = nullptr; -}; - -} // namespace extra2d diff --git a/Extra2D/include/extra2d/core/result.h b/Extra2D/include/extra2d/core/result.h deleted file mode 100644 index 44385d6..0000000 --- a/Extra2D/include/extra2d/core/result.h +++ /dev/null @@ -1,398 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace extra2d { - -/** - * @brief 错误码枚举 - */ -enum class ErrorCode { - None = 0, - Unknown = 1, - InvalidArgument = 2, - OutOfMemory = 3, - FileNotFound = 4, - PermissionDenied = 5, - NotImplemented = 6, - AlreadyExists = 7, - NotInitialized = 8, - AlreadyInitialized = 9, - OperationFailed = 10, - Timeout = 11, - Cancelled = 12, - InvalidState = 13, - ResourceExhausted = 14, - Unavailable = 15, - DataLoss = 16, - Unauthenticated = 17, - PermissionDenied2 = 18, - ResourceNotFound = 19, - Aborted = 20, - OutOfRange = 21, - Unimplemented = 22, - Internal = 23, - DataCorrupted = 24, - RequestTooLarge = 25, - ResourceBusy = 26, - QuotaExceeded = 27, - DeadlineExceeded = 28, - LoadBalancing = 29, - NetworkError = 30, - ProtocolError = 31, - ServiceUnavailable = 32, - GatewayError = 33, - RateLimited = 34, - BadRequest = 35, - Unauthorized = 36, - Forbidden = 37, - NotFound = 38, - MethodNotAllowed = 39, - Conflict = 40, - Gone = 41, - LengthRequired = 42, - PreconditionFailed = 43, - PayloadTooLarge = 44, - UriTooLong = 45, - UnsupportedMediaType = 46, - RangeNotSatisfiable = 47, - ExpectationFailed = 48, - ImATeapot = 49, - MisdirectedRequest = 50, - UnprocessableEntity = 51, - Locked = 52, - FailedDependency = 53, - TooEarly = 54, - UpgradeRequired = 55, - PreconditionRequired = 56, - TooManyRequests = 57, - RequestHeaderFieldsTooLarge = 58, - UnavailableForLegalReasons = 59 -}; - -/** - * @brief 错误信息结构 - */ -struct Error { - ErrorCode code = ErrorCode::None; - std::string message; - std::string file; - int line = 0; - - Error() = default; - Error(ErrorCode c, const std::string& msg) : code(c), message(msg) {} - Error(ErrorCode c, const std::string& msg, const std::string& f, int l) - : code(c), message(msg), file(f), line(l) {} - - bool ok() const { return code == ErrorCode::None; } - - static Error none() { return Error(); } - static Error unknown(const std::string& msg) { return Error(ErrorCode::Unknown, msg); } - static Error invalidArgument(const std::string& msg) { return Error(ErrorCode::InvalidArgument, msg); } - static Error outOfMemory(const std::string& msg) { return Error(ErrorCode::OutOfMemory, msg); } - static Error fileNotFound(const std::string& msg) { return Error(ErrorCode::FileNotFound, msg); } - static Error permissionDenied(const std::string& msg) { return Error(ErrorCode::PermissionDenied, msg); } - static Error notImplemented(const std::string& msg) { return Error(ErrorCode::NotImplemented, msg); } - static Error alreadyExists(const std::string& msg) { return Error(ErrorCode::AlreadyExists, msg); } - static Error notInitialized(const std::string& msg) { return Error(ErrorCode::NotInitialized, msg); } - static Error alreadyInitialized(const std::string& msg) { return Error(ErrorCode::AlreadyInitialized, msg); } - static Error operationFailed(const std::string& msg) { return Error(ErrorCode::OperationFailed, msg); } - static Error timeout(const std::string& msg) { return Error(ErrorCode::Timeout, msg); } - static Error cancelled(const std::string& msg) { return Error(ErrorCode::Cancelled, msg); } - static Error invalidState(const std::string& msg) { return Error(ErrorCode::InvalidState, msg); } - static Error resourceExhausted(const std::string& msg) { return Error(ErrorCode::ResourceExhausted, msg); } - static Error unavailable(const std::string& msg) { return Error(ErrorCode::Unavailable, msg); } - static Error dataLoss(const std::string& msg) { return Error(ErrorCode::DataLoss, msg); } - static Error unauthenticated(const std::string& msg) { return Error(ErrorCode::Unauthenticated, msg); } - static Error permissionDenied2(const std::string& msg) { return Error(ErrorCode::PermissionDenied2, msg); } - static Error resourceNotFound(const std::string& msg) { return Error(ErrorCode::ResourceNotFound, msg); } - static Error aborted(const std::string& msg) { return Error(ErrorCode::Aborted, msg); } - static Error outOfRange(const std::string& msg) { return Error(ErrorCode::OutOfRange, msg); } - static Error unimplemented(const std::string& msg) { return Error(ErrorCode::Unimplemented, msg); } - static Error internal(const std::string& msg) { return Error(ErrorCode::Internal, msg); } - static Error dataCorrupted(const std::string& msg) { return Error(ErrorCode::DataCorrupted, msg); } - static Error requestTooLarge(const std::string& msg) { return Error(ErrorCode::RequestTooLarge, msg); } - static Error resourceBusy(const std::string& msg) { return Error(ErrorCode::ResourceBusy, msg); } - static Error quotaExceeded(const std::string& msg) { return Error(ErrorCode::QuotaExceeded, msg); } - static Error deadlineExceeded(const std::string& msg) { return Error(ErrorCode::DeadlineExceeded, msg); } - static Error loadBalancing(const std::string& msg) { return Error(ErrorCode::LoadBalancing, msg); } - static Error networkError(const std::string& msg) { return Error(ErrorCode::NetworkError, msg); } - static Error protocolError(const std::string& msg) { return Error(ErrorCode::ProtocolError, msg); } - static Error serviceUnavailable(const std::string& msg) { return Error(ErrorCode::ServiceUnavailable, msg); } - static Error gatewayError(const std::string& msg) { return Error(ErrorCode::GatewayError, msg); } - static Error rateLimited(const std::string& msg) { return Error(ErrorCode::RateLimited, msg); } - static Error badRequest(const std::string& msg) { return Error(ErrorCode::BadRequest, msg); } - static Error unauthorized(const std::string& msg) { return Error(ErrorCode::Unauthorized, msg); } - static Error forbidden(const std::string& msg) { return Error(ErrorCode::Forbidden, msg); } - static Error notFound(const std::string& msg) { return Error(ErrorCode::NotFound, msg); } - static Error methodNotAllowed(const std::string& msg) { return Error(ErrorCode::MethodNotAllowed, msg); } - static Error conflict(const std::string& msg) { return Error(ErrorCode::Conflict, msg); } - static Error gone(const std::string& msg) { return Error(ErrorCode::Gone, msg); } - static Error lengthRequired(const std::string& msg) { return Error(ErrorCode::LengthRequired, msg); } - static Error preconditionFailed(const std::string& msg) { return Error(ErrorCode::PreconditionFailed, msg); } - static Error payloadTooLarge(const std::string& msg) { return Error(ErrorCode::PayloadTooLarge, msg); } - static Error uriTooLong(const std::string& msg) { return Error(ErrorCode::UriTooLong, msg); } - static Error unsupportedMediaType(const std::string& msg) { return Error(ErrorCode::UnsupportedMediaType, msg); } - static Error rangeNotSatisfiable(const std::string& msg) { return Error(ErrorCode::RangeNotSatisfiable, msg); } - static Error expectationFailed(const std::string& msg) { return Error(ErrorCode::ExpectationFailed, msg); } - static Error imATeapot(const std::string& msg) { return Error(ErrorCode::ImATeapot, msg); } - static Error misdirectedRequest(const std::string& msg) { return Error(ErrorCode::MisdirectedRequest, msg); } - static Error unprocessableEntity(const std::string& msg) { return Error(ErrorCode::UnprocessableEntity, msg); } - static Error locked(const std::string& msg) { return Error(ErrorCode::Locked, msg); } - static Error failedDependency(const std::string& msg) { return Error(ErrorCode::FailedDependency, msg); } - static Error tooEarly(const std::string& msg) { return Error(ErrorCode::TooEarly, msg); } - static Error upgradeRequired(const std::string& msg) { return Error(ErrorCode::UpgradeRequired, msg); } - static Error preconditionRequired(const std::string& msg) { return Error(ErrorCode::PreconditionRequired, msg); } - static Error tooManyRequests(const std::string& msg) { return Error(ErrorCode::TooManyRequests, msg); } - static Error requestHeaderFieldsTooLarge(const std::string& msg) { return Error(ErrorCode::RequestHeaderFieldsTooLarge, msg); } - static Error unavailableForLegalReasons(const std::string& msg) { return Error(ErrorCode::UnavailableForLegalReasons, msg); } -}; - -/** - * @brief Result类型,用于错误处理 - * @tparam T 成功时的值类型 - * @tparam E 错误类型,默认为Error - */ -template -class Result { -public: - Result() : hasValue_(false) { - new (&storage_.error) E(); - } - - ~Result() { - if (hasValue_) { - storage_.value.~T(); - } else { - storage_.error.~E(); - } - } - - Result(const Result& other) : hasValue_(other.hasValue_) { - if (hasValue_) { - new (&storage_.value) T(other.storage_.value); - } else { - new (&storage_.error) E(other.storage_.error); - } - } - - Result(Result&& other) noexcept : hasValue_(other.hasValue_) { - if (hasValue_) { - new (&storage_.value) T(std::move(other.storage_.value)); - } else { - new (&storage_.error) E(std::move(other.storage_.error)); - } - } - - Result& operator=(const Result& other) { - if (this != &other) { - this->~Result(); - hasValue_ = other.hasValue_; - if (hasValue_) { - new (&storage_.value) T(other.storage_.value); - } else { - new (&storage_.error) E(other.storage_.error); - } - } - return *this; - } - - Result& operator=(Result&& other) noexcept { - if (this != &other) { - this->~Result(); - hasValue_ = other.hasValue_; - if (hasValue_) { - new (&storage_.value) T(std::move(other.storage_.value)); - } else { - new (&storage_.error) E(std::move(other.storage_.error)); - } - } - return *this; - } - - static Result ok(T value) { - Result result; - result.hasValue_ = true; - new (&result.storage_.value) T(std::move(value)); - return result; - } - - static Result err(E error) { - Result result; - result.hasValue_ = false; - new (&result.storage_.error) E(std::move(error)); - return result; - } - - bool ok() const { return hasValue_; } - bool isOk() const { return hasValue_; } - bool isErr() const { return !hasValue_; } - - T& value() & { - return storage_.value; - } - - const T& value() const & { - return storage_.value; - } - - T&& value() && { - return std::move(storage_.value); - } - - E& error() & { - return storage_.error; - } - - const E& error() const & { - return storage_.error; - } - - E&& error() && { - return std::move(storage_.error); - } - - T valueOr(T defaultValue) const { - return hasValue_ ? storage_.value : std::move(defaultValue); - } - - template - Result map(F&& f) { - if (hasValue_) { - return Result::ok(f(storage_.value)); - } - return *this; - } - - template - Result mapErr(F&& f) { - if (!hasValue_) { - return Result::err(f(storage_.error)); - } - return *this; - } - - template - auto andThen(F&& f) -> decltype(f(std::declval())) { - if (hasValue_) { - return f(storage_.value); - } - return Result()))::ValueType, E>::err(storage_.error); - } - - template - Result orElse(F&& f) { - if (!hasValue_) { - return f(storage_.error); - } - return *this; - } - -private: - union Storage { - T value; - E error; - - Storage() {} - ~Storage() {} - } storage_; - - bool hasValue_; -}; - -// 特化void类型 -template -class Result { -public: - Result() : hasValue_(true) {} - - ~Result() { - if (!hasValue_) { - storage_.error.~E(); - } - } - - Result(const Result& other) : hasValue_(other.hasValue_) { - if (!hasValue_) { - new (&storage_.error) E(other.storage_.error); - } - } - - Result(Result&& other) noexcept : hasValue_(other.hasValue_) { - if (!hasValue_) { - new (&storage_.error) E(std::move(other.storage_.error)); - } - } - - Result& operator=(const Result& other) { - if (this != &other) { - this->~Result(); - hasValue_ = other.hasValue_; - if (!hasValue_) { - new (&storage_.error) E(other.storage_.error); - } - } - return *this; - } - - Result& operator=(Result&& other) noexcept { - if (this != &other) { - this->~Result(); - hasValue_ = other.hasValue_; - if (!hasValue_) { - new (&storage_.error) E(std::move(other.storage_.error)); - } - } - return *this; - } - - static Result ok() { - return Result(); - } - - static Result err(E error) { - Result result; - result.hasValue_ = false; - new (&result.storage_.error) E(std::move(error)); - return result; - } - - bool ok() const { return hasValue_; } - bool isOk() const { return hasValue_; } - bool isErr() const { return !hasValue_; } - - E& error() & { - return storage_.error; - } - - const E& error() const & { - return storage_.error; - } - - E&& error() && { - return std::move(storage_.error); - } - -private: - union Storage { - E error; - - Storage() {} - ~Storage() {} - } storage_; - - bool hasValue_; -}; - -// 便捷宏 -#define E2D_TRY(result) \ - do { \ - auto _res = (result); \ - if (!_res.ok()) { \ - return Result::err(_res.error()); \ - } \ - } while(0) - -} // namespace extra2d diff --git a/Extra2D/include/extra2d/core/service_interface.h b/Extra2D/include/extra2d/core/service_interface.h index dcc3416..1b40dbd 100644 --- a/Extra2D/include/extra2d/core/service_interface.h +++ b/Extra2D/include/extra2d/core/service_interface.h @@ -2,6 +2,8 @@ #include #include +#include +#include namespace extra2d { @@ -48,6 +50,7 @@ struct ServiceInfo { */ class IService { friend class ServiceLocator; + friend class Lifecycle; public: virtual ~IService() = default; @@ -69,6 +72,18 @@ public: */ virtual void shutdown() = 0; + /** + * @brief 获取服务依赖列表 + * @return 依赖服务类型列表 + */ + virtual std::vector deps() const { return {}; } + + /** + * @brief 获取模块依赖列表 + * @return 依赖模块类型列表 + */ + virtual std::vector needsModules() const { return {}; } + /** * @brief 暂停服务 */ diff --git a/Extra2D/include/extra2d/core/service_locator.h b/Extra2D/include/extra2d/core/service_locator.h deleted file mode 100644 index 565627e..0000000 --- a/Extra2D/include/extra2d/core/service_locator.h +++ /dev/null @@ -1,307 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace extra2d { - -/** - * @brief 服务工厂函数类型 - */ -template using ServiceFactory = Fn()>; - -/** - * @brief 服务定位器 - * 实现依赖注入和服务发现模式,解耦模块间依赖 - * - * 特性: - * - 类型安全的服务注册和获取 - * - 支持服务工厂延迟创建 - * - 支持服务依赖声明 - * - 线程安全(读写锁) - * - 支持 Mock 测试 - */ -class ServiceLocator { -public: - /** - * @brief 获取单例实例 - * @return 服务定位器实例引用 - */ - static ServiceLocator &instance(); - - ServiceLocator(const ServiceLocator &) = delete; - ServiceLocator &operator=(const ServiceLocator &) = delete; - - /** - * @brief 注册服务实例 - * @tparam T 服务接口类型 - * @param svc 服务实例 - */ - template void add(Ref svc) { - static_assert(std::is_base_of_v, - "T must derive from IService"); - - std::unique_lock lock(mutex_); - auto typeId = std::type_index(typeid(T)); - services_[typeId] = std::static_pointer_cast(svc); - orderedServices_.push_back(svc); - sort(); - } - - /** - * @brief 注册服务工厂 - * @tparam T 服务接口类型 - * @param fn 服务工厂函数 - */ - template void setFactory(ServiceFactory fn) { - static_assert(std::is_base_of_v, - "T must derive from IService"); - - std::unique_lock lock(mutex_); - auto typeId = std::type_index(typeid(T)); - factories_[typeId] = [fn]() -> Ref { - return std::static_pointer_cast(fn()); - }; - - // 立即创建服务实例并添加到有序列表 - auto svc = factories_[typeId](); - services_[typeId] = svc; - orderedServices_.push_back(svc); - sort(); - } - - /** - * @brief 获取服务实例 - * @tparam T 服务接口类型 - * @return 服务实例,不存在返回 nullptr - */ - template Ref get() const { - static_assert(std::is_base_of_v, - "T must derive from IService"); - - auto typeId = std::type_index(typeid(T)); - - // 读锁查询 - std::shared_lock lock(mutex_); - - auto it = services_.find(typeId); - if (it != services_.end()) { - return std::static_pointer_cast(it->second); - } - - auto factoryIt = factories_.find(typeId); - if (factoryIt != factories_.end()) { - auto svc = factoryIt->second(); - services_[typeId] = svc; - return std::static_pointer_cast(svc); - } - - return nullptr; - } - - /** - * @brief 尝试获取服务实例(不创建) - * @tparam T 服务接口类型 - * @return 服务实例,不存在返回 nullptr - */ - template Ref tryGet() const { - static_assert(std::is_base_of_v, - "T must derive from IService"); - - auto typeId = std::type_index(typeid(T)); - - // 读锁查询 - std::shared_lock lock(mutex_); - auto it = services_.find(typeId); - if (it != services_.end()) { - return std::static_pointer_cast(it->second); - } - return nullptr; - } - - /** - * @brief 检查服务是否已注册 - * @tparam T 服务接口类型 - * @return 已注册返回 true - */ - template bool has() const { - std::shared_lock lock(mutex_); - auto typeId = std::type_index(typeid(T)); - return services_.find(typeId) != services_.end() || - factories_.find(typeId) != factories_.end(); - } - - /** - * @brief 注销服务 - * @tparam T 服务接口类型 - */ - template void remove() { - std::unique_lock lock(mutex_); - auto typeId = std::type_index(typeid(T)); - - auto it = services_.find(typeId); - if (it != services_.end()) { - auto svc = it->second; - services_.erase(it); - - auto orderIt = - std::find(orderedServices_.begin(), orderedServices_.end(), svc); - if (orderIt != orderedServices_.end()) { - orderedServices_.erase(orderIt); - } - } - - factories_.erase(typeId); - } - - /** - * @brief 初始化所有已注册的服务 - * @return 所有服务初始化成功返回 true - */ - bool init(); - - /** - * @brief 关闭所有服务 - */ - void shutdown(); - - /** - * @brief 更新所有服务 - * @param dt 帧间隔时间 - */ - void update(f32 dt); - - /** - * @brief 暂停所有服务 - */ - void pause(); - - /** - * @brief 恢复所有服务 - */ - void resume(); - - /** - * @brief 获取所有服务(按优先级排序) - * @return 服务列表 - */ - std::vector> all() const; - - /** - * @brief 清空所有服务和工厂 - */ - void clear(); - - /** - * @brief 获取已注册服务数量 - * @return 服务数量 - */ - size_t size() const { return services_.size(); } - -private: - ServiceLocator() = default; - ~ServiceLocator() = default; - - /** - * @brief 按优先级排序服务 - */ - void sort(); - - mutable std::unordered_map> services_; - std::unordered_map()>> - factories_; - std::vector> orderedServices_; - mutable std::shared_mutex mutex_; -}; - -/** - * @brief 服务注册器 - * 用于静态注册服务 - */ -template class ServiceRegistrar { -public: - explicit ServiceRegistrar(ServiceFactory fn = nullptr) { - if (fn) { - ServiceLocator::instance().setFactory(fn); - } else { - ServiceLocator::instance().setFactory( - []() -> Ref { - return ptr::make(); - }); - } - } -}; - -/** - * @brief 服务注册元数据模板 - * 使用模板元编程实现编译期服务注册 - * 通过静态成员变量的初始化触发注册 - */ -template struct ServiceAutoReg { - /** - * @brief 注册标记,访问此变量时触发服务注册 - */ - static const bool registered; - - /** - * @brief 执行实际的服务注册 - * @return true 表示注册成功 - */ - static bool doRegister() { - ::extra2d::ServiceLocator::instance().setFactory( - []() -> ::extra2d::Ref { - return ::extra2d::ptr::make(); - }); - return true; - } -}; - -// 静态成员定义,在此处触发注册 -template -const bool ServiceAutoReg::registered = - ServiceAutoReg::doRegister(); - -/** - * @brief 服务注册元数据(带自定义工厂) - */ -template struct ServiceAutoRegFactory { - template struct Impl { - static const bool registered; - - static bool doRegister(Factory fn) { - ::extra2d::ServiceLocator::instance().setFactory(fn); - return true; - } - }; -}; - -template -template -const bool ServiceAutoRegFactory::Impl::registered = - ServiceAutoRegFactory::Impl::doRegister(Factory{}); - -/** - * @brief 自动注册服务宏(元数据驱动) - * 在服务实现类中使用,通过模板元编程实现自动注册 - * 比静态对象更可靠,不易被编译器优化 - */ -#define E2D_AUTO_REGISTER_SERVICE(Interface, Implementation) \ - static inline const bool E2D_CONCAT(_service_reg_, __LINE__) = \ - ServiceAutoReg::registered - -/** - * @brief 带自定义工厂的自动注册服务宏(元数据驱动) - */ -#define E2D_AUTO_REGISTER_SERVICE_FACTORY(Interface, Factory) \ - static inline const bool E2D_CONCAT(_service_factory_reg_, __LINE__) = \ - ServiceAutoRegFactory::Impl::registered - -} // namespace extra2d diff --git a/Extra2D/include/extra2d/core/service_registry.h b/Extra2D/include/extra2d/core/service_registry.h deleted file mode 100644 index 3a855f2..0000000 --- a/Extra2D/include/extra2d/core/service_registry.h +++ /dev/null @@ -1,137 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -namespace extra2d { - -/** - * @brief 服务注册信息 - */ -struct ServiceRegistration { - std::string name; - ServicePriority priority; - std::function()> factory; - bool enabled = true; -}; - -/** - * @brief 服务注册表 - * 管理服务的注册信息,支持延迟创建和配置 - */ -class ServiceRegistry { -public: - /** - * @brief 获取单例实例 - * @return 服务注册表实例引用 - */ - static ServiceRegistry& instance(); - - ServiceRegistry(const ServiceRegistry&) = delete; - ServiceRegistry& operator=(const ServiceRegistry&) = delete; - - /** - * @brief 注册服务 - * @tparam T 服务接口类型 - * @tparam Impl 服务实现类型 - * @param name 服务名称 - * @param priority 服务优先级 - */ - template - void add(const std::string& name, ServicePriority priority) { - static_assert(std::is_base_of_v, - "T must derive from IService"); - static_assert(std::is_base_of_v, - "Impl must derive from T"); - - ServiceRegistration reg; - reg.name = name; - reg.priority = priority; - reg.factory = []() -> Ref { - return std::static_pointer_cast(ptr::make()); - }; - registrations_.push_back(reg); - } - - /** - * @brief 注册服务(带工厂函数) - * @tparam T 服务接口类型 - * @param name 服务名称 - * @param priority 服务优先级 - * @param factory 工厂函数 - */ - template - void addWithFactory( - const std::string& name, - ServicePriority priority, - std::function()> factory) { - static_assert(std::is_base_of_v, - "T must derive from IService"); - - ServiceRegistration reg; - reg.name = name; - reg.priority = priority; - reg.factory = [factory]() -> Ref { - return std::static_pointer_cast(factory()); - }; - registrations_.push_back(reg); - } - - /** - * @brief 启用/禁用服务 - * @param name 服务名称 - * @param enabled 是否启用 - */ - void setEnabled(const std::string& name, bool enabled); - - /** - * @brief 创建所有已注册的服务 - * 并注册到 ServiceLocator - */ - void createAll(); - - /** - * @brief 获取所有注册信息 - * @return 注册信息列表 - */ - const std::vector& all() const { - return registrations_; - } - - /** - * @brief 清空所有注册 - */ - void clear() { - registrations_.clear(); - } - -private: - ServiceRegistry() = default; - ~ServiceRegistry() = default; - - std::vector registrations_; -}; - -/** - * @brief 自动服务注册器 - * 在全局作用域使用,自动注册服务 - */ -template -class AutoServiceRegistrar { -public: - AutoServiceRegistrar(const std::string& name, ServicePriority priority) { - ServiceRegistry::instance().add( - name, priority); - } -}; - -} - -#define E2D_REGISTER_SERVICE_AUTO(Interface, Implementation, Name, Priority) \ - namespace { \ - static ::extra2d::AutoServiceRegistrar \ - E2D_CONCAT(auto_service_registrar_, __LINE__)(Name, Priority); \ - } diff --git a/Extra2D/include/extra2d/extra2d.h b/Extra2D/include/extra2d/extra2d.h index 11b7702..9971dfe 100644 --- a/Extra2D/include/extra2d/extra2d.h +++ b/Extra2D/include/extra2d/extra2d.h @@ -5,14 +5,15 @@ // Core #include +#include #include #include -#include #include // Window #include #include +#include #include // Window - SDL2 + OpenGL @@ -21,6 +22,7 @@ #include #include #include +#include #include #include #include diff --git a/Extra2D/include/extra2d/render/render_module.h b/Extra2D/include/extra2d/render/render_module.h new file mode 100644 index 0000000..ea93cf5 --- /dev/null +++ b/Extra2D/include/extra2d/render/render_module.h @@ -0,0 +1,129 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace extra2d { + +/** + * @brief 渲染模块配置结构 + */ +struct RenderCfg { + int glMajor = 4; + int glMinor = 5; + bool useES = false; + int redBits = 8; + int greenBits = 8; + int blueBits = 8; + int alphaBits = 8; + int depthBits = 24; + int stencilBits = 8; + bool doubleBuffer = true; + int msaaSamples = 0; + bool vsync = true; + int priority = 10; + + RenderCfg() = default; +}; + +/** + * @brief 渲染模块 + * 管理 OpenGL 渲染设备和上下文 + */ +class RenderModule : public Module { +public: + /** + * @brief 构造函数(Lambda 配置) + * @param configFn 配置函数 + */ + explicit RenderModule(std::function configFn); + + /** + * @brief 析构函数 + */ + ~RenderModule() override; + + /** + * @brief 初始化渲染模块 + * @return 初始化成功返回 true + */ + bool init() override; + + /** + * @brief 关闭渲染模块 + */ + void shutdown() override; + + /** + * @brief 检查模块是否已初始化 + * @return 已初始化返回 true + */ + bool ok() const override { return initialized_; } + + /** + * @brief 获取模块名称 + * @return 模块名称 + */ + const char *name() const override { return "RenderModule"; } + + /** + * @brief 获取模块优先级 + * @return 优先级值(渲染模块在窗口模块之后初始化) + */ + int priority() const override { return cfg_.priority; } + + /** + * @brief 获取模块依赖 + * @return 依赖 WindowModule + */ + std::vector deps() const override { + return {std::type_index(typeid(WindowModule))}; + } + + /** + * @brief 获取服务依赖 + * @return 依赖 ILogger + */ + std::vector needsServices() const override { + return {std::type_index(typeid(ILogger))}; + } + + /** + * @brief 渲染模块不支持并行初始化(OpenGL 上下文需要串行创建) + * @return false + */ + bool parallel() const override { return false; } + + /** + * @brief 交换缓冲区 + */ + void swapBuffers(); + + /** + * @brief 设置 VSync + * @param enabled 是否启用 + */ + void setVSync(bool enabled); + + /** + * @brief 获取渲染设备 + * @return 渲染设备引用 + */ + RenderDevice &device() { return RenderDevice::instance(); } + + /** + * @brief 获取渲染能力信息 + * @return 渲染能力信息 + */ + const RenderCaps &caps() const { return RenderDevice::instance().caps(); } + +private: + RenderCfg cfg_; + bool initialized_ = false; +}; + +} // namespace extra2d diff --git a/Extra2D/include/extra2d/services/asset_service.h b/Extra2D/include/extra2d/services/asset_service.h index e4e4982..f8adf9a 100644 --- a/Extra2D/include/extra2d/services/asset_service.h +++ b/Extra2D/include/extra2d/services/asset_service.h @@ -9,8 +9,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -232,6 +232,13 @@ public: return i; } + /** + * @brief 资源服务依赖日志服务 + */ + std::vector deps() const override { + return { std::type_index(typeid(ILogger)) }; + } + bool init() override; void shutdown() override; @@ -327,8 +334,6 @@ private: * @return 资源类型索引 */ std::type_index inferType(const std::string &path); - - E2D_AUTO_REGISTER_SERVICE(IAssetService, AssetService); }; } // namespace extra2d diff --git a/Extra2D/include/extra2d/services/event_service.h b/Extra2D/include/extra2d/services/event_service.h index ae60d64..7e6d941 100644 --- a/Extra2D/include/extra2d/services/event_service.h +++ b/Extra2D/include/extra2d/services/event_service.h @@ -1,9 +1,13 @@ #pragma once #include -#include +#include #include #include +#include +#include +#include +#include namespace extra2d { @@ -12,23 +16,23 @@ namespace extra2d { */ class IEventService : public IService { public: - virtual ~IEventService() = default; + virtual ~IEventService() = default; - virtual void push(const Event& event) = 0; - virtual void push(Event&& event) = 0; - virtual bool poll(Event& event) = 0; + virtual void push(const Event &event) = 0; + virtual void push(Event &&event) = 0; + virtual bool poll(Event &event) = 0; - virtual ListenerID on(EventType type, EventDispatcher::EventFn fn) = 0; - virtual void off(ListenerID id) = 0; - virtual void offAll(EventType type) = 0; - virtual void offAll() = 0; + virtual ListenerID on(EventType type, EventDispatcher::EventFn fn) = 0; + virtual void off(ListenerID id) = 0; + virtual void offAll(EventType type) = 0; + virtual void offAll() = 0; - virtual void dispatch(Event& event) = 0; - virtual void process() = 0; + virtual void dispatch(Event &event) = 0; + virtual void process() = 0; - virtual size_t listenerCount(EventType type) const = 0; - virtual size_t totalListeners() const = 0; - virtual size_t queueSize() const = 0; + virtual size_t listenerCount(EventType type) const = 0; + virtual size_t totalListeners() const = 0; + virtual size_t queueSize() const = 0; }; /** @@ -36,42 +40,53 @@ public: */ class EventService : public IEventService { public: - EventService(); - ~EventService() override = default; + EventService(); + ~EventService() override = default; - ServiceInfo info() const override; + ServiceInfo info() const override; - bool init() override; - void shutdown() override; - void update(f32 dt) override; + /** + * @brief 事件服务依赖日志服务 + */ + std::vector deps() const override { + return {std::type_index(typeid(ILogger))}; + } - void push(const Event& event) override; - void push(Event&& event) override; - bool poll(Event& event) override; + /** + * @brief 事件服务依赖窗口模块 + */ + std::vector needsModules() const override { + return {std::type_index(typeid(WindowModule))}; + } - ListenerID on(EventType type, EventDispatcher::EventFn fn) override; - void off(ListenerID id) override; - void offAll(EventType type) override; - void offAll() override; + bool init() override; + void shutdown() override; + void update(f32 dt) override; - void dispatch(Event& event) override; - void process() override; + void push(const Event &event) override; + void push(Event &&event) override; + bool poll(Event &event) override; - size_t listenerCount(EventType type) const override; - size_t totalListeners() const override; - size_t queueSize() const override; + ListenerID on(EventType type, EventDispatcher::EventFn fn) override; + void off(ListenerID id) override; + void offAll(EventType type) override; + void offAll() override; - EventQueue& queue() { return queue_; } - const EventQueue& queue() const { return queue_; } - EventDispatcher& dispatcher() { return dispatcher_; } - const EventDispatcher& dispatcher() const { return dispatcher_; } + void dispatch(Event &event) override; + void process() override; + + size_t listenerCount(EventType type) const override; + size_t totalListeners() const override; + size_t queueSize() const override; + + EventQueue &queue() { return queue_; } + const EventQueue &queue() const { return queue_; } + EventDispatcher &dispatcher() { return dispatcher_; } + const EventDispatcher &dispatcher() const { return dispatcher_; } private: - EventQueue queue_; - EventDispatcher dispatcher_; - - // 服务注册元数据 - E2D_AUTO_REGISTER_SERVICE(IEventService, EventService); + EventQueue queue_; + EventDispatcher dispatcher_; }; -} +} // namespace extra2d diff --git a/Extra2D/include/extra2d/services/logger_service.h b/Extra2D/include/extra2d/services/logger_service.h index 43a3c48..53cd231 100644 --- a/Extra2D/include/extra2d/services/logger_service.h +++ b/Extra2D/include/extra2d/services/logger_service.h @@ -1,7 +1,7 @@ #pragma once +#include #include -#include #include #include #include @@ -74,6 +74,11 @@ public: i.priority = ServicePriority::Core; return i; } + + /** + * @brief 日志服务无依赖 + */ + std::vector deps() const override { return {}; } }; /** @@ -117,8 +122,6 @@ private: LogColor levelColors_[7]; class Impl; Unique impl_; - - E2D_AUTO_REGISTER_SERVICE(ILogger, ConsoleLogger); }; } // namespace extra2d @@ -173,16 +176,16 @@ inline std::string format_str(const char *fmt) { return fmt; } // 日志宏 #define E2D_LOG(lvl, ...) \ do { \ - if (auto log = ::extra2d::ServiceLocator::instance() \ - .tryGet<::extra2d::ILogger>()) \ + if (auto log = \ + ::extra2d::Lifecycle::instance().service<::extra2d::ILogger>()) \ if (log->enabled(lvl)) \ log->log(lvl, ::extra2d::format_str(__VA_ARGS__)); \ } while (0) #define E2D_LOG_CAT(lvl, cat, ...) \ do { \ - if (auto log = ::extra2d::ServiceLocator::instance() \ - .tryGet<::extra2d::ILogger>()) \ + if (auto log = \ + ::extra2d::Lifecycle::instance().service<::extra2d::ILogger>()) \ if (log->enabled(lvl)) { \ std::string _e2d_msg = ::extra2d::format_str(__VA_ARGS__); \ log->log(lvl, ::extra2d::format_str("[{}] {}", cat, _e2d_msg)); \ diff --git a/Extra2D/include/extra2d/services/timer_service.h b/Extra2D/include/extra2d/services/timer_service.h index c7b112b..068c87f 100644 --- a/Extra2D/include/extra2d/services/timer_service.h +++ b/Extra2D/include/extra2d/services/timer_service.h @@ -1,8 +1,11 @@ #pragma once #include -#include +#include +#include #include +#include +#include namespace extra2d { @@ -32,6 +35,13 @@ public: ServiceInfo info() const override; + /** + * @brief 计时器服务依赖日志服务 + */ + std::vector deps() const override { + return { std::type_index(typeid(ILogger)) }; + } + bool init() override; void shutdown() override; void update(f32 dt) override; @@ -49,9 +59,6 @@ public: private: TimerManager mgr_; - - // 服务注册元数据 - E2D_AUTO_REGISTER_SERVICE(ITimerService, TimerService); }; } diff --git a/Extra2D/include/extra2d/window/window.h b/Extra2D/include/extra2d/window/window.h index 0cafe2c..ed0aa33 100644 --- a/Extra2D/include/extra2d/window/window.h +++ b/Extra2D/include/extra2d/window/window.h @@ -8,6 +8,9 @@ namespace extra2d { +/** + * @brief 窗口配置结构体 + */ struct WindowConfig { std::string title = "Extra2D Application"; int width = 1280; diff --git a/Extra2D/include/extra2d/window/window_module.h b/Extra2D/include/extra2d/window/window_module.h new file mode 100644 index 0000000..d14700c --- /dev/null +++ b/Extra2D/include/extra2d/window/window_module.h @@ -0,0 +1,164 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace extra2d { + +/** + * @brief 窗口模块配置结构 + */ +struct WindowCfg { + std::string title = "Extra2D"; + int width = 1280; + int height = 720; + bool fullscreen = false; + bool resizable = true; + bool centerWindow = true; + int priority = 0; + + WindowCfg() = default; +}; + +/** + * @brief 窗口模块 + * 管理窗口创建和生命周期 + */ +class WindowModule : public Module { +public: + /** + * @brief 构造函数(Lambda 配置) + * @param configFn 配置函数 + */ + explicit WindowModule(std::function configFn); + + /** + * @brief 析构函数 + */ + ~WindowModule() override; + + /** + * @brief 初始化窗口模块 + * @return 初始化成功返回 true + */ + bool init() override; + + /** + * @brief 关闭窗口模块 + */ + void shutdown() override; + + /** + * @brief 检查模块是否已初始化 + * @return 已初始化返回 true + */ + bool ok() const override { return initialized_; } + + /** + * @brief 获取模块名称 + * @return 模块名称 + */ + const char *name() const override { return "WindowModule"; } + + /** + * @brief 获取模块优先级 + * @return 优先级值 + */ + int priority() const override { return cfg_.priority; } + + /** + * @brief 获取服务依赖 + * @return 依赖 ILogger + */ + std::vector needsServices() const override { + return {std::type_index(typeid(ILogger))}; + } + + /** + * @brief 窗口模块不支持并行初始化(SDL 窗口创建需要串行) + * @return false + */ + bool parallel() const override { return false; } + + /** + * @brief 轮询窗口事件 + */ + void poll(); + + /** + * @brief 检查窗口是否应该关闭 + * @return 应该关闭返回 true + */ + bool shouldClose() const; + + /** + * @brief 关闭窗口 + */ + void close(); + + /** + * @brief 设置窗口标题 + * @param title 窗口标题 + */ + void setTitle(const std::string &title); + + /** + * @brief 设置窗口大小 + * @param width 窗口宽度 + * @param height 窗口高度 + */ + void setSize(int width, int height); + + /** + * @brief 设置全屏模式 + * @param fullscreen 是否全屏 + */ + void setFullscreen(bool fullscreen); + + /** + * @brief 获取窗口宽度 + * @return 窗口宽度 + */ + int width() const; + + /** + * @brief 获取窗口高度 + * @return 窗口高度 + */ + int height() const; + + /** + * @brief 检查是否全屏 + * @return 全屏返回 true + */ + bool fullscreen() const; + + /** + * @brief 设置事件回调 + * @param cb 事件回调函数 + */ + void onEvent(std::function cb); + + /** + * @brief 获取原生窗口指针 + * @return SDL 窗口指针 + */ + SDL_Window *native() const; + + /** + * @brief 获取内部窗口对象 + * @return 窗口对象指针 + */ + Window *win() const { return window_.get(); } + +private: + WindowCfg cfg_; + Unique window_; + bool initialized_ = false; +}; + +} // namespace extra2d diff --git a/Extra2D/src/app/application.cpp b/Extra2D/src/app/application.cpp index 6aa73dd..df6910d 100644 --- a/Extra2D/src/app/application.cpp +++ b/Extra2D/src/app/application.cpp @@ -1,14 +1,17 @@ #include -#include +#include +#include #include #include #include -#include +#include #include namespace extra2d { +Application::Application() { Lifecycle::instance().setApp(this); } + Application &Application::instance() { static Application app; return app; @@ -20,37 +23,24 @@ bool Application::init() { if (initialized_) return true; - // 先初始化服务定位器(包括日志服务) - ServiceLocator::instance().init(); - E2D_INFO(CAT_APP, "应用程序初始化中:{}", name); - window_ = new Window(); - if (!window_->create({.title = name, .width = 1280, .height = 720})) { - E2D_ERROR(CAT_APP, "创建窗口失败"); - delete window_; - window_ = nullptr; + if (!Lifecycle::instance().init()) { + E2D_ERROR(CAT_APP, "初始化失败"); return false; } - // 设置事件回调,将 SDL 事件转换为 Extra2D 事件 - window_->onEvent([](const SDL_Event &e) { - Event event = EventConverter::convert(e); - if (event.type != EventType::None) { - auto eventService = ServiceLocator::instance().get(); - if (eventService) { - eventService->push(event); + auto *winMod = module(); + if (winMod && winMod->win()) { + winMod->onEvent([](const SDL_Event &e) { + Event event = EventConverter::convert(e); + if (event.type != EventType::None) { + auto eventService = Lifecycle::instance().service(); + if (eventService) { + eventService->push(event); + } } - } - }); - - auto &device = RenderDevice::instance(); - if (!device.init(window_->native())) { - E2D_ERROR(CAT_APP, "渲染设备初始化失败"); - window_->destroy(); - delete window_; - window_ = nullptr; - return false; + }); } initialized_ = true; @@ -67,15 +57,7 @@ void Application::shutdown() { E2D_INFO(CAT_APP, "应用程序正在关闭"); - RenderDevice::instance().shutdown(); - - if (window_) { - window_->destroy(); - delete window_; - window_ = nullptr; - } - - ServiceLocator::instance().shutdown(); + Lifecycle::instance().clear(); initialized_ = false; running_ = false; @@ -85,13 +67,19 @@ void Application::run() { if (!initialized_) return; - while (running_ && !window_->shouldClose()) { + auto *winMod = module(); + if (!winMod || !winMod->win()) + return; + + while (running_ && !winMod->shouldClose()) { mainLoop(); } } void Application::quit() { running_ = false; } +WindowModule *Application::windowModule() const { return module(); } + void Application::mainLoop() { u64 currentTime = SDL_GetPerformanceCounter(); u64 frequency = SDL_GetPerformanceFrequency(); @@ -109,9 +97,16 @@ void Application::mainLoop() { fpsTimer_ -= 1.0f; } - window_->poll(); - ServiceLocator::instance().update(dt_); - RenderDevice::instance().swapBuffers(); + auto *winMod = module(); + if (winMod) { + winMod->poll(); + } + Lifecycle::instance().update(dt_); + + auto *renderMod = module(); + if (renderMod) { + renderMod->swapBuffers(); + } } } // namespace extra2d diff --git a/Extra2D/src/core/lifecycle.cpp b/Extra2D/src/core/lifecycle.cpp new file mode 100644 index 0000000..7cddedf --- /dev/null +++ b/Extra2D/src/core/lifecycle.cpp @@ -0,0 +1,329 @@ +#include +#include +#include +#include +#include +#include + +namespace extra2d { + +Lifecycle& Lifecycle::instance() { + static Lifecycle instance; + return instance; +} + +size_t Lifecycle::findModuleIndex(std::type_index type) const { + for (size_t i = 0; i < modules_.size(); ++i) { + if (modules_[i].module && + std::type_index(typeid(*modules_[i].module)) == type) { + return i; + } + } + return SIZE_MAX; +} + +size_t Lifecycle::findServiceIndex(std::type_index type) const { + for (size_t i = 0; i < services_.size(); ++i) { + if (services_[i].id == type) { + return i; + } + } + return SIZE_MAX; +} + +std::vector> Lifecycle::groupByLevel() { + std::vector> levels; + + size_t totalUnits = modules_.size() + services_.size(); + std::vector inDegree(totalUnits, 0); + std::vector> adj(totalUnits); + + for (size_t i = 0; i < modules_.size(); ++i) { + if (!modules_[i].module) continue; + + auto* mod = modules_[i].module.get(); + + for (auto& depType : mod->deps()) { + size_t depIdx = findModuleIndex(depType); + if (depIdx != SIZE_MAX) { + adj[depIdx].push_back(i); + inDegree[i]++; + } + } + + for (auto& depType : mod->needsServices()) { + size_t depIdx = findServiceIndex(depType); + if (depIdx != SIZE_MAX) { + adj[modules_.size() + depIdx].push_back(i); + inDegree[i]++; + } + } + } + + for (size_t i = 0; i < services_.size(); ++i) { + if (!services_[i].service) continue; + + auto* svc = services_[i].service.get(); + + for (auto& depType : svc->deps()) { + size_t depIdx = findServiceIndex(depType); + if (depIdx != SIZE_MAX) { + adj[modules_.size() + depIdx].push_back(modules_.size() + i); + inDegree[modules_.size() + i]++; + } + } + + for (auto& depType : svc->needsModules()) { + size_t depIdx = findModuleIndex(depType); + if (depIdx != SIZE_MAX) { + adj[depIdx].push_back(modules_.size() + i); + inDegree[modules_.size() + i]++; + } + } + } + + std::queue q; + std::vector levelMap(totalUnits, -1); + + for (size_t i = 0; i < totalUnits; ++i) { + if (inDegree[i] == 0) { + q.push(i); + levelMap[i] = 0; + } + } + + while (!q.empty()) { + size_t curr = q.front(); + q.pop(); + + int currLevel = levelMap[curr]; + + if (levels.size() <= static_cast(currLevel)) { + levels.resize(currLevel + 1); + } + + UnitIndex ui; + if (curr < modules_.size()) { + ui.type = UnitType::Module; + ui.index = curr; + } else { + ui.type = UnitType::Service; + ui.index = curr - modules_.size(); + } + levels[currLevel].push_back(ui); + + for (size_t next : adj[curr]) { + inDegree[next]--; + if (inDegree[next] == 0) { + q.push(next); + levelMap[next] = currLevel + 1; + } + } + } + + return levels; +} + +bool Lifecycle::init() { + auto levels = groupByLevel(); + + std::cout << "[INFO] [生命周期] 正在初始化 " << modules_.size() + services_.size() + << " 个单元,共 " << levels.size() << " 个层级..." << std::endl; + + for (size_t level = 0; level < levels.size(); ++level) { + auto& units = levels[level]; + + bool hasParallelUnits = false; + for (auto& ui : units) { + if (ui.type == UnitType::Module) { + if (modules_[ui.index].module && + modules_[ui.index].module->parallel()) { + hasParallelUnits = true; + break; + } + } + } + + if (units.size() <= 1 || !hasParallelUnits) { + for (auto& ui : units) { + if (ui.type == UnitType::Module) { + auto* mod = modules_[ui.index].module.get(); + if (!mod) continue; + + std::cout << "[INFO] [模块系统] 正在初始化模块: " << mod->name() + << " (层级 " << level << ")" << std::endl; + + if (!mod->init()) { + std::cerr << "[ERROR] [模块系统] 初始化模块失败: " << mod->name() << std::endl; + return false; + } + + std::cout << "[INFO] [模块系统] 模块 " << mod->name() << " 初始化成功" << std::endl; + } else { + auto& svc = services_[ui.index].service; + if (!svc) continue; + + auto info = svc->info(); + if (!info.enabled) continue; + + std::cout << "[INFO] [服务系统] 正在初始化服务: " << info.name + << " (层级 " << level << ")" << std::endl; + + svc->setState(ServiceState::Initializing); + if (!svc->init()) { + svc->setState(ServiceState::Stopped); + std::cerr << "[ERROR] [服务系统] 初始化服务失败: " << info.name << std::endl; + return false; + } + svc->setState(ServiceState::Running); + + std::cout << "[INFO] [服务系统] 服务 " << info.name << " 初始化成功" << std::endl; + } + } + } else { + std::cout << "[INFO] [生命周期] 正在并行初始化 " << units.size() + << " 个单元 (层级 " << level << ")..." << std::endl; + + std::vector>> futures; + std::vector serialUnits; + + for (auto& ui : units) { + if (ui.type == UnitType::Module) { + auto* mod = modules_[ui.index].module.get(); + if (!mod) continue; + + if (mod->parallel()) { + futures.push_back(std::async(std::launch::async, + [this, ui, level]() -> std::pair { + auto* m = modules_[ui.index].module.get(); + std::cout << "[INFO] [模块系统] 正在初始化模块: " << m->name() + << " (层级 " << level << ")" << std::endl; + bool success = m->init(); + if (success) { + std::cout << "[INFO] [模块系统] 模块 " << m->name() + << " 初始化成功 (并行)" << std::endl; + } + return {ui, success}; + })); + } else { + serialUnits.push_back(ui); + } + } else { + serialUnits.push_back(ui); + } + } + + for (auto& future : futures) { + auto [ui, success] = future.get(); + if (!success) { + if (ui.type == UnitType::Module) { + auto* mod = modules_[ui.index].module.get(); + std::cerr << "[ERROR] [模块系统] 初始化模块失败: " << mod->name() << std::endl; + } + return false; + } + } + + for (auto& ui : serialUnits) { + if (ui.type == UnitType::Module) { + auto* mod = modules_[ui.index].module.get(); + if (!mod) continue; + + std::cout << "[INFO] [模块系统] 正在初始化模块: " << mod->name() + << " (串行, 层级 " << level << ")" << std::endl; + + if (!mod->init()) { + std::cerr << "[ERROR] [模块系统] 初始化模块失败: " << mod->name() << std::endl; + return false; + } + + std::cout << "[INFO] [模块系统] 模块 " << mod->name() << " 初始化成功" << std::endl; + } else { + auto& svc = services_[ui.index].service; + if (!svc) continue; + + auto info = svc->info(); + if (!info.enabled) continue; + + std::cout << "[INFO] [服务系统] 正在初始化服务: " << info.name + << " (层级 " << level << ")" << std::endl; + + svc->setState(ServiceState::Initializing); + if (!svc->init()) { + svc->setState(ServiceState::Stopped); + std::cerr << "[ERROR] [服务系统] 初始化服务失败: " << info.name << std::endl; + return false; + } + svc->setState(ServiceState::Running); + + std::cout << "[INFO] [服务系统] 服务 " << info.name << " 初始化成功" << std::endl; + } + } + } + + std::cout << "[INFO] [生命周期] 层级 " << level << " 初始化完成" << std::endl; + } + + std::cout << "[INFO] [生命周期] 所有单元初始化完成" << std::endl; + return true; +} + +void Lifecycle::update(f32 dt) { + for (auto& entry : services_) { + if (entry.service && entry.service->initialized()) { + auto state = entry.service->state(); + if (state == ServiceState::Running) { + entry.service->update(dt); + } + } + } +} + +void Lifecycle::pause() { + for (auto& entry : services_) { + if (entry.service && entry.service->initialized()) { + entry.service->pause(); + } + } +} + +void Lifecycle::resume() { + for (auto& entry : services_) { + if (entry.service && entry.service->initialized()) { + entry.service->resume(); + } + } +} + +void Lifecycle::shutdown() { + auto levels = groupByLevel(); + + for (auto it = levels.rbegin(); it != levels.rend(); ++it) { + for (auto& ui : *it) { + if (ui.type == UnitType::Module) { + auto* mod = modules_[ui.index].module.get(); + if (mod && mod->ok()) { + E2D_INFO(CAT_MODULES, "正在关闭模块: {}", mod->name()); + mod->shutdown(); + } + } else { + auto& svc = services_[ui.index].service; + if (svc && svc->initialized()) { + E2D_INFO(CAT_SERVICES, "正在关闭服务: {}", svc->name()); + svc->setState(ServiceState::Stopping); + svc->shutdown(); + svc->setState(ServiceState::Stopped); + } + } + } + } +} + +void Lifecycle::clear() { + shutdown(); + + modules_.clear(); + services_.clear(); +} + +} // namespace extra2d diff --git a/Extra2D/src/core/registry.cpp b/Extra2D/src/core/registry.cpp deleted file mode 100644 index 964a864..0000000 --- a/Extra2D/src/core/registry.cpp +++ /dev/null @@ -1,224 +0,0 @@ -#include -#include -#include -#include - -namespace extra2d { - -Registry &Registry::instance() { - static Registry instance; - return instance; -} - -bool Registry::init() { - auto levels = group(); - E2D_INFO(CAT_MODULES, "正在初始化 {} 个模块,共 {} 个层级...", moduleCount_, - levels.size()); - - for (size_t level = 0; level < levels.size(); ++level) { - auto &modules = levels[level]; - - // 检查当前层级是否有支持并行初始化的模块 - bool hasParallelModules = false; - for (auto *module : modules) { - if (module->parallel()) { - hasParallelModules = true; - break; - } - } - - // 如果只有一个模块或不支持并行,使用串行初始化 - if (modules.size() <= 1 || !hasParallelModules) { - for (auto *module : modules) { - E2D_INFO(CAT_MODULES, "正在初始化模块: {} (层级 {})", module->name(), - level); - - if (!module->init()) { - E2D_ERROR(CAT_MODULES, "初始化模块失败: {}", module->name()); - return false; - } - - E2D_INFO(CAT_MODULES, "模块 {} 初始化成功", module->name()); - } - } else { - // 并行初始化当前层级的模块 - E2D_INFO(CAT_MODULES, "正在并行初始化 {} 个模块 (层级 {})...", - modules.size(), level); - - std::vector>> futures; - std::vector serialModules; - - // 分离支持并行和不支持并行的模块 - for (auto *module : modules) { - if (module->parallel()) { - futures.push_back(std::async(std::launch::async, [module]() { - return std::make_pair(module, module->init()); - })); - } else { - serialModules.push_back(module); - } - } - - // 等待并行模块完成 - for (auto &future : futures) { - auto [module, success] = future.get(); - if (!success) { - E2D_ERROR(CAT_MODULES, "初始化模块失败: {}", module->name()); - return false; - } - E2D_INFO(CAT_MODULES, "模块 {} 初始化成功 (并行)", module->name()); - } - - // 串行初始化不支持并行的模块 - for (auto *module : serialModules) { - E2D_INFO(CAT_MODULES, "正在初始化模块: {} (串行, 层级 {})", - module->name(), level); - if (!module->init()) { - E2D_ERROR(CAT_MODULES, "初始化模块失败: {}", module->name()); - return false; - } - E2D_INFO(CAT_MODULES, "模块 {} 初始化成功", module->name()); - } - } - - E2D_INFO(CAT_MODULES, "层级 {} 初始化完成", level); - } - - E2D_INFO(CAT_MODULES, "所有模块初始化完成"); - return true; -} - -void Registry::shutdown() { - // 从后向前关闭模块 - for (size_t i = moduleCount_; i > 0; --i) { - if (modules_[i - 1].valid && modules_[i - 1].module) { - modules_[i - 1].module->shutdown(); - } - } -} - -void Registry::clear() { - shutdown(); - - // 销毁所有模块 - for (size_t i = 0; i < moduleCount_; ++i) { - modules_[i].module.reset(); - modules_[i].valid = false; - } - moduleCount_ = 0; -} - -std::vector Registry::sort() { - std::vector result; - std::vector inDegree(moduleCount_, 0); - std::vector> adj(moduleCount_); - - // 构建依赖图 - for (size_t i = 0; i < moduleCount_; ++i) { - if (!modules_[i].valid) - continue; - - auto deps = modules_[i].module->deps(); - for (auto &depType : deps) { - // 查找依赖模块的索引 - for (size_t j = 0; j < moduleCount_; ++j) { - auto &mod = *modules_[j].module; - if (modules_[j].valid && std::type_index(typeid(mod)) == depType) { - adj[j].push_back(i); - inDegree[i]++; - break; - } - } - } - } - - // 使用优先队列,按优先级排序 - auto cmp = [this](size_t a, size_t b) { - return modules_[a].module->priority() > modules_[b].module->priority(); - }; - std::priority_queue, decltype(cmp)> pq(cmp); - - for (size_t i = 0; i < moduleCount_; ++i) { - if (inDegree[i] == 0) { - pq.push(i); - } - } - - while (!pq.empty()) { - size_t curr = pq.top(); - pq.pop(); - result.push_back(modules_[curr].module.get()); - - for (size_t next : adj[curr]) { - inDegree[next]--; - if (inDegree[next] == 0) { - pq.push(next); - } - } - } - - return result; -} - -std::vector> Registry::group() { - std::vector> levels; - std::vector inDegree(moduleCount_, 0); - std::vector> adj(moduleCount_); - - // 构建依赖图 - for (size_t i = 0; i < moduleCount_; ++i) { - if (!modules_[i].valid) - continue; - - auto deps = modules_[i].module->deps(); - for (auto &depType : deps) { - for (size_t j = 0; j < moduleCount_; ++j) { - auto &mod = *modules_[j].module; - if (modules_[j].valid && std::type_index(typeid(mod)) == depType) { - adj[j].push_back(i); - inDegree[i]++; - break; - } - } - } - } - - // 使用 BFS 按层级分组 - std::queue q; - std::vector levelMap(moduleCount_, -1); - - // 找到所有入度为 0 的模块(第一层) - for (size_t i = 0; i < moduleCount_; ++i) { - if (inDegree[i] == 0) { - q.push(i); - levelMap[i] = 0; - } - } - - // BFS 遍历 - while (!q.empty()) { - size_t curr = q.front(); - q.pop(); - - int currLevel = levelMap[curr]; - - // 确保当前层级存在 - if (levels.size() <= static_cast(currLevel)) { - levels.resize(currLevel + 1); - } - levels[currLevel].push_back(modules_[curr].module.get()); - - // 处理依赖当前模块的其他模块 - for (size_t next : adj[curr]) { - inDegree[next]--; - if (inDegree[next] == 0) { - q.push(next); - levelMap[next] = currLevel + 1; - } - } - } - - return levels; -} - -} // namespace extra2d diff --git a/Extra2D/src/core/service_locator.cpp b/Extra2D/src/core/service_locator.cpp deleted file mode 100644 index 94ca13c..0000000 --- a/Extra2D/src/core/service_locator.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include -#include - -namespace extra2d { - -ServiceLocator& ServiceLocator::instance() { - static ServiceLocator instance; - return instance; -} - -bool ServiceLocator::init() { - std::shared_lock lock(mutex_); - - for (auto& svc : orderedServices_) { - if (!svc) continue; - - auto info = svc->info(); - if (!info.enabled) continue; - - if (!svc->initialized()) { - svc->setState(ServiceState::Initializing); - if (!svc->init()) { - svc->setState(ServiceState::Stopped); - return false; - } - svc->setState(ServiceState::Running); - } - } - - return true; -} - -void ServiceLocator::shutdown() { - std::shared_lock lock(mutex_); - - for (auto it = orderedServices_.rbegin(); - it != orderedServices_.rend(); ++it) { - if (*it && (*it)->initialized()) { - (*it)->setState(ServiceState::Stopping); - (*it)->shutdown(); - (*it)->setState(ServiceState::Stopped); - } - } -} - -void ServiceLocator::update(f32 dt) { - std::shared_lock lock(mutex_); - - for (auto& svc : orderedServices_) { - if (svc && svc->initialized()) { - auto state = svc->state(); - if (state == ServiceState::Running) { - svc->update(dt); - } - } - } -} - -void ServiceLocator::pause() { - std::shared_lock lock(mutex_); - - for (auto& svc : orderedServices_) { - if (svc && svc->initialized()) { - svc->pause(); - } - } -} - -void ServiceLocator::resume() { - std::shared_lock lock(mutex_); - - for (auto& svc : orderedServices_) { - if (svc && svc->initialized()) { - svc->resume(); - } - } -} - -std::vector> ServiceLocator::all() const { - std::shared_lock lock(mutex_); - return orderedServices_; -} - -void ServiceLocator::clear() { - std::unique_lock lock(mutex_); - - for (auto it = orderedServices_.rbegin(); - it != orderedServices_.rend(); ++it) { - if (*it && (*it)->initialized()) { - (*it)->setState(ServiceState::Stopping); - (*it)->shutdown(); - (*it)->setState(ServiceState::Stopped); - } - } - - services_.clear(); - factories_.clear(); - orderedServices_.clear(); -} - -void ServiceLocator::sort() { - std::stable_sort(orderedServices_.begin(), orderedServices_.end(), - [](const Ref& a, const Ref& b) { - if (!a || !b) return false; - return static_cast(a->info().priority) < - static_cast(b->info().priority); - }); -} - -} diff --git a/Extra2D/src/core/service_registry.cpp b/Extra2D/src/core/service_registry.cpp deleted file mode 100644 index f238a76..0000000 --- a/Extra2D/src/core/service_registry.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include - -namespace extra2d { - -ServiceRegistry& ServiceRegistry::instance() { - static ServiceRegistry instance; - return instance; -} - -void ServiceRegistry::setEnabled(const std::string& name, bool enabled) { - for (auto& reg : registrations_) { - if (reg.name == name) { - reg.enabled = enabled; - break; - } - } -} - -void ServiceRegistry::createAll() { - std::sort(registrations_.begin(), registrations_.end(), - [](const ServiceRegistration& a, const ServiceRegistration& b) { - return static_cast(a.priority) < static_cast(b.priority); - }); - - for (const auto& reg : registrations_) { - if (!reg.enabled) { - continue; - } - - auto service = reg.factory(); - if (service) { - ServiceLocator::instance().add(service); - } - } -} - -} diff --git a/Extra2D/src/render/render_module.cpp b/Extra2D/src/render/render_module.cpp new file mode 100644 index 0000000..5e39b9d --- /dev/null +++ b/Extra2D/src/render/render_module.cpp @@ -0,0 +1,91 @@ +#include +#include +#include +#include + +namespace extra2d { + +/** + * @brief 构造函数 + * 使用 Lambda 配置渲染参数 + */ +RenderModule::RenderModule(std::function configFn) { + if (configFn) { + configFn(cfg_); + } +} + +/** + * @brief 析构函数 + */ +RenderModule::~RenderModule() { shutdown(); } + +/** + * @brief 初始化渲染模块 + * 创建 OpenGL 上下文并初始化渲染设备 + */ +bool RenderModule::init() { + if (initialized_) { + return true; + } + + // 获取窗口模块 + auto *winMod = app()->module(); + if (!winMod || !winMod->win()) { + E2D_ERROR(CAT_RENDER, "WindowModule 未初始化"); + return false; + } + + // 转换配置 + RenderDeviceConfig config; + config.glMajor = cfg_.glMajor; + config.glMinor = cfg_.glMinor; + config.useES = cfg_.useES; + config.redBits = cfg_.redBits; + config.greenBits = cfg_.greenBits; + config.blueBits = cfg_.blueBits; + config.alphaBits = cfg_.alphaBits; + config.depthBits = cfg_.depthBits; + config.stencilBits = cfg_.stencilBits; + config.doubleBuffer = cfg_.doubleBuffer; + config.msaaSamples = cfg_.msaaSamples; + config.vsync = cfg_.vsync; + + auto &device = RenderDevice::instance(); + if (!device.init(winMod->native(), config)) { + E2D_ERROR(CAT_RENDER, "RenderDevice 初始化失败"); + return false; + } + + initialized_ = true; + + E2D_INFO(CAT_RENDER, "RenderModule initialized"); + + return true; +} + +/** + * @brief 关闭渲染模块 + */ +void RenderModule::shutdown() { + if (!initialized_) { + return; + } + + RenderDevice::instance().shutdown(); + initialized_ = false; +} + +/** + * @brief 交换缓冲区 + */ +void RenderModule::swapBuffers() { RenderDevice::instance().swapBuffers(); } + +/** + * @brief 设置 VSync + */ +void RenderModule::setVSync(bool enabled) { + RenderDevice::instance().setVSync(enabled); +} + +} // namespace extra2d diff --git a/Extra2D/src/services/logger_service.cpp b/Extra2D/src/services/logger_service.cpp index 17af605..75cafd1 100644 --- a/Extra2D/src/services/logger_service.cpp +++ b/Extra2D/src/services/logger_service.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -96,7 +97,11 @@ static void SDLCALL logOutput(void *userdata, int category, const char *content; parseCategory(message, cat, content); - Uint32 ticks = SDL_GetTicks(); + // 使用 std::chrono 替代 SDL_GetTicks(),避免 SDL 未初始化的问题 + auto now = std::chrono::steady_clock::now(); + auto ms = std::chrono::duration_cast( + now.time_since_epoch()); + Uint32 ticks = static_cast(ms.count() % (24 * 60 * 60 * 1000)); Uint32 seconds = ticks / 1000; Uint32 minutes = seconds / 60; Uint32 hours = minutes / 60; diff --git a/Extra2D/src/window/window_module.cpp b/Extra2D/src/window/window_module.cpp new file mode 100644 index 0000000..72000cc --- /dev/null +++ b/Extra2D/src/window/window_module.cpp @@ -0,0 +1,156 @@ +#include + +namespace extra2d { + +/** + * @brief 构造函数 + * 使用 Lambda 配置窗口参数 + */ +WindowModule::WindowModule(std::function configFn) { + if (configFn) { + configFn(cfg_); + } +} + +/** + * @brief 析构函数 + */ +WindowModule::~WindowModule() { + shutdown(); +} + +/** + * @brief 初始化窗口模块 + * 创建窗口并设置事件回调 + */ +bool WindowModule::init() { + if (initialized_) { + return true; + } + + window_ = ptr::unique(); + + WindowConfig config; + config.title = cfg_.title; + config.width = cfg_.width; + config.height = cfg_.height; + config.fullscreen = cfg_.fullscreen; + config.resizable = cfg_.resizable; + config.centerWindow = cfg_.centerWindow; + + if (!window_->create(config)) { + window_.reset(); + return false; + } + + initialized_ = true; + return true; +} + +/** + * @brief 关闭窗口模块 + * 销毁窗口并释放资源 + */ +void WindowModule::shutdown() { + if (!initialized_) { + return; + } + + if (window_) { + window_->destroy(); + window_.reset(); + } + + initialized_ = false; +} + +/** + * @brief 轮询窗口事件 + */ +void WindowModule::poll() { + if (window_) { + window_->poll(); + } +} + +/** + * @brief 检查窗口是否应该关闭 + */ +bool WindowModule::shouldClose() const { + return window_ ? window_->shouldClose() : true; +} + +/** + * @brief 关闭窗口 + */ +void WindowModule::close() { + if (window_) { + window_->close(); + } +} + +/** + * @brief 设置窗口标题 + */ +void WindowModule::setTitle(const std::string& title) { + if (window_) { + window_->setTitle(title); + } +} + +/** + * @brief 设置窗口大小 + */ +void WindowModule::setSize(int width, int height) { + if (window_) { + window_->setSize(width, height); + } +} + +/** + * @brief 设置全屏模式 + */ +void WindowModule::setFullscreen(bool fullscreen) { + if (window_) { + window_->setFullscreen(fullscreen); + } +} + +/** + * @brief 获取窗口宽度 + */ +int WindowModule::width() const { + return window_ ? window_->width() : 0; +} + +/** + * @brief 获取窗口高度 + */ +int WindowModule::height() const { + return window_ ? window_->height() : 0; +} + +/** + * @brief 检查是否全屏 + */ +bool WindowModule::fullscreen() const { + return window_ ? window_->fullscreen() : false; +} + +/** + * @brief 设置事件回调 + */ +void WindowModule::onEvent(std::function cb) { + if (window_) { + window_->onEvent(cb); + } +} + +/** + * @brief 获取原生窗口指针 + */ +SDL_Window* WindowModule::native() const { + return window_ ? window_->native() : nullptr; +} + +} // namespace extra2d diff --git a/examples/hello_world/main.cpp b/examples/hello_world/main.cpp index b5aea5b..de05252 100644 --- a/examples/hello_world/main.cpp +++ b/examples/hello_world/main.cpp @@ -2,51 +2,57 @@ using namespace extra2d; -// ============================================================================ -// Hello World 示例 -// ============================================================================ - int main(int argc, char **argv) { - E2D_INFO(CAT_APP, "========================"); - E2D_INFO(CAT_APP, "Extra2D Hello World Demo"); - E2D_INFO(CAT_APP, "========================"); + E2D_INFO(CAT_APP, "========================"); + E2D_INFO(CAT_APP, "Extra2D Hello World Demo"); + E2D_INFO(CAT_APP, "========================"); - // 获取应用实例并初始化 - auto &app = Application::instance(); - - if (!app.init()) { - E2D_ERROR(CAT_APP, "应用初始化失败!"); - return -1; - } + auto &app = Application::instance(); + app.name = "Hello World"; - // 获取事件服务并订阅键盘事件 - auto eventService = ServiceLocator::instance().get(); - if (eventService) { - // 订阅 ESC 键退出 - eventService->on(EventType::KeyPressed, [&app](Event &e) { - auto &keyEvent = std::get(e.data); - if (keyEvent.key == static_cast(Key::Escape)) { - E2D_INFO(CAT_INPUT, "ESC 键按下,退出应用"); - app.quit(); - } - }); + // 注册服务和模块(顺序无关,Lifecycle 会自动按依赖拓扑排序) + app.useService(); + app.useService(); + app.useService(); + app.useModule([](WindowCfg &cfg) { + cfg.title = "Extra2D - Hello World"; + cfg.width = 1280; + cfg.height = 720; + }); + app.useModule([](RenderCfg &cfg) { + cfg.glMajor = 4; + cfg.glMinor = 5; + cfg.vsync = true; + }); - // 订阅手柄按钮退出 - eventService->on(EventType::GamepadButtonPressed, [&app](Event &e) { - auto &btnEvent = std::get(e.data); - if (btnEvent.button == static_cast(Gamepad::Start)) { - E2D_INFO(CAT_INPUT, "START 按钮按下,退出应用"); - app.quit(); - } - }); - } + if (!app.init()) { + E2D_ERROR(CAT_APP, "应用初始化失败!"); + return -1; + } - E2D_INFO(CAT_APP, "开始主循环..."); + auto eventService = Lifecycle::instance().service(); + if (eventService) { + eventService->on(EventType::KeyPressed, [&app](Event &e) { + auto &keyEvent = std::get(e.data); + if (keyEvent.key == static_cast(Key::Escape)) { + E2D_INFO(CAT_INPUT, "ESC 键按下,退出应用"); + app.quit(); + } + }); - // 运行应用 - app.run(); + eventService->on(EventType::GamepadButtonPressed, [&app](Event &e) { + auto &btnEvent = std::get(e.data); + if (btnEvent.button == static_cast(Gamepad::Start)) { + E2D_INFO(CAT_INPUT, "START 按钮按下,退出应用"); + app.quit(); + } + }); + } - E2D_INFO(CAT_APP, "应用结束"); + E2D_INFO(CAT_APP, "开始主循环..."); + app.run(); + E2D_INFO(CAT_APP, "应用结束"); - return 0; + app.shutdown(); + return 0; }