From b672b16b839f7623d1d6a55c1f05ef851dc5a635 Mon Sep 17 00:00:00 2001 From: ChestnutYueyue <952134128@qq.com> Date: Mon, 16 Mar 2026 17:44:36 +0800 Subject: [PATCH] =?UTF-8?q?refactor(assets):=20=E9=87=8D=E6=9E=84=E8=B5=84?= =?UTF-8?q?=E6=BA=90=E7=B3=BB=E7=BB=9F=E6=9E=B6=E6=9E=84=EF=BC=8C=E6=8F=90?= =?UTF-8?q?=E5=8F=96=E6=A0=B8=E5=BF=83=E9=80=BB=E8=BE=91=E5=88=B0=20AssetS?= =?UTF-8?q?ystem?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 AssetSystem 类,整合异步加载、热重载、依赖跟踪等核心功能 - 将 AssetAsyncRuntime、AssetHotReloadRuntime 等组件提取为独立运行时类 - 重命名 AssetDependencyTracker 为 AssetDependencyGraph,改进数据结构 - 新增 BuiltinAssetFactory 负责默认资源的创建与管理 - 新增 AssetCache 提供线程安全的资源缓存机制 - 简化 AssetsModule 实现,将其职责委托给 AssetSystem - 保持原有 API 兼容性,仅重构内部实现 --- include/assets/assets_module.h | 24 +- .../assets/builtin/builtin_asset_factory.h | 41 + include/assets/cache/asset_cache.h | 52 ++ include/assets/core/asset_system.h | 95 +++ .../asset_dependency_graph.h} | 32 +- include/assets/runtime/asset_async_runtime.h | 21 + .../assets/runtime/asset_hot_reload_runtime.h | 26 + src/assets/assets_module.cpp | 710 ++++-------------- src/assets/builtin/builtin_asset_factory.cpp | 95 +++ src/assets/core/asset_system.cpp | 313 ++++++++ .../dependency/asset_dependency_graph.cpp | 81 ++ src/assets/deps/asset_dependency_tracker.cpp | 89 --- src/assets/runtime/asset_async_runtime.cpp | 18 + .../runtime/asset_hot_reload_runtime.cpp | 37 + 14 files changed, 927 insertions(+), 707 deletions(-) create mode 100644 include/assets/builtin/builtin_asset_factory.h create mode 100644 include/assets/cache/asset_cache.h create mode 100644 include/assets/core/asset_system.h rename include/assets/{deps/asset_dependency_tracker.h => dependency/asset_dependency_graph.h} (58%) create mode 100644 include/assets/runtime/asset_async_runtime.h create mode 100644 include/assets/runtime/asset_hot_reload_runtime.h create mode 100644 src/assets/builtin/builtin_asset_factory.cpp create mode 100644 src/assets/core/asset_system.cpp create mode 100644 src/assets/dependency/asset_dependency_graph.cpp delete mode 100644 src/assets/deps/asset_dependency_tracker.cpp create mode 100644 src/assets/runtime/asset_async_runtime.cpp create mode 100644 src/assets/runtime/asset_hot_reload_runtime.cpp diff --git a/include/assets/assets_module.h b/include/assets/assets_module.h index 8897caf..b220a58 100644 --- a/include/assets/assets_module.h +++ b/include/assets/assets_module.h @@ -1,10 +1,7 @@ #pragma once #include -#include -#include -#include -#include +#include #include #include #include @@ -239,17 +236,6 @@ public: */ void setHotReloadInterval(float interval); -private: - /** - * @brief 重新加载纹理 - */ - void reloadTexture(const AssetHotReloader::FileWatchInfo &info); - - /** - * @brief 重新加载着色器 - */ - void reloadShader(const AssetHotReloader::FileWatchInfo &info); - public: //=========================================================================== // 统计 @@ -285,9 +271,6 @@ private: Handle defaultMaterial_; Handle defaultQuad_; - AssetFileSystem fileSystem_; - AssetHotReloader hotReloader_; - // 线程安全 mutable std::shared_mutex mutex_; @@ -334,9 +317,6 @@ public: */ void processAsyncCallbacks(); -private: - AssetAsyncLoader asyncLoader_; - //=========================================================================== // 资源依赖跟踪 //=========================================================================== @@ -373,7 +353,7 @@ public: void notifyShaderReloaded(Handle shader); private: - AssetDependencyTracker dependencyTracker_; + std::unique_ptr system_; }; // 全局访问 diff --git a/include/assets/builtin/builtin_asset_factory.h b/include/assets/builtin/builtin_asset_factory.h new file mode 100644 index 0000000..aa55f96 --- /dev/null +++ b/include/assets/builtin/builtin_asset_factory.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace extra2d { + +class BuiltinAssetFactory { +public: + BuiltinAssetFactory(AssetStorage &textures, AssetStorage &shaders, + AssetStorage &materials, AssetStorage &meshes, + const AssetFileSystem &fileSystem); + + bool create(); + void destroy(); + + Handle defaultTexture() const; + Handle defaultShader() const; + Handle defaultMaterial() const; + Handle defaultQuad() const; + +private: + AssetStorage &textures_; + AssetStorage &shaders_; + AssetStorage &materials_; + AssetStorage &meshes_; + const AssetFileSystem &fileSystem_; + + Handle defaultTexture_; + Handle defaultShader_; + Handle defaultMaterial_; + Handle defaultQuad_; +}; + +} // namespace extra2d + diff --git a/include/assets/cache/asset_cache.h b/include/assets/cache/asset_cache.h new file mode 100644 index 0000000..d2d2c50 --- /dev/null +++ b/include/assets/cache/asset_cache.h @@ -0,0 +1,52 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace extra2d { + +template class AssetCache { +public: + Handle find(const std::string &key) const { + std::shared_lock lock(mutex_); + auto it = map_.find(key); + if (it == map_.end()) { + return Handle::invalid(); + } + return it->second; + } + + void set(const std::string &key, Handle handle) { + std::unique_lock lock(mutex_); + map_[key] = handle; + } + + void erase(const std::string &key) { + std::unique_lock lock(mutex_); + map_.erase(key); + } + + void clear() { + std::unique_lock lock(mutex_); + map_.clear(); + } + + std::string findKeyByHandle(Handle handle) const { + std::shared_lock lock(mutex_); + for (const auto &pair : map_) { + if (pair.second == handle) { + return pair.first; + } + } + return ""; + } + +private: + std::unordered_map> map_; + mutable std::shared_mutex mutex_; +}; + +} // namespace extra2d diff --git a/include/assets/core/asset_system.h b/include/assets/core/asset_system.h new file mode 100644 index 0000000..ad9854c --- /dev/null +++ b/include/assets/core/asset_system.h @@ -0,0 +1,95 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace extra2d { + +class ShaderLoader; + +class AssetSystem { +public: + struct Stats { + size_t textureCount = 0; + size_t shaderCount = 0; + size_t materialCount = 0; + size_t meshCount = 0; + }; + + AssetSystem(AssetStorage &textures, AssetStorage &shaders, + AssetStorage &materials, AssetStorage &meshes, + std::unique_ptr> &textureLoader, + std::unique_ptr> &shaderLoader); + + Handle loadTexture(const std::string &path); + Handle loadTextureFromMemory(const std::string &key, + const uint8_t *data, size_t size); + std::vector> + loadTextureDir(const std::string &directory, bool recursive); + + Handle loadShader(const std::string &path); + Handle loadShader(const std::string &vertPath, + const std::string &fragPath); + + void loadTextureAsync(const std::string &path, + std::function)> callback); + void loadShaderAsync(const std::string &path, + std::function)> callback); + void initAsync(uint32_t threadCount = 0); + void shutdownAsync(); + void processAsyncCallbacks(); + + void registerTextureLoader(std::unique_ptr> loader); + void registerShaderLoader(std::unique_ptr> loader); + + bool createDefaults(); + void destroyDefaults(); + Handle defaultTexture() const; + Handle defaultShader() const; + Handle defaultMaterial() const; + Handle defaultQuad() const; + + void enableHotReload(bool enable); + void setHotReloadInterval(float interval); + void checkForChanges(); + + void registerDependency(Handle material, Handle texture); + void registerDependency(Handle material, Handle shader); + void notifyTextureReloaded(Handle texture); + void notifyShaderReloaded(Handle shader); + + void clear(); + Stats stats() const; + +private: + void reloadTexture(const AssetHotReloader::FileWatchInfo &info); + void reloadShader(const AssetHotReloader::FileWatchInfo &info); + + AssetStorage &textures_; + AssetStorage &shaders_; + AssetStorage &materials_; + AssetStorage &meshes_; + + std::unique_ptr> &textureLoader_; + std::unique_ptr> &shaderLoader_; + + AssetCache textureCache_; + AssetCache shaderCache_; + AssetDependencyGraph dependencyGraph_; + AssetAsyncRuntime asyncRuntime_; + AssetHotReloadRuntime hotReloadRuntime_; + BuiltinAssetFactory builtinFactory_; + AssetFileSystem fileSystem_; +}; + +} // namespace extra2d diff --git a/include/assets/deps/asset_dependency_tracker.h b/include/assets/dependency/asset_dependency_graph.h similarity index 58% rename from include/assets/deps/asset_dependency_tracker.h rename to include/assets/dependency/asset_dependency_graph.h index 5ac6d1c..cd2ae32 100644 --- a/include/assets/deps/asset_dependency_tracker.h +++ b/include/assets/dependency/asset_dependency_graph.h @@ -1,30 +1,22 @@ #pragma once #include +#include +#include #include #include #include -#include -#include #include #include #include namespace extra2d { -class AssetDependencyTracker { +class AssetDependencyGraph { public: - struct DependencyInfo { - Handle texture; - Handle shader; - std::vector> dependentMaterials; - }; - void clear(); - void registerMaterialDependency(Handle material, - Handle texture); - void registerMaterialDependency(Handle material, - Handle shader); + void registerDependency(Handle material, Handle texture); + void registerDependency(Handle material, Handle shader); void notifyTextureReloaded( Handle texture, const std::function)> &onMaterialUpdate) const; @@ -33,8 +25,18 @@ public: const std::function)> &onMaterialUpdate) const; private: - std::unordered_map textureDependencies_; - std::unordered_map shaderDependencies_; + struct TextureDeps { + Handle texture; + std::vector> materials; + }; + + struct ShaderDeps { + Handle shader; + std::vector> materials; + }; + + std::unordered_map textureDeps_; + std::unordered_map shaderDeps_; mutable std::shared_mutex mutex_; }; diff --git a/include/assets/runtime/asset_async_runtime.h b/include/assets/runtime/asset_async_runtime.h new file mode 100644 index 0000000..515f8f7 --- /dev/null +++ b/include/assets/runtime/asset_async_runtime.h @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +namespace extra2d { + +class AssetAsyncRuntime { +public: + void init(uint32_t threadCount = 0); + void shutdown(); + bool running() const; + void submit(const AssetAsyncLoader::Task &task); + void processCallbacks(); + +private: + AssetAsyncLoader loader_; +}; + +} // namespace extra2d + diff --git a/include/assets/runtime/asset_hot_reload_runtime.h b/include/assets/runtime/asset_hot_reload_runtime.h new file mode 100644 index 0000000..30bd2e3 --- /dev/null +++ b/include/assets/runtime/asset_hot_reload_runtime.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +namespace extra2d { + +class AssetHotReloadRuntime { +public: + explicit AssetHotReloadRuntime(const AssetFileSystem &fileSystem); + void enable(bool enable); + bool enabled() const; + void setInterval(float interval); + void addWatch(const std::string &path, Handle handle); + void addWatch(const std::string &path, Handle handle); + void clear(); + void check(const std::function + &reloadTexture, + const std::function + &reloadShader); + +private: + AssetHotReloader reloader_; +}; + +} // namespace extra2d + diff --git a/src/assets/assets_module.cpp b/src/assets/assets_module.cpp index 3b61bfa..0ee9190 100644 --- a/src/assets/assets_module.cpp +++ b/src/assets/assets_module.cpp @@ -1,17 +1,14 @@ -#include #include #include #include #include -#include -#include #include namespace extra2d { AssetsModule *g_assetsModule = nullptr; -AssetsModule::AssetsModule() : hotReloader_(fileSystem_) { g_assetsModule = this; } +AssetsModule::AssetsModule() { g_assetsModule = this; } AssetsModule::~AssetsModule() { if (g_assetsModule == this) { @@ -21,712 +18,263 @@ AssetsModule::~AssetsModule() { bool AssetsModule::init() { E2D_INFO("资源模块正在初始化..."); - textureLoader_ = std::make_unique(); - shaderLoader_ = std::make_unique(fileSystem_); - - // 监听窗口显示事件,在 OpenGL 上下文创建完成后创建默认资源 + shaderLoader_ = std::make_unique(); + system_ = std::make_unique(textures_, shaders_, materials_, meshes_, + textureLoader_, shaderLoader_); onShowListener_ = std::make_unique(); onShowListener_->bind([this]() { this->onGLContextReady(); }); - - E2D_INFO("资源模块初始化成功 (等待 GL 上下文)"); + E2D_INFO("资源模块初始化成功 (V2)"); return true; } -void AssetsModule::onGLContextReady() { - if (defaultResourcesCreated_) { - return; - } - - E2D_INFO("OpenGL 上下文就绪,正在创建默认资源..."); - - if (!createDefaultResources()) { - E2D_ERROR("创建默认资源失败"); - return; - } - - defaultResourcesCreated_ = true; - E2D_INFO("默认资源创建成功"); -} - void AssetsModule::shutdown() { E2D_INFO("资源模块正在关闭..."); - - // 关闭异步加载系统 - shutdownAsyncLoader(); - - // 释放事件监听器 onShowListener_.reset(); - - destroyDefaultResources(); - - // 清空资源(使用写锁保护) - { - std::unique_lock lock(mutex_); - textures_.clear(); - shaders_.clear(); - materials_.clear(); - meshes_.clear(); - - texturePathCache_.clear(); - shaderPathCache_.clear(); + if (system_) { + system_->clear(); + system_.reset(); } - - hotReloader_.clear(); - dependencyTracker_.clear(); - + textures_.clear(); + shaders_.clear(); + materials_.clear(); + meshes_.clear(); textureLoader_.reset(); shaderLoader_.reset(); - defaultResourcesCreated_ = false; - E2D_INFO("资源模块关闭完成"); } +void AssetsModule::onGLContextReady() { + if (defaultResourcesCreated_ || !system_) { + return; + } + if (!system_->createDefaults()) { + E2D_ERROR("创建默认资源失败"); + return; + } + defaultResourcesCreated_ = true; +} + AssetsModule *getAssets() { return g_assetsModule; } -//=========================================================================== -// Texture 加载特化 -//=========================================================================== - -template <> -Handle AssetsModule::load(const std::string &path) { - // 先检查缓存(读锁) - { - std::shared_lock lock(mutex_); - auto it = texturePathCache_.find(path); - if (it != texturePathCache_.end()) { - if (textures_.isValid(it->second)) { - return it->second; - } - } - } - - if (!textureLoader_) { - E2D_ERROR("纹理加载器未注册"); +template <> Handle AssetsModule::load(const std::string &path) { + if (!system_) { return Handle::invalid(); } - - Ptr texture = textureLoader_->load(path); - if (!texture) { - E2D_ERROR("加载纹理失败: {}", path); - return Handle::invalid(); - } - - // 插入资源(写锁) - Handle handle; - { - std::unique_lock lock(mutex_); - - // 双重检查,避免重复加载 - auto it = texturePathCache_.find(path); - if (it != texturePathCache_.end() && textures_.isValid(it->second)) { - return it->second; - } - - handle = textures_.insert(texture); - texturePathCache_[path] = handle; - } - - E2D_DEBUG("已加载纹理: {} -> 句柄索引 {}", path, handle.index()); - - // 如果启用了热重载,添加文件监控 - if (hotReloader_.enabled()) { - hotReloader_.addFileWatch(path, handle); - } - - return handle; + return system_->loadTexture(path); } template <> Handle AssetsModule::loadFromMemory(const std::string &key, const uint8_t *data, size_t size) { - auto it = texturePathCache_.find(key); - if (it != texturePathCache_.end()) { - if (textures_.isValid(it->second)) { - return it->second; - } - texturePathCache_.erase(it); - } - - if (!textureLoader_) { - E2D_ERROR("纹理加载器未注册"); + if (!system_) { return Handle::invalid(); } - - Ptr texture = textureLoader_->loadFromMemory(data, size); - if (!texture) { - E2D_ERROR("从内存加载纹理失败: {}", key); - return Handle::invalid(); - } - - Handle handle = textures_.insert(texture); - texturePathCache_[key] = handle; - - return handle; + return system_->loadTextureFromMemory(key, data, size); } -//=========================================================================== -// Shader 加载特化 -//=========================================================================== - template <> Handle AssetsModule::load(const std::string &path) { - // 先检查缓存(读锁) - { - std::shared_lock lock(mutex_); - auto it = shaderPathCache_.find(path); - if (it != shaderPathCache_.end()) { - if (shaders_.isValid(it->second)) { - return it->second; - } - } - } - - if (!shaderLoader_) { - E2D_ERROR("着色器加载器未注册"); + if (!system_) { return Handle::invalid(); } - - Ptr shader = shaderLoader_->load(path); - if (!shader) { - E2D_ERROR("加载着色器失败: {}", path); - return Handle::invalid(); - } - - // 插入资源(写锁) - Handle handle; - { - std::unique_lock lock(mutex_); - - // 双重检查 - auto it = shaderPathCache_.find(path); - if (it != shaderPathCache_.end() && shaders_.isValid(it->second)) { - return it->second; - } - - handle = shaders_.insert(shader); - shaderPathCache_[path] = handle; - } - - E2D_DEBUG("已加载着色器: {} -> 句柄索引 {}", path, handle.index()); - - // 如果启用了热重载,添加文件监控 - if (hotReloader_.enabled()) { - hotReloader_.addFileWatch(path, handle); - } - - return handle; + return system_->loadShader(path); } template <> Handle AssetsModule::load(const std::string &vertPath, const std::string &fragPath) { - std::string cacheKey = vertPath + "|" + fragPath; - - // 先检查缓存(读锁) - { - std::shared_lock lock(mutex_); - auto it = shaderPathCache_.find(cacheKey); - if (it != shaderPathCache_.end()) { - if (shaders_.isValid(it->second)) { - return it->second; - } - } - } - - if (!shaderLoader_) { - E2D_ERROR("着色器加载器未注册"); + if (!system_) { return Handle::invalid(); } - - ShaderLoader *shaderLoader = static_cast(shaderLoader_.get()); - Ptr shader = shaderLoader->load(vertPath, fragPath); - if (!shader) { - E2D_ERROR("加载着色器失败: {} + {}", vertPath, fragPath); - return Handle::invalid(); - } - - // 插入资源(写锁) - Handle handle; - { - std::unique_lock lock(mutex_); - - // 双重检查 - auto it = shaderPathCache_.find(cacheKey); - if (it != shaderPathCache_.end() && shaders_.isValid(it->second)) { - return it->second; - } - - handle = shaders_.insert(shader); - shaderPathCache_[cacheKey] = handle; - } - - E2D_DEBUG("已加载着色器: {} + {} -> 句柄索引 {}", vertPath, fragPath, - handle.index()); - - // 如果启用了热重载,添加文件监控 - if (hotReloader_.enabled()) { - hotReloader_.addFileWatch(vertPath, handle); - hotReloader_.addFileWatch(fragPath, handle); - } - - return handle; + return system_->loadShader(vertPath, fragPath); } -//=========================================================================== -// 批量加载 -//=========================================================================== - template <> std::vector> AssetsModule::loadDir(const std::string &directory, const std::string &pattern, bool recursive) { - std::vector> handles; - - try { - std::filesystem::path dirPath(directory); - if (!fileSystem_.exists(directory)) { - E2D_WARN("目录未找到: {}", directory); - return handles; - } - - auto loadFile = [this, &handles](const std::filesystem::path &filePath) { - std::string ext = filePath.extension().string(); - std::string pathStr = filePath.string(); - - for (const auto &supportedExt : textureLoader_->getExtensions()) { - if (ext == supportedExt) { - Handle handle = load(pathStr); - if (handle.isValid()) { - handles.push_back(handle); - } - break; - } - } - }; - - if (recursive) { - for (const auto &entry : - std::filesystem::recursive_directory_iterator(dirPath)) { - if (entry.is_regular_file()) { - loadFile(entry.path()); - } - } - } else { - for (const auto &entry : std::filesystem::directory_iterator(dirPath)) { - if (entry.is_regular_file()) { - loadFile(entry.path()); - } - } - } - } catch (const std::exception &e) { - E2D_ERROR("加载目录 {} 时出错: {}", directory, e.what()); + (void)pattern; + if (!system_) { + return {}; } - - E2D_DEBUG("已从 {} 加载 {} 个纹理", directory, handles.size()); - return handles; + return system_->loadTextureDir(directory, recursive); } -//=========================================================================== -// 异步加载 -//=========================================================================== - template <> void AssetsModule::loadAsync( const std::string &path, std::function)> callback) { - // 确保异步加载系统已初始化 - if (!asyncLoader_.isRunning()) { - initAsyncLoader(); + if (!system_) { + return; } - - // 创建并提交加载任务 - LoadTask task; - task.type = LoadTask::Type::Texture; - task.priority = LoadTask::Priority::Normal; - task.path = path; - task.textureCallback = callback; - - submitLoadTask(task); + system_->loadTextureAsync(path, std::move(callback)); } template <> void AssetsModule::loadAsync( const std::string &path, std::function)> callback) { - // 确保异步加载系统已初始化 - if (!asyncLoader_.isRunning()) { - initAsyncLoader(); + if (!system_) { + return; } - - // 创建并提交加载任务 - LoadTask task; - task.type = LoadTask::Type::Shader; - task.priority = LoadTask::Priority::Normal; - task.path = path; - task.secondaryPath = ""; - task.shaderCallback = callback; - - submitLoadTask(task); + system_->loadShaderAsync(path, std::move(callback)); } -//=========================================================================== -// 加载器注册 -//=========================================================================== - template <> void AssetsModule::registerLoader( std::unique_ptr> loader) { - textureLoader_ = std::move(loader); + if (!system_) { + textureLoader_ = std::move(loader); + return; + } + system_->registerTextureLoader(std::move(loader)); } template <> void AssetsModule::registerLoader( std::unique_ptr> loader) { - shaderLoader_ = std::move(loader); + if (!system_) { + shaderLoader_ = std::move(loader); + return; + } + system_->registerShaderLoader(std::move(loader)); } -//=========================================================================== -// 默认资源 -//=========================================================================== - bool AssetsModule::createDefaultResources() { - { - Ptr texture = makePtr(); - uint8_t whitePixel[] = {255, 255, 255, 255}; - if (!texture->loadFromMemory(whitePixel, 1, 1, TextureFormat::RGBA8)) { - E2D_ERROR("创建默认纹理失败"); - return false; - } - defaultTexture_ = textures_.insert(texture); - E2D_DEBUG("已创建默认纹理"); + if (!system_) { + return false; } - - { - // 从文件加载默认着色器 - // 使用 FileModule 的 assetPath 来获取正确的资源路径(支持 RomFS) - std::string vertPath = fileSystem_.assetPath("shader/default.vert"); - std::string fragPath = fileSystem_.assetPath("shader/default.frag"); - - if (!fileSystem_.exists(vertPath) || !fileSystem_.exists(fragPath)) { - E2D_ERROR("默认着色器文件未找到: {}, {}", vertPath, fragPath); - return false; - } - - // 读取着色器文件内容 - std::string vsSource = fileSystem_.readString(vertPath); - std::string fsSource = fileSystem_.readString(fragPath); - if (vsSource.empty() || fsSource.empty()) { - E2D_ERROR("读取默认着色器文件失败: {}, {}", vertPath, fragPath); - return false; - } - - // 从源码加载着色器 - Ptr shader = makePtr(); - if (!shader->loadFromSource(vsSource, fsSource)) { - E2D_ERROR("编译默认着色器失败: {}, {}", vertPath, fragPath); - return false; - } - - defaultShader_ = shaders_.insert(shader); - E2D_DEBUG("已从文件加载默认着色器: {}, {}", vertPath, fragPath); - } - - { - // 创建材质布局(与着色器中的 MaterialUBO 匹配) - // layout(std140, binding = 1) uniform MaterialUBO { - // vec4 uColor; // 16 bytes - // vec4 uTintColor; // 16 bytes - // float uOpacity; // 4 bytes - // float uPadding[3]; // 12 bytes - // }; - Ptr layout = makePtr(); - layout->addParam("uColor", MaterialParamType::Color); - layout->addParam("uTintColor", MaterialParamType::Color); - layout->addParam("uOpacity", MaterialParamType::Float); - layout->finalize(); - - Ptr material = makePtr(); - material->setShader(getPtr(defaultShader_)); - material->setLayout(layout); - - // 设置默认材质参数 - material->setColor("uColor", Color::White); - material->setColor("uTintColor", Color::White); - material->setFloat("uOpacity", 1.0f); - - // 添加默认纹理到材质 - material->setTexture("uTexture", getPtr(defaultTexture_), 0); - defaultMaterial_ = materials_.insert(material); - E2D_DEBUG("已创建默认材质,使用默认纹理和布局"); - } - - { - Ptr mesh = Mesh::createQuad(Vec2(1.0f, 1.0f)); - if (!mesh) { - E2D_ERROR("创建默认四边形网格失败"); - return false; - } - defaultQuad_ = meshes_.insert(mesh); - E2D_DEBUG("已创建默认四边形网格"); - } - - return true; + return system_->createDefaults(); } void AssetsModule::destroyDefaultResources() { - materials_.remove(defaultMaterial_); - meshes_.remove(defaultQuad_); - textures_.remove(defaultTexture_); - shaders_.remove(defaultShader_); - - defaultMaterial_ = Handle::invalid(); - defaultQuad_ = Handle::invalid(); - defaultTexture_ = Handle::invalid(); - defaultShader_ = Handle::invalid(); + if (!system_) { + return; + } + system_->destroyDefaults(); } -Handle AssetsModule::getDefaultTexture() { return defaultTexture_; } - -Handle AssetsModule::getDefaultShader() { return defaultShader_; } - -Handle AssetsModule::getDefaultMaterial() { return defaultMaterial_; } - -Handle AssetsModule::getDefaultQuad() { return defaultQuad_; } - -Texture *AssetsModule::getDefaultTexturePtr() { - return textures_.get(defaultTexture_); +Handle AssetsModule::getDefaultTexture() { + return system_ ? system_->defaultTexture() : Handle::invalid(); } -Shader *AssetsModule::getDefaultShaderPtr() { - return shaders_.get(defaultShader_); +Handle AssetsModule::getDefaultShader() { + return system_ ? system_->defaultShader() : Handle::invalid(); } +Handle AssetsModule::getDefaultMaterial() { + return system_ ? system_->defaultMaterial() : Handle::invalid(); +} + +Handle AssetsModule::getDefaultQuad() { + return system_ ? system_->defaultQuad() : Handle::invalid(); +} + +Texture *AssetsModule::getDefaultTexturePtr() { return textures_.get(getDefaultTexture()); } + +Shader *AssetsModule::getDefaultShaderPtr() { return shaders_.get(getDefaultShader()); } + Material *AssetsModule::getDefaultMaterialPtr() { - return materials_.get(defaultMaterial_); + return materials_.get(getDefaultMaterial()); } -Mesh *AssetsModule::getDefaultQuadPtr() { return meshes_.get(defaultQuad_); } - -//=========================================================================== -// 热重载 -//=========================================================================== +Mesh *AssetsModule::getDefaultQuadPtr() { return meshes_.get(getDefaultQuad()); } void AssetsModule::enableHotReload(bool enable) { - hotReloader_.enable(enable); - if (enable) { - E2D_INFO("热重载已启用"); - } else { - E2D_INFO("热重载已禁用"); + if (!system_) { + return; } + system_->enableHotReload(enable); } void AssetsModule::setHotReloadInterval(float interval) { - hotReloader_.setInterval(interval); -} - -void AssetsModule::reloadTexture(const AssetHotReloader::FileWatchInfo &info) { - if (!textureLoader_ || !info.textureHandle.isValid()) { + if (!system_) { return; } - - E2D_INFO("正在重载纹理: {}", info.path); - - // 获取旧纹理指针 - Texture *oldTexture = textures_.get(info.textureHandle); - if (!oldTexture) { - E2D_ERROR("未找到要重载的旧纹理: {}", info.path); - return; - } - - // 直接在原有纹理对象上重新加载 - if (!oldTexture->reloadFromFile(info.path)) { - E2D_ERROR("重载纹理失败: {}", info.path); - return; - } - - E2D_INFO("纹理重载成功: {}", info.path); - notifyTextureReloaded(info.textureHandle); -} - -void AssetsModule::reloadShader(const AssetHotReloader::FileWatchInfo &info) { - if (!shaderLoader_ || !info.shaderHandle.isValid()) { - return; - } - - E2D_INFO("正在重载着色器: {}", info.path); - - // 获取旧着色器指针 - Shader *oldShader = shaders_.get(info.shaderHandle); - if (!oldShader) { - E2D_ERROR("未找到要重载的旧着色器: {}", info.path); - return; - } - - // 查找缓存键 - std::string cacheKey; - { - std::shared_lock lock(mutex_); - for (const auto &pair : shaderPathCache_) { - if (pair.second == info.shaderHandle) { - cacheKey = pair.first; - break; - } - } - } - - if (cacheKey.empty()) { - E2D_WARN("未找到着色器缓存键: {}", info.path); - return; - } - - // 解析顶点/片段着色器路径并重新加载 - size_t sepPos = cacheKey.find('|'); - if (sepPos == std::string::npos) { - // 单文件模式 - 这里暂不支持,因为 ShaderLoader 目前只支持双文件 - E2D_WARN("不支持单文件着色器重载: {}", info.path); - } else { - // 双文件模式 - std::string vertPath = cacheKey.substr(0, sepPos); - std::string fragPath = cacheKey.substr(sepPos + 1); - - // 读取着色器文件内容 - std::string vsSource = fileSystem_.readString(vertPath); - std::string fsSource = fileSystem_.readString(fragPath); - if (vsSource.empty() || fsSource.empty()) { - E2D_ERROR("读取着色器文件失败: {}, {}", vertPath, fragPath); - return; - } - - // 直接在原有着色器对象上重新加载 - if (!oldShader->reloadFromSource(vsSource, fsSource)) { - E2D_ERROR("重载着色器失败: {} + {}", vertPath, fragPath); - return; - } - } - - E2D_INFO("着色器重载成功: {}", info.path); - notifyShaderReloaded(info.shaderHandle); + system_->setHotReloadInterval(interval); } void AssetsModule::checkForChanges() { - hotReloader_.checkForChanges( - [this](const AssetHotReloader::FileWatchInfo &info) { - reloadTexture(info); - }, - [this](const AssetHotReloader::FileWatchInfo &info) { - reloadShader(info); - }); -} - -//=========================================================================== -// 异步加载系统 -//=========================================================================== - -void AssetsModule::initAsyncLoader(uint32_t threadCount) { - if (asyncLoader_.isRunning()) { + if (!system_) { return; } - asyncLoader_.init(threadCount); - E2D_INFO("异步加载器已初始化,使用 {} 个线程", threadCount); + system_->checkForChanges(); +} + +void AssetsModule::initAsyncLoader(uint32_t threadCount) { + if (!system_) { + return; + } + system_->initAsync(threadCount); } void AssetsModule::shutdownAsyncLoader() { - if (!asyncLoader_.isRunning()) { + if (!system_) { return; } - asyncLoader_.shutdown(); - E2D_INFO("异步加载器已关闭"); + system_->shutdownAsync(); } void AssetsModule::submitLoadTask(const LoadTask &task) { - AssetAsyncLoader::Task asyncTask; - asyncTask.priority = static_cast(task.priority); - - if (task.type == LoadTask::Type::Texture) { - auto handle = std::make_shared>(Handle::invalid()); - asyncTask.work = [this, path = task.path, handle]() { - *handle = load(path); - }; - if (task.textureCallback) { - asyncTask.onComplete = [handle, callback = task.textureCallback]() { - callback(*handle); - }; - } - } else { - auto handle = std::make_shared>(Handle::invalid()); - asyncTask.work = [this, path = task.path, secondary = task.secondaryPath, - handle]() { - if (secondary.empty()) { - *handle = load(path); - } else { - *handle = load(path, secondary); - } - }; - if (task.shaderCallback) { - asyncTask.onComplete = [handle, callback = task.shaderCallback]() { - callback(*handle); - }; - } + if (!system_) { + return; + } + if (task.type == LoadTask::Type::Texture) { + system_->loadTextureAsync(task.path, task.textureCallback); + } else { + system_->loadShaderAsync(task.path, task.shaderCallback); } - - asyncLoader_.submit(asyncTask); } void AssetsModule::processAsyncCallbacks() { - asyncLoader_.processCallbacks(); + if (!system_) { + return; + } + system_->processAsyncCallbacks(); } -//=========================================================================== -// 资源依赖跟踪 -//=========================================================================== - void AssetsModule::registerMaterialDependency(Handle material, Handle texture) { - dependencyTracker_.registerMaterialDependency(material, texture); - E2D_DEBUG("已注册材质 {} 对纹理 {} 的依赖", material.index(), texture.index()); + if (!system_) { + return; + } + system_->registerDependency(material, texture); } void AssetsModule::registerMaterialDependency(Handle material, Handle shader) { - dependencyTracker_.registerMaterialDependency(material, shader); - E2D_DEBUG("已注册材质 {} 对着色器 {} 的依赖", material.index(), - shader.index()); + if (!system_) { + return; + } + system_->registerDependency(material, shader); } void AssetsModule::notifyTextureReloaded(Handle texture) { - dependencyTracker_.notifyTextureReloaded( - texture, [this](Handle materialHandle) { - Material *material = materials_.get(materialHandle); - if (material) { - E2D_DEBUG("材质 {} 已更新为重载后的纹理", materialHandle.index()); - } - }); + if (!system_) { + return; + } + system_->notifyTextureReloaded(texture); } void AssetsModule::notifyShaderReloaded(Handle shader) { - dependencyTracker_.notifyShaderReloaded( - shader, [this, shader](Handle materialHandle) { - Material *material = materials_.get(materialHandle); - if (material) { - material->setShader(getPtr(shader)); - E2D_DEBUG("材质 {} 已更新为重载后的着色器", materialHandle.index()); - } - }); + if (!system_) { + return; + } + system_->notifyShaderReloaded(shader); } -//=========================================================================== -// 统计 -//=========================================================================== - AssetsModule::Stats AssetsModule::getStats() const { - std::shared_lock lock(mutex_); - Stats stats; - stats.textureCount = textures_.count(); - stats.shaderCount = shaders_.count(); - stats.materialCount = materials_.count(); - stats.meshCount = meshes_.count(); + if (!system_) { + return stats; + } + AssetSystem::Stats systemStats = system_->stats(); + stats.textureCount = systemStats.textureCount; + stats.shaderCount = systemStats.shaderCount; + stats.materialCount = systemStats.materialCount; + stats.meshCount = systemStats.meshCount; return stats; } } // namespace extra2d + diff --git a/src/assets/builtin/builtin_asset_factory.cpp b/src/assets/builtin/builtin_asset_factory.cpp new file mode 100644 index 0000000..9aac6dc --- /dev/null +++ b/src/assets/builtin/builtin_asset_factory.cpp @@ -0,0 +1,95 @@ +#include +#include + +namespace extra2d { + +BuiltinAssetFactory::BuiltinAssetFactory(AssetStorage &textures, + AssetStorage &shaders, + AssetStorage &materials, + AssetStorage &meshes, + const AssetFileSystem &fileSystem) + : textures_(textures), shaders_(shaders), materials_(materials), meshes_(meshes), + fileSystem_(fileSystem) {} + +bool BuiltinAssetFactory::create() { + { + Ptr texture = makePtr(); + uint8_t whitePixel[] = {255, 255, 255, 255}; + if (!texture->loadFromMemory(whitePixel, 1, 1, TextureFormat::RGBA8)) { + return false; + } + defaultTexture_ = textures_.insert(texture); + } + + { + std::string vertPath = fileSystem_.assetPath("shader/default.vert"); + std::string fragPath = fileSystem_.assetPath("shader/default.frag"); + if (!fileSystem_.exists(vertPath) || !fileSystem_.exists(fragPath)) { + return false; + } + std::string vsSource = fileSystem_.readString(vertPath); + std::string fsSource = fileSystem_.readString(fragPath); + if (vsSource.empty() || fsSource.empty()) { + return false; + } + Ptr shader = makePtr(); + if (!shader->loadFromSource(vsSource, fsSource)) { + return false; + } + defaultShader_ = shaders_.insert(shader); + } + + { + Ptr layout = makePtr(); + layout->addParam("uColor", MaterialParamType::Color); + layout->addParam("uTintColor", MaterialParamType::Color); + layout->addParam("uOpacity", MaterialParamType::Float); + layout->finalize(); + + Ptr material = makePtr(); + material->setShader(shaders_.getPtr(defaultShader_)); + material->setLayout(layout); + material->setColor("uColor", Color::White); + material->setColor("uTintColor", Color::White); + material->setFloat("uOpacity", 1.0f); + material->setTexture("uTexture", textures_.getPtr(defaultTexture_), 0); + defaultMaterial_ = materials_.insert(material); + } + + { + Ptr mesh = Mesh::createQuad(Vec2(1.0f, 1.0f)); + if (!mesh) { + return false; + } + defaultQuad_ = meshes_.insert(mesh); + } + + E2D_DEBUG("BuiltinAssetFactory: 默认资源创建完成"); + return true; +} + +void BuiltinAssetFactory::destroy() { + materials_.remove(defaultMaterial_); + meshes_.remove(defaultQuad_); + textures_.remove(defaultTexture_); + shaders_.remove(defaultShader_); + defaultMaterial_ = Handle::invalid(); + defaultQuad_ = Handle::invalid(); + defaultTexture_ = Handle::invalid(); + defaultShader_ = Handle::invalid(); +} + +Handle BuiltinAssetFactory::defaultTexture() const { + return defaultTexture_; +} + +Handle BuiltinAssetFactory::defaultShader() const { return defaultShader_; } + +Handle BuiltinAssetFactory::defaultMaterial() const { + return defaultMaterial_; +} + +Handle BuiltinAssetFactory::defaultQuad() const { return defaultQuad_; } + +} // namespace extra2d + diff --git a/src/assets/core/asset_system.cpp b/src/assets/core/asset_system.cpp new file mode 100644 index 0000000..57312e4 --- /dev/null +++ b/src/assets/core/asset_system.cpp @@ -0,0 +1,313 @@ +#include +#include +#include +#include + +namespace extra2d { + +AssetSystem::AssetSystem(AssetStorage &textures, + AssetStorage &shaders, + AssetStorage &materials, + AssetStorage &meshes, + std::unique_ptr> &textureLoader, + std::unique_ptr> &shaderLoader) + : textures_(textures), shaders_(shaders), materials_(materials), meshes_(meshes), + textureLoader_(textureLoader), shaderLoader_(shaderLoader), + hotReloadRuntime_(fileSystem_), + builtinFactory_(textures, shaders, materials, meshes, fileSystem_) {} + +Handle AssetSystem::loadTexture(const std::string &path) { + Handle cached = textureCache_.find(path); + if (cached.isValid() && textures_.isValid(cached)) { + return cached; + } + if (!textureLoader_) { + return Handle::invalid(); + } + Ptr texture = textureLoader_->load(path); + if (!texture) { + return Handle::invalid(); + } + Handle handle = textures_.insert(texture); + textureCache_.set(path, handle); + if (hotReloadRuntime_.enabled()) { + hotReloadRuntime_.addWatch(path, handle); + } + return handle; +} + +Handle AssetSystem::loadTextureFromMemory(const std::string &key, + const uint8_t *data, + size_t size) { + Handle cached = textureCache_.find(key); + if (cached.isValid() && textures_.isValid(cached)) { + return cached; + } + if (!textureLoader_) { + return Handle::invalid(); + } + Ptr texture = textureLoader_->loadFromMemory(data, size); + if (!texture) { + return Handle::invalid(); + } + Handle handle = textures_.insert(texture); + textureCache_.set(key, handle); + return handle; +} + +std::vector> +AssetSystem::loadTextureDir(const std::string &directory, bool recursive) { + std::vector> handles; + if (!textureLoader_ || !fileSystem_.exists(directory)) { + return handles; + } + std::filesystem::path dirPath(directory); + auto loadFile = [this, &handles](const std::filesystem::path &filePath) { + std::string ext = filePath.extension().string(); + for (const auto &supported : textureLoader_->getExtensions()) { + if (ext == supported) { + Handle handle = loadTexture(filePath.string()); + if (handle.isValid()) { + handles.push_back(handle); + } + break; + } + } + }; + try { + if (recursive) { + for (const auto &entry : + std::filesystem::recursive_directory_iterator(dirPath)) { + if (entry.is_regular_file()) { + loadFile(entry.path()); + } + } + } else { + for (const auto &entry : std::filesystem::directory_iterator(dirPath)) { + if (entry.is_regular_file()) { + loadFile(entry.path()); + } + } + } + } catch (...) { + return {}; + } + return handles; +} + +Handle AssetSystem::loadShader(const std::string &path) { + Handle cached = shaderCache_.find(path); + if (cached.isValid() && shaders_.isValid(cached)) { + return cached; + } + if (!shaderLoader_) { + return Handle::invalid(); + } + Ptr shader = shaderLoader_->load(path); + if (!shader) { + return Handle::invalid(); + } + Handle handle = shaders_.insert(shader); + shaderCache_.set(path, handle); + if (hotReloadRuntime_.enabled()) { + hotReloadRuntime_.addWatch(path, handle); + } + return handle; +} + +Handle AssetSystem::loadShader(const std::string &vertPath, + const std::string &fragPath) { + std::string key = vertPath + "|" + fragPath; + Handle cached = shaderCache_.find(key); + if (cached.isValid() && shaders_.isValid(cached)) { + return cached; + } + if (!shaderLoader_) { + return Handle::invalid(); + } + ShaderLoader *shaderLoader = static_cast(shaderLoader_.get()); + Ptr shader = shaderLoader->load(vertPath, fragPath); + if (!shader) { + return Handle::invalid(); + } + Handle handle = shaders_.insert(shader); + shaderCache_.set(key, handle); + if (hotReloadRuntime_.enabled()) { + hotReloadRuntime_.addWatch(vertPath, handle); + hotReloadRuntime_.addWatch(fragPath, handle); + } + return handle; +} + +void AssetSystem::initAsync(uint32_t threadCount) { + if (asyncRuntime_.running()) { + return; + } + asyncRuntime_.init(threadCount); +} + +void AssetSystem::shutdownAsync() { + if (!asyncRuntime_.running()) { + return; + } + asyncRuntime_.shutdown(); +} + +void AssetSystem::loadTextureAsync( + const std::string &path, std::function)> callback) { + if (!asyncRuntime_.running()) { + initAsync(); + } + auto handle = std::make_shared>(Handle::invalid()); + AssetAsyncLoader::Task task; + task.priority = AssetAsyncLoader::Priority::Normal; + task.work = [this, path, handle]() { *handle = loadTexture(path); }; + task.onComplete = [handle, callback]() { + if (callback) { + callback(*handle); + } + }; + asyncRuntime_.submit(task); +} + +void AssetSystem::loadShaderAsync( + const std::string &path, std::function)> callback) { + if (!asyncRuntime_.running()) { + initAsync(); + } + auto handle = std::make_shared>(Handle::invalid()); + AssetAsyncLoader::Task task; + task.priority = AssetAsyncLoader::Priority::Normal; + task.work = [this, path, handle]() { *handle = loadShader(path); }; + task.onComplete = [handle, callback]() { + if (callback) { + callback(*handle); + } + }; + asyncRuntime_.submit(task); +} + +void AssetSystem::processAsyncCallbacks() { asyncRuntime_.processCallbacks(); } + +void AssetSystem::registerTextureLoader( + std::unique_ptr> loader) { + textureLoader_ = std::move(loader); +} + +void AssetSystem::registerShaderLoader(std::unique_ptr> loader) { + shaderLoader_ = std::move(loader); +} + +bool AssetSystem::createDefaults() { return builtinFactory_.create(); } + +void AssetSystem::destroyDefaults() { builtinFactory_.destroy(); } + +Handle AssetSystem::defaultTexture() const { + return builtinFactory_.defaultTexture(); +} + +Handle AssetSystem::defaultShader() const { + return builtinFactory_.defaultShader(); +} + +Handle AssetSystem::defaultMaterial() const { + return builtinFactory_.defaultMaterial(); +} + +Handle AssetSystem::defaultQuad() const { + return builtinFactory_.defaultQuad(); +} + +void AssetSystem::enableHotReload(bool enable) { hotReloadRuntime_.enable(enable); } + +void AssetSystem::setHotReloadInterval(float interval) { + hotReloadRuntime_.setInterval(interval); +} + +void AssetSystem::checkForChanges() { + hotReloadRuntime_.check( + [this](const AssetHotReloader::FileWatchInfo &info) { reloadTexture(info); }, + [this](const AssetHotReloader::FileWatchInfo &info) { reloadShader(info); }); +} + +void AssetSystem::reloadTexture(const AssetHotReloader::FileWatchInfo &info) { + if (!info.textureHandle.isValid()) { + return; + } + Texture *texture = textures_.get(info.textureHandle); + if (!texture) { + return; + } + if (!texture->reloadFromFile(info.path)) { + return; + } + notifyTextureReloaded(info.textureHandle); +} + +void AssetSystem::reloadShader(const AssetHotReloader::FileWatchInfo &info) { + if (!info.shaderHandle.isValid()) { + return; + } + Shader *shader = shaders_.get(info.shaderHandle); + if (!shader) { + return; + } + std::string key = shaderCache_.findKeyByHandle(info.shaderHandle); + size_t sep = key.find('|'); + if (sep == std::string::npos) { + return; + } + std::string vertPath = key.substr(0, sep); + std::string fragPath = key.substr(sep + 1); + std::string vsSource = fileSystem_.readString(vertPath); + std::string fsSource = fileSystem_.readString(fragPath); + if (vsSource.empty() || fsSource.empty()) { + return; + } + if (!shader->reloadFromSource(vsSource, fsSource)) { + return; + } + notifyShaderReloaded(info.shaderHandle); +} + +void AssetSystem::registerDependency(Handle material, + Handle texture) { + dependencyGraph_.registerDependency(material, texture); +} + +void AssetSystem::registerDependency(Handle material, + Handle shader) { + dependencyGraph_.registerDependency(material, shader); +} + +void AssetSystem::notifyTextureReloaded(Handle texture) { + dependencyGraph_.notifyTextureReloaded(texture, [](Handle) {}); +} + +void AssetSystem::notifyShaderReloaded(Handle shader) { + dependencyGraph_.notifyShaderReloaded(shader, [this, shader](Handle material) { + Material *ptr = materials_.get(material); + if (ptr) { + ptr->setShader(shaders_.getPtr(shader)); + } + }); +} + +void AssetSystem::clear() { + shutdownAsync(); + hotReloadRuntime_.clear(); + dependencyGraph_.clear(); + textureCache_.clear(); + shaderCache_.clear(); +} + +AssetSystem::Stats AssetSystem::stats() const { + Stats s; + s.textureCount = textures_.count(); + s.shaderCount = shaders_.count(); + s.materialCount = materials_.count(); + s.meshCount = meshes_.count(); + return s; +} + +} // namespace extra2d diff --git a/src/assets/dependency/asset_dependency_graph.cpp b/src/assets/dependency/asset_dependency_graph.cpp new file mode 100644 index 0000000..02e0fcd --- /dev/null +++ b/src/assets/dependency/asset_dependency_graph.cpp @@ -0,0 +1,81 @@ +#include +#include + +namespace extra2d { + +void AssetDependencyGraph::clear() { + std::unique_lock lock(mutex_); + textureDeps_.clear(); + shaderDeps_.clear(); +} + +void AssetDependencyGraph::registerDependency(Handle material, + Handle texture) { + if (!material.isValid() || !texture.isValid()) { + return; + } + std::unique_lock lock(mutex_); + auto &deps = textureDeps_[texture.index()]; + deps.texture = texture; + auto it = std::find(deps.materials.begin(), deps.materials.end(), material); + if (it == deps.materials.end()) { + deps.materials.push_back(material); + } +} + +void AssetDependencyGraph::registerDependency(Handle material, + Handle shader) { + if (!material.isValid() || !shader.isValid()) { + return; + } + std::unique_lock lock(mutex_); + auto &deps = shaderDeps_[shader.index()]; + deps.shader = shader; + auto it = std::find(deps.materials.begin(), deps.materials.end(), material); + if (it == deps.materials.end()) { + deps.materials.push_back(material); + } +} + +void AssetDependencyGraph::notifyTextureReloaded( + Handle texture, + const std::function)> &onMaterialUpdate) const { + if (!texture.isValid()) { + return; + } + std::vector> materials; + { + std::shared_lock lock(mutex_); + auto it = textureDeps_.find(texture.index()); + if (it == textureDeps_.end()) { + return; + } + materials = it->second.materials; + } + for (const auto &material : materials) { + onMaterialUpdate(material); + } +} + +void AssetDependencyGraph::notifyShaderReloaded( + Handle shader, + const std::function)> &onMaterialUpdate) const { + if (!shader.isValid()) { + return; + } + std::vector> materials; + { + std::shared_lock lock(mutex_); + auto it = shaderDeps_.find(shader.index()); + if (it == shaderDeps_.end()) { + return; + } + materials = it->second.materials; + } + for (const auto &material : materials) { + onMaterialUpdate(material); + } +} + +} // namespace extra2d + diff --git a/src/assets/deps/asset_dependency_tracker.cpp b/src/assets/deps/asset_dependency_tracker.cpp deleted file mode 100644 index bc36978..0000000 --- a/src/assets/deps/asset_dependency_tracker.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include -#include - -namespace extra2d { - -void AssetDependencyTracker::clear() { - std::unique_lock lock(mutex_); - textureDependencies_.clear(); - shaderDependencies_.clear(); -} - -void AssetDependencyTracker::registerMaterialDependency(Handle material, - Handle texture) { - if (!material.isValid() || !texture.isValid()) { - return; - } - - std::unique_lock lock(mutex_); - auto &info = textureDependencies_[texture.index()]; - info.texture = texture; - auto it = std::find(info.dependentMaterials.begin(), - info.dependentMaterials.end(), material); - if (it == info.dependentMaterials.end()) { - info.dependentMaterials.push_back(material); - } -} - -void AssetDependencyTracker::registerMaterialDependency(Handle material, - Handle shader) { - if (!material.isValid() || !shader.isValid()) { - return; - } - - std::unique_lock lock(mutex_); - auto &info = shaderDependencies_[shader.index()]; - info.shader = shader; - auto it = std::find(info.dependentMaterials.begin(), - info.dependentMaterials.end(), material); - if (it == info.dependentMaterials.end()) { - info.dependentMaterials.push_back(material); - } -} - -void AssetDependencyTracker::notifyTextureReloaded( - Handle texture, - const std::function)> &onMaterialUpdate) const { - if (!texture.isValid()) { - return; - } - - std::vector> materials; - { - std::shared_lock lock(mutex_); - auto it = textureDependencies_.find(texture.index()); - if (it == textureDependencies_.end()) { - return; - } - materials = it->second.dependentMaterials; - } - - for (const auto &material : materials) { - onMaterialUpdate(material); - } -} - -void AssetDependencyTracker::notifyShaderReloaded( - Handle shader, - const std::function)> &onMaterialUpdate) const { - if (!shader.isValid()) { - return; - } - - std::vector> materials; - { - std::shared_lock lock(mutex_); - auto it = shaderDependencies_.find(shader.index()); - if (it == shaderDependencies_.end()) { - return; - } - materials = it->second.dependentMaterials; - } - - for (const auto &material : materials) { - onMaterialUpdate(material); - } -} - -} // namespace extra2d - diff --git a/src/assets/runtime/asset_async_runtime.cpp b/src/assets/runtime/asset_async_runtime.cpp new file mode 100644 index 0000000..d15f2af --- /dev/null +++ b/src/assets/runtime/asset_async_runtime.cpp @@ -0,0 +1,18 @@ +#include + +namespace extra2d { + +void AssetAsyncRuntime::init(uint32_t threadCount) { loader_.init(threadCount); } + +void AssetAsyncRuntime::shutdown() { loader_.shutdown(); } + +bool AssetAsyncRuntime::running() const { return loader_.isRunning(); } + +void AssetAsyncRuntime::submit(const AssetAsyncLoader::Task &task) { + loader_.submit(task); +} + +void AssetAsyncRuntime::processCallbacks() { loader_.processCallbacks(); } + +} // namespace extra2d + diff --git a/src/assets/runtime/asset_hot_reload_runtime.cpp b/src/assets/runtime/asset_hot_reload_runtime.cpp new file mode 100644 index 0000000..e4e7555 --- /dev/null +++ b/src/assets/runtime/asset_hot_reload_runtime.cpp @@ -0,0 +1,37 @@ +#include + +namespace extra2d { + +AssetHotReloadRuntime::AssetHotReloadRuntime(const AssetFileSystem &fileSystem) + : reloader_(fileSystem) {} + +void AssetHotReloadRuntime::enable(bool enable) { reloader_.enable(enable); } + +bool AssetHotReloadRuntime::enabled() const { return reloader_.enabled(); } + +void AssetHotReloadRuntime::setInterval(float interval) { + reloader_.setInterval(interval); +} + +void AssetHotReloadRuntime::addWatch(const std::string &path, + Handle handle) { + reloader_.addFileWatch(path, handle); +} + +void AssetHotReloadRuntime::addWatch(const std::string &path, + Handle handle) { + reloader_.addFileWatch(path, handle); +} + +void AssetHotReloadRuntime::clear() { reloader_.clear(); } + +void AssetHotReloadRuntime::check( + const std::function + &reloadTexture, + const std::function + &reloadShader) { + reloader_.checkForChanges(reloadTexture, reloadShader); +} + +} // namespace extra2d +