#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace extra2d { /** * @brief 资源管理模块(主流 ECS 风格) * * 设计参考 Bevy/Amethyst: * - AssetStorage: 密集存储资源 * - load(): 统一加载接口 * - Handle: 轻量级句柄 */ class AssetsModule : public Module { E2D_REGISTER_MODULE(AssetsModule, "Assets", 2) public: AssetsModule(); ~AssetsModule() override; bool init() override; void shutdown() override; /** * @brief 在 OpenGL 上下文就绪后创建默认资源 */ void onGLContextReady(); //=========================================================================== // 核心加载接口(模板方法,主流设计) //=========================================================================== /** * @brief 加载资源(自动缓存,重复加载返回已有) * * 示例: * @code * Handle tex = assets->load("player.png"); * Handle shader = assets->load("sprite.vert", "sprite.frag"); * @endcode * * @tparam T 资源类型 * @param path 文件路径 * @return 资源句柄 */ template Handle load(const std::string& path, Args&&... args); /** * @brief 从内存加载资源 * @tparam T 资源类型 * @param key 缓存键名 * @param data 数据指针 * @param size 数据大小 * @return 资源句柄 */ template Handle loadFromMemory(const std::string& key, const uint8_t* data, size_t size); /** * @brief 获取资源(返回指针,可能为 nullptr) * * 示例: * @code * Texture* tex = assets->get(handle); * if (tex) { * tex->bind(); * } * @endcode */ template T* get(Handle handle); /** * @brief 获取资源(返回智能指针) */ template Ptr getPtr(Handle handle); /** * @brief 检查句柄是否有效 */ template bool isValid(Handle handle) const; /** * @brief 移除资源 */ template void remove(Handle handle); //=========================================================================== // 批量加载(目录/包) //=========================================================================== /** * @brief 加载整个目录 * @tparam T 资源类型 * @param directory 目录路径 * @param pattern 文件模式(如 "*.png") * @param recursive 是否递归 * @return 句柄列表 */ template std::vector> loadDir(const std::string& directory, const std::string& pattern = "*", bool recursive = true); //=========================================================================== // 异步加载 //=========================================================================== /** * @brief 异步加载资源 * @tparam T 资源类型 * @param path 文件路径 * @param callback 加载完成回调 */ template void loadAsync(const std::string& path, std::function)> callback); //=========================================================================== // 注册加载器(扩展点) //=========================================================================== /** * @brief 注册资源加载器 * @tparam T 资源类型 * @param loader 加载器实例 */ template void registerLoader(std::unique_ptr> loader); //=========================================================================== // 默认资源 //=========================================================================== /** * @brief 创建默认资源 * @return 是否成功 */ bool createDefaultResources(); /** * @brief 销毁默认资源 */ void destroyDefaultResources(); Handle getDefaultTexture(); Handle getDefaultShader(); Handle getDefaultMaterial(); Handle getDefaultQuad(); Texture* getDefaultTexturePtr(); Shader* getDefaultShaderPtr(); Material* getDefaultMaterialPtr(); Mesh* getDefaultQuadPtr(); //=========================================================================== // 热重载 //=========================================================================== /** * @brief 启用/禁用热重载 * @param enable 是否启用 */ void enableHotReload(bool enable); /** * @brief 检查文件变更并重新加载 */ void checkForChanges(); //=========================================================================== // 统计 //=========================================================================== struct Stats { size_t textureCount = 0; size_t shaderCount = 0; size_t materialCount = 0; size_t meshCount = 0; }; Stats getStats() const; private: // 资源存储 AssetStorage textures_; AssetStorage shaders_; AssetStorage materials_; AssetStorage meshes_; // 加载器 std::unique_ptr> textureLoader_; std::unique_ptr> shaderLoader_; // 路径缓存(避免重复加载) std::unordered_map> texturePathCache_; std::unordered_map> shaderPathCache_; // 默认资源 Handle defaultTexture_; Handle defaultShader_; Handle defaultMaterial_; Handle defaultQuad_; // 热重载 bool hotReloadEnabled_ = false; // 线程安全 mutable std::mutex mutex_; // 事件监听器 std::unique_ptr onShowListener_; // 标记默认资源是否已创建 bool defaultResourcesCreated_ = false; }; // 全局访问 AssetsModule* getAssets(); //=========================================================================== // 模板实现 //=========================================================================== template Handle AssetsModule::load(const std::string& path, Args&&... args) { static_assert(sizeof...(Args) == 0 || sizeof...(Args) == 1, "load() accepts 0 or 1 additional arguments"); return Handle::invalid(); } template<> Handle AssetsModule::load(const std::string& path); template<> Handle AssetsModule::load(const std::string& path); template<> Handle AssetsModule::load(const std::string& vertPath, const std::string& fragPath); template Handle AssetsModule::loadFromMemory(const std::string& key, const uint8_t* data, size_t size) { return Handle::invalid(); } template<> Handle AssetsModule::loadFromMemory(const std::string& key, const uint8_t* data, size_t size); template T* AssetsModule::get(Handle handle) { return nullptr; } template<> inline Texture* AssetsModule::get(Handle handle) { return textures_.get(handle); } template<> inline Shader* AssetsModule::get(Handle handle) { return shaders_.get(handle); } template<> inline Material* AssetsModule::get(Handle handle) { return materials_.get(handle); } template<> inline Mesh* AssetsModule::get(Handle handle) { return meshes_.get(handle); } template Ptr AssetsModule::getPtr(Handle handle) { return Ptr(); } template<> inline Ptr AssetsModule::getPtr(Handle handle) { return textures_.getPtr(handle); } template<> inline Ptr AssetsModule::getPtr(Handle handle) { return shaders_.getPtr(handle); } template<> inline Ptr AssetsModule::getPtr(Handle handle) { return materials_.getPtr(handle); } template<> inline Ptr AssetsModule::getPtr(Handle handle) { return meshes_.getPtr(handle); } template bool AssetsModule::isValid(Handle handle) const { return false; } template<> inline bool AssetsModule::isValid(Handle handle) const { return textures_.isValid(handle); } template<> inline bool AssetsModule::isValid(Handle handle) const { return shaders_.isValid(handle); } template<> inline bool AssetsModule::isValid(Handle handle) const { return materials_.isValid(handle); } template<> inline bool AssetsModule::isValid(Handle handle) const { return meshes_.isValid(handle); } template void AssetsModule::remove(Handle handle) { } template<> inline void AssetsModule::remove(Handle handle) { textures_.remove(handle); } template<> inline void AssetsModule::remove(Handle handle) { shaders_.remove(handle); } template<> inline void AssetsModule::remove(Handle handle) { materials_.remove(handle); } template<> inline void AssetsModule::remove(Handle handle) { meshes_.remove(handle); } template std::vector> AssetsModule::loadDir(const std::string& directory, const std::string& pattern, bool recursive) { return {}; } template<> std::vector> AssetsModule::loadDir(const std::string& directory, const std::string& pattern, bool recursive); template void AssetsModule::loadAsync(const std::string& path, std::function)> callback) { } template<> void AssetsModule::loadAsync(const std::string& path, std::function)> callback); template void AssetsModule::registerLoader(std::unique_ptr> loader) { } template<> void AssetsModule::registerLoader(std::unique_ptr> loader); template<> void AssetsModule::registerLoader(std::unique_ptr> loader); } // namespace extra2d