From 0a6e088ebe874cd6ee5e926f482f3717a93b42fe Mon Sep 17 00:00:00 2001 From: Ricardo Antunes Date: Fri, 27 Sep 2024 13:03:16 +0200 Subject: [PATCH] feat(assets): allow unloading a metadata directory --- engine/include/cubos/engine/assets/assets.hpp | 8 ++++++ engine/src/assets/assets.cpp | 24 +++++++++++++++++ engine/src/assets/bridges/file.cpp | 27 +++++++++++++------ 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/engine/include/cubos/engine/assets/assets.hpp b/engine/include/cubos/engine/assets/assets.hpp index 6cfcb38ef..0419572f6 100644 --- a/engine/include/cubos/engine/assets/assets.hpp +++ b/engine/include/cubos/engine/assets/assets.hpp @@ -87,6 +87,14 @@ namespace cubos::engine /// @param path Path to load metadata from. void loadMeta(std::string_view path); + /// @brief Unloads all asset metadata from assets within the given path. + /// + /// If an asset from the given path is currently loaded, it will not be unloaded, but it will be dissociated + /// from its original metadata path. + /// + /// @param path Path to unload metadata from. + void unloadMeta(std::string_view path); + /// @brief Loads the asset with the given handle, upgrading the handle to a strong one. /// /// This method doesn't block, thus the asset may have not yet been loaded when it returns. diff --git a/engine/src/assets/assets.cpp b/engine/src/assets/assets.cpp index fa3412c12..511d3ce06 100644 --- a/engine/src/assets/assets.cpp +++ b/engine/src/assets/assets.cpp @@ -181,6 +181,30 @@ void Assets::loadMeta(std::string_view path) } } +void Assets::unloadMeta(std::string_view path) +{ + std::unique_lock lock(mMutex); + + // Search for assets that have the given path as a prefix and remove the path from their metadata. + std::vector toRemove; + for (auto& [id, entry] : mEntries) + { + std::unique_lock lock(entry->mutex); + + if (auto metaPath = entry->meta.get("path")) + { + if (metaPath->starts_with(path)) + { + entry->meta.remove("path"); + if (entry->status == Status::Unloaded || entry->status == Status::Unknown) + { + toRemove.push_back(id); + } + } + } + } +} + AnyAsset Assets::load(AnyAsset handle) const { auto assetEntry = this->entry(handle); diff --git a/engine/src/assets/bridges/file.cpp b/engine/src/assets/bridges/file.cpp index d891cadfe..d2a0dd764 100644 --- a/engine/src/assets/bridges/file.cpp +++ b/engine/src/assets/bridges/file.cpp @@ -11,17 +11,23 @@ using namespace cubos::engine; bool FileBridge::load(Assets& assets, const AnyAsset& handle) { - auto path = assets.readMeta(handle)->get("path").value(); - auto stream = FileSystem::open(path, File::OpenMode::Read); + auto path = assets.readMeta(handle)->get("path"); + if (!path.has_value()) + { + CUBOS_ERROR("Asset does not have a file path"); + return false; + } + + auto stream = FileSystem::open(*path, File::OpenMode::Read); if (stream == nullptr) { - CUBOS_ERROR("Could not open file {}", path); + CUBOS_ERROR("Could not open file {}", *path); return false; } if (!this->loadFromFile(assets, handle, *stream)) { - CUBOS_ERROR("Could not load asset from file {}", path); + CUBOS_ERROR("Could not load asset from file {}", *path); return false; } @@ -30,9 +36,14 @@ bool FileBridge::load(Assets& assets, const AnyAsset& handle) bool FileBridge::save(const Assets& assets, const AnyAsset& handle) { - auto path = assets.readMeta(handle)->get("path").value(); + auto path = assets.readMeta(handle)->get("path"); + if (!path.has_value()) + { + CUBOS_ERROR("Asset does not have a file path"); + return false; + } - auto swpPath = path + ".swp"; + auto swpPath = *path + ".swp"; auto swpFile = FileSystem::create(swpPath); if (swpFile == nullptr) @@ -58,9 +69,9 @@ bool FileBridge::save(const Assets& assets, const AnyAsset& handle) stream = nullptr; /// @todo This can be done simpler with #737. - if (!FileSystem::copy(swpPath, path)) + if (!FileSystem::copy(swpPath, *path)) { - CUBOS_ERROR("Could not overwrite asset {} with swap file", path); + CUBOS_ERROR("Could not overwrite asset {} with swap file", *path); return false; }