diff --git a/engine/include/cubos/engine/assets/asset.hpp b/engine/include/cubos/engine/assets/asset.hpp index 4152bb98fd..05d4d7e545 100644 --- a/engine/include/cubos/engine/assets/asset.hpp +++ b/engine/include/cubos/engine/assets/asset.hpp @@ -12,6 +12,7 @@ namespace cubos::engine { + template class Asset; @@ -27,6 +28,13 @@ namespace cubos::engine { public: CUBOS_REFLECT; + /// @brief Type of the asset identifier. + enum class IdType + { + UUID, + Path, + Invalid + }; /// @brief Avoid using this field, use @ref getId() instead. /// @todo This was added as a dirty fix for #692, should be removed once the issue is fixed. @@ -71,11 +79,22 @@ namespace cubos::engine /// @return Asset version. int getVersion() const; + /// @brief Gets the type of the asset identifier. + /// @return Asset identifier type. + IdType getIdType() const; + /// @brief Gets the Path or UUID of the asset. /// @return Asset Path or UUID. std::string getIdString() const; - /// @brief Gets the UUID of the asset if it is the case of having one. + /// @brief Gets the UUID of the asset if it has one. + /// + /// There are two possible reasons for an asset handle to have no UUID: + /// - it being an invalid or null handle; + /// - it being created from an asset path. + /// + /// To ensure an asset handle gets a UUID, you can use @ref Assets::load. + /// /// @return Asset UUID. std::optional getId() const; diff --git a/engine/include/cubos/engine/assets/assets.hpp b/engine/include/cubos/engine/assets/assets.hpp index 9fbc243a32..6380cdb9e5 100644 --- a/engine/include/cubos/engine/assets/assets.hpp +++ b/engine/include/cubos/engine/assets/assets.hpp @@ -364,11 +364,6 @@ namespace cubos::engine /// @return Lock guard. std::unique_lock lockWrite(const AnyAsset& handle) const; - /// @brief Checks if the given path is a valid path to an asset. - /// @param path Path to check. - /// @return A string that says if the given string is a path, uuid or not a valid format string - static std::string isPath(const std::string& path); - /// @brief Gets a pointer to the entry associated with the given handle. /// @param handle Handle to get the entry for. /// @return Entry for the given handle, or nullptr if there is no such entry. diff --git a/engine/include/cubos/engine/assets/meta.hpp b/engine/include/cubos/engine/assets/meta.hpp index f42ab493dc..b660ed42da 100644 --- a/engine/include/cubos/engine/assets/meta.hpp +++ b/engine/include/cubos/engine/assets/meta.hpp @@ -52,7 +52,7 @@ namespace cubos::engine /// @brief Gets the path of the asset. /// @return Path of the asset. - std::string getPath() const; + std::optional getPath() const; /// @brief Sets a parameter on the asset's metadata. /// @param key Key of the parameter. diff --git a/engine/src/assets/asset.cpp b/engine/src/assets/asset.cpp index ab4693640d..c7ab5f4f2d 100644 --- a/engine/src/assets/asset.cpp +++ b/engine/src/assets/asset.cpp @@ -43,13 +43,13 @@ AnyAsset::AnyAsset(std::string_view str) pathOrId = str; mId = id.value(); } - else if (str.find('/') != std::string_view::npos || str.find('\\') != std::string_view::npos) + else if (!str.empty() && str[0] == '/') { pathOrId = str; } else { - CUBOS_ERROR("Could not create asset handle, invalid UUID: \"{}\"", str); + CUBOS_ERROR("Could not create asset handle, invalid path or UUID: \"{}\"", str); } } @@ -113,6 +113,19 @@ int AnyAsset::getVersion() const return getId().has_value() && getId().value() == mId ? mVersion : 0; } +AnyAsset::IdType AnyAsset::getIdType() const +{ + if (!pathOrId.empty() && pathOrId[0] == '/') + { + return IdType::Path; + } + else if (auto id = uuids::uuid::from_string(pathOrId)) + { + return IdType::UUID; + } + return IdType::Invalid; +} + std::string AnyAsset::getIdString() const { return pathOrId; diff --git a/engine/src/assets/assets.cpp b/engine/src/assets/assets.cpp index c3d4a1d5ba..86ee08d782 100644 --- a/engine/src/assets/assets.cpp +++ b/engine/src/assets/assets.cpp @@ -621,18 +621,6 @@ std::unique_lock Assets::lockWrite(const AnyAsset& handle) co abort(); } -std::string Assets::isPath(const std::string& path) -{ - if (path.find('/') != std::string::npos || path.find('\\') != std::string::npos) - { - return "Path"; - } - else if (auto id = uuids::uuid::from_string(path)) - { - return "UUID"; - } - return "Invalid format"; -} std::shared_ptr Assets::entry(const AnyAsset& handle) const { // If the handle is null, we can't access the asset. @@ -646,8 +634,9 @@ std::shared_ptr Assets::entry(const AnyAsset& handle) const auto sharedLock = std::shared_lock(mMutex); auto sid = handle.getIdString(); + auto type = handle.getIdType(); - if (isPath(sid) == "Path") + if (type == AnyAsset::IdType::Path) { for (const auto& [eid, entry] : mEntries) { @@ -659,7 +648,7 @@ std::shared_ptr Assets::entry(const AnyAsset& handle) const CUBOS_ERROR("No such asset {}", handle); return nullptr; } - if (isPath(sid) == "UUID") + if (type == AnyAsset::IdType::UUID) { // Search for the entry in the map. auto it = mEntries.find(handle.getId().value()); @@ -697,8 +686,8 @@ std::shared_ptr Assets::entry(const AnyAsset& handle, bool create } auto sid = handle.getIdString(); - - if (isPath(sid) == "Path") + auto type = handle.getIdType(); + if (type == AnyAsset::IdType::Path) { for (const auto& [eid, entry] : mEntries) { @@ -721,9 +710,8 @@ std::shared_ptr Assets::entry(const AnyAsset& handle, bool create CUBOS_ERROR("No such asset {}", handle); return nullptr; } - if (isPath(sid) == "UUID") + else if (type == AnyAsset::IdType::UUID) { - // Search for an existing entry for the asset. auto it = mEntries.find(handle.getId().value()); if (it == mEntries.end()) diff --git a/engine/src/assets/meta.cpp b/engine/src/assets/meta.cpp index a248bb1262..aa2763914f 100644 --- a/engine/src/assets/meta.cpp +++ b/engine/src/assets/meta.cpp @@ -27,11 +27,7 @@ uuids::uuid AssetMeta::getId() const return uuids::uuid::from_string(this->get("id").value()).value(); } -std::string AssetMeta::getPath() const +std::optional AssetMeta::getPath() const { - if (auto path = this->get("path")) - { - return path.value(); - } - return {}; + return this->get("path"); } diff --git a/engine/src/render/mesh/plugin.cpp b/engine/src/render/mesh/plugin.cpp index 23f16f4847..de3660f5b4 100644 --- a/engine/src/render/mesh/plugin.cpp +++ b/engine/src/render/mesh/plugin.cpp @@ -79,7 +79,7 @@ void cubos::engine::renderMeshPlugin(Cubos& cubos) cubos.observer("update RenderMesh on LoadRenderVoxels") .onAdd() - .call([](Commands cmds, State& state, Assets& assets, Query query) { + .call([](Commands cmds, State& state, Assets& assets, Query query) { for (auto [ent, grid] : query) { if (grid.asset.isNull()) @@ -87,8 +87,8 @@ void cubos::engine::renderMeshPlugin(Cubos& cubos) continue; } - // If not loaded, the mId might be a nil UUID, so we need to load the asset first. - assets.load(grid.asset); + // The asset handle might not yet have a valid ID, and since we need getId, we load it first. + grid.asset = assets.load(grid.asset); // If the asset has never been loaded, or it has been updated since the last meshing, update the entry // and queue a meshing task. Otherwise, just reuse the existing mesh. auto& entry = state.entries[grid.asset.getId().value()];