diff --git a/source/blender/asset_system/AS_asset_identifier.hh b/source/blender/asset_system/AS_asset_identifier.hh new file mode 100644 index 00000000000..33b7f71becc --- /dev/null +++ b/source/blender/asset_system/AS_asset_identifier.hh @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup asset_system + * + * \brief Information to uniquely identify and locate an asset. + * + * https://wiki.blender.org/wiki/Source/Architecture/Asset_System/Back_End#Asset_Identifier + */ + +#pragma once + +#include +#include + +namespace blender::asset_system { + +class AssetIdentifier { + std::shared_ptr library_root_path_; + std::string relative_asset_path_; + + public: + AssetIdentifier(std::shared_ptr library_root_path, std::string relative_asset_path); + AssetIdentifier(AssetIdentifier &&) = default; + AssetIdentifier(const AssetIdentifier &) = default; + + std::string full_path() const; +}; + +} // namespace blender::asset_system diff --git a/source/blender/asset_system/AS_asset_library.hh b/source/blender/asset_system/AS_asset_library.hh index 7df6e6d9f51..9f9b1b80343 100644 --- a/source/blender/asset_system/AS_asset_library.hh +++ b/source/blender/asset_system/AS_asset_library.hh @@ -24,6 +24,7 @@ struct Main; namespace blender::asset_system { +class AssetIdentifier; class AssetRepresentation; class AssetStorage; @@ -35,8 +36,10 @@ class AssetStorage; */ class AssetLibrary { /** If this is an asset library on disk, the top-level directory path. Normalized using - * #normalize_directory_path().*/ - std::string root_path_; + * #normalize_directory_path(). Shared pointer so assets can safely point to it, and don't have + * to hold a copy (which is the size of `std::string` + the allocated buffer, if no short string + * optimization is used). With thousands of assets this might make a reasonable difference. */ + std::shared_ptr root_path_; /** Storage for assets (better said their representations) that are considered to be part of this * library. Assets are not automatically loaded into this when loading an asset library. Assets @@ -79,10 +82,16 @@ class AssetLibrary { * representation is not needed anymore, it must be freed using #remove_asset(), or there will be * leaking that's only cleared when the library storage is destructed (typically on exit or * loading a different file). + * + * \param relative_asset_path: The path of the asset relative to the asset library root. With + * this the asset must be uniquely identifiable within the asset + * library. */ - AssetRepresentation &add_external_asset(StringRef name, std::unique_ptr metadata); + AssetRepresentation &add_external_asset(StringRef relative_asset_path, + StringRef name, + std::unique_ptr metadata); /** See #AssetLibrary::add_external_asset(). */ - AssetRepresentation &add_local_id_asset(ID &id); + AssetRepresentation &add_local_id_asset(StringRef relative_asset_path, ID &id); /** Remove an asset from the library that was added using #add_external_asset() or * #add_local_id_asset(). Can usually be expected to be constant time complexity (worst case may * differ). @@ -112,6 +121,12 @@ class AssetLibrary { void on_blend_save_post(Main *bmain, PointerRNA **pointers, int num_pointers); + /** + * Create an asset identifier from the root path of this asset library and the given relative + * asset path (relative to the asset library root directory). + */ + AssetIdentifier derive_asset_identifier(StringRef relative_asset_path); + StringRefNull root_path() const; private: diff --git a/source/blender/asset_system/AS_asset_representation.hh b/source/blender/asset_system/AS_asset_representation.hh index 853222c8dc7..65f7e08f395 100644 --- a/source/blender/asset_system/AS_asset_representation.hh +++ b/source/blender/asset_system/AS_asset_representation.hh @@ -16,21 +16,23 @@ #include "BLI_string_ref.hh" +#include "AS_asset_identifier.hh" + struct AssetMetaData; struct ID; namespace blender::asset_system { class AssetRepresentation { - struct ExternalAsset { - std::string name; - std::unique_ptr metadata_ = nullptr; - }; - + AssetIdentifier identifier_; /** Indicate if this is a local or external asset, and as such, which of the union members below * should be used. */ const bool is_local_id_ = false; + struct ExternalAsset { + std::string name; + std::unique_ptr metadata_ = nullptr; + }; union { ExternalAsset external_asset_; ID *local_asset_id_ = nullptr; /* Non-owning. */ @@ -40,10 +42,12 @@ class AssetRepresentation { public: /** Constructs an asset representation for an external ID. The asset will not be editable. */ - explicit AssetRepresentation(StringRef name, std::unique_ptr metadata); + AssetRepresentation(AssetIdentifier &&identifier, + StringRef name, + std::unique_ptr metadata); /** Constructs an asset representation for an ID stored in the current file. This makes the asset * local and fully editable. */ - explicit AssetRepresentation(ID &id); + AssetRepresentation(AssetIdentifier &&identifier, ID &id); AssetRepresentation(AssetRepresentation &&other); /* Non-copyable type. */ AssetRepresentation(const AssetRepresentation &other) = delete; @@ -55,6 +59,8 @@ class AssetRepresentation { /* Non-copyable type. */ AssetRepresentation &operator=(const AssetRepresentation &other) = delete; + const AssetIdentifier &get_identifier() const; + StringRefNull get_name() const; AssetMetaData &get_metadata() const; /** Returns if this asset is stored inside this current file, and as such fully editable. */ @@ -62,3 +68,8 @@ class AssetRepresentation { }; } // namespace blender::asset_system + +/* C-Handle */ +struct AssetRepresentation; + +const std::string AS_asset_representation_full_path_get(const ::AssetRepresentation *asset); diff --git a/source/blender/asset_system/CMakeLists.txt b/source/blender/asset_system/CMakeLists.txt index c9ef11d33f4..de1f41667d5 100644 --- a/source/blender/asset_system/CMakeLists.txt +++ b/source/blender/asset_system/CMakeLists.txt @@ -17,6 +17,7 @@ set(SRC intern/asset_catalog.cc intern/asset_catalog_path.cc intern/asset_catalog_tree.cc + intern/asset_identifier.cc intern/asset_library.cc intern/asset_library_service.cc intern/asset_representation.cc @@ -26,6 +27,7 @@ set(SRC AS_asset_catalog.hh AS_asset_catalog_path.hh AS_asset_catalog_tree.hh + AS_asset_identifier.hh AS_asset_library.hh AS_asset_representation.hh intern/asset_library_service.hh diff --git a/source/blender/asset_system/intern/asset_identifier.cc b/source/blender/asset_system/intern/asset_identifier.cc new file mode 100644 index 00000000000..94a15103b52 --- /dev/null +++ b/source/blender/asset_system/intern/asset_identifier.cc @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup asset_system + */ + +#include "BLI_path_util.h" +#include + +#include "AS_asset_identifier.hh" + +namespace blender::asset_system { + +AssetIdentifier::AssetIdentifier(std::shared_ptr library_root_path, + std::string relative_asset_path) + : library_root_path_(library_root_path), relative_asset_path_(relative_asset_path) +{ +} + +std::string AssetIdentifier::full_path() const +{ + char path[FILE_MAX]; + BLI_path_join(path, sizeof(path), library_root_path_->c_str(), relative_asset_path_.c_str()); + return path; +} + +} // namespace blender::asset_system diff --git a/source/blender/asset_system/intern/asset_library.cc b/source/blender/asset_system/intern/asset_library.cc index 7bdffe9abad..2f3b56d226a 100644 --- a/source/blender/asset_system/intern/asset_library.cc +++ b/source/blender/asset_system/intern/asset_library.cc @@ -7,6 +7,7 @@ #include #include "AS_asset_catalog_tree.hh" +#include "AS_asset_identifier.hh" #include "AS_asset_library.h" #include "AS_asset_library.hh" #include "AS_asset_representation.hh" @@ -122,7 +123,7 @@ void AS_asset_library_remap_ids(const IDRemapper *mappings) namespace blender::asset_system { AssetLibrary::AssetLibrary(StringRef root_path) - : root_path_(utils::normalize_directory_path(root_path)), + : root_path_(std::make_shared(utils::normalize_directory_path(root_path))), asset_storage_(std::make_unique()), catalog_service(std::make_unique()) { @@ -147,15 +148,18 @@ void AssetLibrary::refresh() this->catalog_service->reload_catalogs(); } -AssetRepresentation &AssetLibrary::add_external_asset(StringRef name, +AssetRepresentation &AssetLibrary::add_external_asset(StringRef relative_asset_path, + StringRef name, std::unique_ptr metadata) { - return asset_storage_->add_external_asset(name, std::move(metadata)); + AssetIdentifier identifier = derive_asset_identifier(relative_asset_path); + return asset_storage_->add_external_asset(std::move(identifier), name, std::move(metadata)); } -AssetRepresentation &AssetLibrary::add_local_id_asset(ID &id) +AssetRepresentation &AssetLibrary::add_local_id_asset(StringRef relative_asset_path, ID &id) { - return asset_storage_->add_local_id_asset(id); + AssetIdentifier identifier = derive_asset_identifier(relative_asset_path); + return asset_storage_->add_local_id_asset(std::move(identifier), id); } bool AssetLibrary::remove_asset(AssetRepresentation &asset) @@ -211,6 +215,11 @@ void AssetLibrary::on_blend_save_post(struct Main *main, } } +AssetIdentifier AssetLibrary::derive_asset_identifier(StringRef relative_asset_path) +{ + return AssetIdentifier(root_path_, relative_asset_path); +} + void AssetLibrary::refresh_catalog_simplename(struct AssetMetaData *asset_data) { if (BLI_uuid_is_nil(asset_data->catalog_id)) { @@ -228,7 +237,7 @@ void AssetLibrary::refresh_catalog_simplename(struct AssetMetaData *asset_data) StringRefNull AssetLibrary::root_path() const { - return root_path_; + return *root_path_; } Vector all_valid_asset_library_refs() diff --git a/source/blender/asset_system/intern/asset_representation.cc b/source/blender/asset_system/intern/asset_representation.cc index b1e76da0f75..c6bc5193570 100644 --- a/source/blender/asset_system/intern/asset_representation.cc +++ b/source/blender/asset_system/intern/asset_representation.cc @@ -9,6 +9,7 @@ #include "DNA_ID.h" #include "DNA_asset_types.h" +#include "AS_asset_identifier.hh" #include "AS_asset_representation.h" #include "AS_asset_representation.hh" @@ -16,14 +17,17 @@ namespace blender::asset_system { -AssetRepresentation::AssetRepresentation(StringRef name, std::unique_ptr metadata) - : is_local_id_(false), external_asset_() +AssetRepresentation::AssetRepresentation(AssetIdentifier &&identifier, + StringRef name, + std::unique_ptr metadata) + : identifier_(identifier), is_local_id_(false), external_asset_() { external_asset_.name = name; external_asset_.metadata_ = std::move(metadata); } -AssetRepresentation::AssetRepresentation(ID &id) : is_local_id_(true), local_asset_id_(&id) +AssetRepresentation::AssetRepresentation(AssetIdentifier &&identifier, ID &id) + : identifier_(identifier), is_local_id_(true), local_asset_id_(&id) { if (!id.asset_data) { throw std::invalid_argument("Passed ID is not an asset"); @@ -31,7 +35,7 @@ AssetRepresentation::AssetRepresentation(ID &id) : is_local_id_(true), local_ass } AssetRepresentation::AssetRepresentation(AssetRepresentation &&other) - : is_local_id_(other.is_local_id_) + : identifier_(std::move(other.identifier_)), is_local_id_(other.is_local_id_) { if (is_local_id_) { local_asset_id_ = other.local_asset_id_; @@ -49,6 +53,11 @@ AssetRepresentation::~AssetRepresentation() } } +const AssetIdentifier &AssetRepresentation::get_identifier() const +{ + return identifier_; +} + StringRefNull AssetRepresentation::get_name() const { if (is_local_id_) { @@ -70,12 +79,20 @@ bool AssetRepresentation::is_local_id() const } // namespace blender::asset_system +using namespace blender; + +const std::string AS_asset_representation_full_path_get(const AssetRepresentation *asset_handle) +{ + const asset_system::AssetRepresentation *asset = + reinterpret_cast(asset_handle); + const asset_system::AssetIdentifier &identifier = asset->get_identifier(); + return identifier.full_path(); +} + /* ---------------------------------------------------------------------- */ /** \name C-API * \{ */ -using namespace blender; - const char *AS_asset_representation_name_get(const AssetRepresentation *asset_handle) { const asset_system::AssetRepresentation *asset = diff --git a/source/blender/asset_system/intern/asset_storage.cc b/source/blender/asset_system/intern/asset_storage.cc index d21468a9c8e..73b9d582616 100644 --- a/source/blender/asset_system/intern/asset_storage.cc +++ b/source/blender/asset_system/intern/asset_storage.cc @@ -15,16 +15,18 @@ namespace blender::asset_system { -AssetRepresentation &AssetStorage::add_local_id_asset(ID &id) +AssetRepresentation &AssetStorage::add_local_id_asset(AssetIdentifier &&identifier, ID &id) { - return *local_id_assets_.lookup_key_or_add(std::make_unique(id)); + return *local_id_assets_.lookup_key_or_add( + std::make_unique(std::move(identifier), id)); } -AssetRepresentation &AssetStorage::add_external_asset(StringRef name, +AssetRepresentation &AssetStorage::add_external_asset(AssetIdentifier &&identifier, + StringRef name, std::unique_ptr metadata) { return *external_assets_.lookup_key_or_add( - std::make_unique(name, std::move(metadata))); + std::make_unique(std::move(identifier), name, std::move(metadata))); } bool AssetStorage::remove_asset(AssetRepresentation &asset) diff --git a/source/blender/asset_system/intern/asset_storage.hh b/source/blender/asset_system/intern/asset_storage.hh index 9278b3f41d1..2b4614abca5 100644 --- a/source/blender/asset_system/intern/asset_storage.hh +++ b/source/blender/asset_system/intern/asset_storage.hh @@ -19,6 +19,7 @@ struct IDRemapper; namespace blender::asset_system { +class AssetIdentifier; class AssetRepresentation; class AssetStorage { @@ -32,9 +33,11 @@ class AssetStorage { public: /** See #AssetLibrary::add_external_asset(). */ - AssetRepresentation &add_external_asset(StringRef name, std::unique_ptr metadata); + AssetRepresentation &add_external_asset(AssetIdentifier &&identifier, + StringRef name, + std::unique_ptr metadata); /** See #AssetLibrary::add_external_asset(). */ - AssetRepresentation &add_local_id_asset(ID &id); + AssetRepresentation &add_local_id_asset(AssetIdentifier &&identifier, ID &id); /** See #AssetLibrary::remove_asset(). */ bool remove_asset(AssetRepresentation &asset); diff --git a/source/blender/editors/space_file/filelist.cc b/source/blender/editors/space_file/filelist.cc index 4a27893e985..b97f1e27a1a 100644 --- a/source/blender/editors/space_file/filelist.cc +++ b/source/blender/editors/space_file/filelist.cc @@ -3099,8 +3099,8 @@ static void filelist_readjob_list_lib_add_datablock(FileListReadJob *job_params, datablock_info->asset_data); BKE_asset_metadata_free(&datablock_info->asset_data); - entry->asset = &filelist->asset_library->add_external_asset(datablock_info->name, - std::move(metadata)); + entry->asset = &filelist->asset_library->add_external_asset( + entry->relpath, datablock_info->name, std::move(metadata)); } } } @@ -3745,7 +3745,8 @@ static void filelist_readjob_main_assets_add_items(FileListReadJob *job_params, const char *id_code_name = BKE_idtype_idcode_to_name(GS(id_iter->name)); entry = MEM_cnew(__func__); - entry->relpath = current_relpath_append(job_params, id_code_name); + std::string datablock_path = StringRef(id_code_name) + "/" + (id_iter->name + 2); + entry->relpath = current_relpath_append(job_params, datablock_path.c_str()); entry->name = id_iter->name + 2; entry->free_name = false; entry->typeflag |= FILE_TYPE_BLENDERLIB | FILE_TYPE_ASSET; @@ -3755,7 +3756,7 @@ static void filelist_readjob_main_assets_add_items(FileListReadJob *job_params, id_iter); entry->local_data.id = id_iter; if (filelist->asset_library) { - entry->asset = &filelist->asset_library->add_local_id_asset(*id_iter); + entry->asset = &filelist->asset_library->add_local_id_asset(entry->relpath, *id_iter); } entries_num++; BLI_addtail(&tmp_entries, entry);