Asset system: Initial asset identifier type
No user visible changes expected. `AssetIdentifier` holds information to uniquely identify and locate an asset. More information: https://wiki.blender.org/wiki/Source/Architecture/Asset_System/Back_End#Asset_Identifier For the start this is tied quite a bit to file paths, so that external assets are assumed to be in the file system. This is needed to support an "All" asset library (see T102879), which would contain assets from different locations. Currently the location of an asset is queried via the file browser backend, which however requires a common root location. It also moves us further away from the file browser towards the asset system (see T87235) and allows us to remove some hacks (see following commit).
This commit is contained in:
parent
cfaca0d9ab
commit
f68da703a5
|
@ -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 <memory>
|
||||
#include <string>
|
||||
|
||||
namespace blender::asset_system {
|
||||
|
||||
class AssetIdentifier {
|
||||
std::shared_ptr<std::string> library_root_path_;
|
||||
std::string relative_asset_path_;
|
||||
|
||||
public:
|
||||
AssetIdentifier(std::shared_ptr<std::string> library_root_path, std::string relative_asset_path);
|
||||
AssetIdentifier(AssetIdentifier &&) = default;
|
||||
AssetIdentifier(const AssetIdentifier &) = default;
|
||||
|
||||
std::string full_path() const;
|
||||
};
|
||||
|
||||
} // namespace blender::asset_system
|
|
@ -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<std::string> 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<AssetMetaData> metadata);
|
||||
AssetRepresentation &add_external_asset(StringRef relative_asset_path,
|
||||
StringRef name,
|
||||
std::unique_ptr<AssetMetaData> 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:
|
||||
|
|
|
@ -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<AssetMetaData> 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<AssetMetaData> 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<AssetMetaData> metadata);
|
||||
AssetRepresentation(AssetIdentifier &&identifier,
|
||||
StringRef name,
|
||||
std::unique_ptr<AssetMetaData> 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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup asset_system
|
||||
*/
|
||||
|
||||
#include "BLI_path_util.h"
|
||||
#include <iostream>
|
||||
|
||||
#include "AS_asset_identifier.hh"
|
||||
|
||||
namespace blender::asset_system {
|
||||
|
||||
AssetIdentifier::AssetIdentifier(std::shared_ptr<std::string> 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
|
|
@ -7,6 +7,7 @@
|
|||
#include <memory>
|
||||
|
||||
#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<std::string>(utils::normalize_directory_path(root_path))),
|
||||
asset_storage_(std::make_unique<AssetStorage>()),
|
||||
catalog_service(std::make_unique<AssetCatalogService>())
|
||||
{
|
||||
|
@ -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<AssetMetaData> 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<AssetLibraryReference> all_valid_asset_library_refs()
|
||||
|
|
|
@ -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<AssetMetaData> metadata)
|
||||
: is_local_id_(false), external_asset_()
|
||||
AssetRepresentation::AssetRepresentation(AssetIdentifier &&identifier,
|
||||
StringRef name,
|
||||
std::unique_ptr<AssetMetaData> 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<const asset_system::AssetRepresentation *>(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 =
|
||||
|
|
|
@ -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<AssetRepresentation>(id));
|
||||
return *local_id_assets_.lookup_key_or_add(
|
||||
std::make_unique<AssetRepresentation>(std::move(identifier), id));
|
||||
}
|
||||
|
||||
AssetRepresentation &AssetStorage::add_external_asset(StringRef name,
|
||||
AssetRepresentation &AssetStorage::add_external_asset(AssetIdentifier &&identifier,
|
||||
StringRef name,
|
||||
std::unique_ptr<AssetMetaData> metadata)
|
||||
{
|
||||
return *external_assets_.lookup_key_or_add(
|
||||
std::make_unique<AssetRepresentation>(name, std::move(metadata)));
|
||||
std::make_unique<AssetRepresentation>(std::move(identifier), name, std::move(metadata)));
|
||||
}
|
||||
|
||||
bool AssetStorage::remove_asset(AssetRepresentation &asset)
|
||||
|
|
|
@ -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<AssetMetaData> metadata);
|
||||
AssetRepresentation &add_external_asset(AssetIdentifier &&identifier,
|
||||
StringRef name,
|
||||
std::unique_ptr<AssetMetaData> 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);
|
||||
|
|
|
@ -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<FileListInternEntry>(__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);
|
||||
|
|
Loading…
Reference in New Issue