Compare commits
27 Commits
temp-vulka
...
temp-asset
Author | SHA1 | Date | |
---|---|---|---|
5c342b1000 | |||
b090c18ce4 | |||
2e1ba1ee20 | |||
ffafde7bd6 | |||
84cc68b68f | |||
3fb8ad93ad | |||
ab92154104 | |||
e1c0e2f7f1 | |||
49964a5abe | |||
9ca80d7564 | |||
9822a79f90 | |||
0e2a400f11 | |||
9e67d373df | |||
0a8effa0f6 | |||
cffb0ba217 | |||
98fc2aa93f | |||
dc5d7441e7 | |||
8ed8d21f5e | |||
195a1c7fc8 | |||
14db6975e6 | |||
61eb425db8 | |||
efaeed1c17 | |||
3de27e2ed9 | |||
acb8aa8834 | |||
d7936c2de0 | |||
8bc3363c0f | |||
968b0495e2 |
@@ -23,6 +23,9 @@ struct ID;
|
||||
struct IDProperty;
|
||||
struct PreviewImage;
|
||||
|
||||
/** C handle for #bke::AssetRepresentation. */
|
||||
typedef struct AssetRepresentation AssetRepresentation;
|
||||
|
||||
typedef void (*PreSaveFn)(void *asset_ptr, struct AssetMetaData *asset_data);
|
||||
|
||||
typedef struct AssetTypeInfo {
|
||||
@@ -68,6 +71,20 @@ struct PreviewImage *BKE_asset_metadata_preview_get_from_id(const struct AssetMe
|
||||
void BKE_asset_metadata_write(struct BlendWriter *writer, struct AssetMetaData *asset_data);
|
||||
void BKE_asset_metadata_read(struct BlendDataReader *reader, struct AssetMetaData *asset_data);
|
||||
|
||||
AssetMetaData *BKE_asset_representation_metadata_get(const AssetRepresentation *asset)
|
||||
ATTR_WARN_UNUSED_RESULT;
|
||||
bool BKE_asset_representation_is_local_id(const AssetRepresentation *asset)
|
||||
ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
# include <memory>
|
||||
|
||||
[[nodiscard]] std::unique_ptr<AssetMetaData> BKE_asset_metadata_move_to_unique_ptr(
|
||||
AssetMetaData *asset_data);
|
||||
|
||||
#endif
|
||||
|
@@ -6,6 +6,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
struct IDRemapper;
|
||||
struct Main;
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -24,41 +25,6 @@ typedef struct AssetLibrary AssetLibrary;
|
||||
*/
|
||||
struct AssetLibrary *BKE_asset_library_load(const char *library_path);
|
||||
|
||||
/**
|
||||
* Try to find an appropriate location for an asset library root from a file or directory path.
|
||||
* Does not check if \a input_path exists.
|
||||
*
|
||||
* The design is made to find an appropriate asset library path from a .blend file path, but
|
||||
* technically works with any file or directory as \a input_path.
|
||||
* Design is:
|
||||
* * If \a input_path lies within a known asset library path (i.e. an asset library registered in
|
||||
* the Preferences), return the asset library path.
|
||||
* * Otherwise, if \a input_path has a parent path, return the parent path (e.g. to use the
|
||||
* directory a .blend file is in as asset library root).
|
||||
* * If \a input_path is empty or doesn't have a parent path (e.g. because a .blend wasn't saved
|
||||
* yet), there is no suitable path. The caller has to decide how to handle this case.
|
||||
*
|
||||
* \param r_library_path: The returned asset library path with a trailing slash, or an empty string
|
||||
* if no suitable path is found. Assumed to be a buffer of at least
|
||||
* #FILE_MAXDIR bytes.
|
||||
*
|
||||
* \return True if the function could find a valid, that is, a non-empty path to return in \a
|
||||
* r_library_path.
|
||||
*/
|
||||
bool BKE_asset_library_find_suitable_root_path_from_path(
|
||||
const char *input_path, char r_library_path[768 /* FILE_MAXDIR */]);
|
||||
/**
|
||||
* Uses the current location on disk of the file represented by \a bmain as input to
|
||||
* #BKE_asset_library_find_suitable_root_path_from_path(). Refer to it for a design
|
||||
* description.
|
||||
*
|
||||
* \return True if the function could find a valid, that is, a non-empty path to return in \a
|
||||
* r_library_path. If \a bmain wasn't saved into a file yet, the return value will be
|
||||
* false.
|
||||
*/
|
||||
bool BKE_asset_library_find_suitable_root_path_from_main(
|
||||
const struct Main *bmain, char r_library_path[768 /* FILE_MAXDIR */]);
|
||||
|
||||
/** Look up the asset's catalog and copy its simple name into #asset_data. */
|
||||
void BKE_asset_library_refresh_catalog_simplename(struct AssetLibrary *asset_library,
|
||||
struct AssetMetaData *asset_data);
|
||||
@@ -66,6 +32,8 @@ void BKE_asset_library_refresh_catalog_simplename(struct AssetLibrary *asset_lib
|
||||
/** Return whether any loaded AssetLibrary has unsaved changes to its catalogs. */
|
||||
bool BKE_asset_library_has_any_unsaved_catalogs(void);
|
||||
|
||||
void BKE_asset_library_remap_ids(struct IDRemapper *mappings);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -12,6 +12,9 @@
|
||||
|
||||
#include "DNA_asset_types.h"
|
||||
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
#include "BKE_asset_library.h"
|
||||
|
||||
#include "BKE_asset_catalog.hh"
|
||||
@@ -19,27 +22,50 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
struct AssetLibraryReference;
|
||||
struct Main;
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
struct AssetRepresentation;
|
||||
|
||||
/**
|
||||
* AssetLibrary provides access to an asset library's data.
|
||||
* For now this is only for catalogs, later this can be expanded to indexes/caches/more.
|
||||
*
|
||||
* The asset library contains catalogs and storage for asset representations. It could be extended
|
||||
* to also include asset indexes and more.
|
||||
*/
|
||||
struct AssetLibrary {
|
||||
/* Controlled by #ED_asset_catalogs_set_save_catalogs_when_file_is_saved,
|
||||
* for managing the "Save Catalog Changes" in the quit-confirmation dialog box. */
|
||||
static bool save_catalogs_when_file_is_saved;
|
||||
|
||||
/** The directory representing the root of this library. */
|
||||
std::string root_path;
|
||||
|
||||
std::unique_ptr<AssetCatalogService> catalog_service;
|
||||
|
||||
AssetLibrary();
|
||||
~AssetLibrary();
|
||||
|
||||
void load(StringRefNull library_root_directory);
|
||||
void load_catalogs(StringRefNull library_root_directory);
|
||||
|
||||
/** Load catalogs that have changed on disk. */
|
||||
void refresh();
|
||||
|
||||
/**
|
||||
* Create a representation of an asset to be considered part of this library. Once the
|
||||
* 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).
|
||||
*/
|
||||
AssetRepresentation &add_external_asset(std::unique_ptr<AssetMetaData> metadata);
|
||||
AssetRepresentation &add_local_id_asset(ID &id);
|
||||
/** Remove an asset from the library that was added using #add_external_asset() or
|
||||
* #add_local_id_asset().
|
||||
* \return True on success, false if the asset couldn't be found inside the library. */
|
||||
bool remove_asset(AssetRepresentation &asset);
|
||||
|
||||
/**
|
||||
* Update `catalog_simple_name` by looking up the asset's catalog by its ID.
|
||||
*
|
||||
@@ -53,8 +79,27 @@ struct AssetLibrary {
|
||||
|
||||
void on_blend_save_post(Main *bmain, PointerRNA **pointers, int num_pointers);
|
||||
|
||||
void remap_ids(struct IDRemapper &mappings);
|
||||
|
||||
private:
|
||||
bCallbackFuncStore on_save_callback_store_{};
|
||||
|
||||
/** 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
|
||||
* have to be loaded externally and added to this storage via #add_external_asset() or
|
||||
* #add_local_id_asset(). So this really is arbitrary storage as far as #AssetLibrary is
|
||||
* concerned (allowing the API user to manage partial library storage and partial loading, so
|
||||
* only relevant parts of a library are kept in memory).
|
||||
*
|
||||
* For now, multiple parts of Blender just keep adding their own assets to this storage. E.g.
|
||||
* multiple asset browsers might load multiple representations for the same asset into this.
|
||||
* Currently there is just no way to properly identify assets, or keep track of which assets are
|
||||
* already in memory and which not. Neither do we keep track of how many parts of Blender are
|
||||
* using an asset or an asset library, which is needed to know when assets can be freed.
|
||||
*/
|
||||
Vector<std::unique_ptr<AssetRepresentation>> asset_storage_;
|
||||
|
||||
std::optional<int> find_asset_index(const AssetRepresentation &asset);
|
||||
};
|
||||
|
||||
Vector<AssetLibraryReference> all_valid_asset_library_refs();
|
||||
@@ -64,6 +109,40 @@ Vector<AssetLibraryReference> all_valid_asset_library_refs();
|
||||
blender::bke::AssetLibrary *BKE_asset_library_load(const Main *bmain,
|
||||
const AssetLibraryReference &library_reference);
|
||||
|
||||
/**
|
||||
* Try to find an appropriate location for an asset library root from a file or directory path.
|
||||
* Does not check if \a input_path exists.
|
||||
*
|
||||
* The design is made to find an appropriate asset library path from a .blend file path, but
|
||||
* technically works with any file or directory as \a input_path.
|
||||
* Design is:
|
||||
* * If \a input_path lies within a known asset library path (i.e. an asset library registered in
|
||||
* the Preferences), return the asset library path.
|
||||
* * Otherwise, if \a input_path has a parent path, return the parent path (e.g. to use the
|
||||
* directory a .blend file is in as asset library root).
|
||||
* * If \a input_path is empty or doesn't have a parent path (e.g. because a .blend wasn't saved
|
||||
* yet), there is no suitable path. The caller has to decide how to handle this case.
|
||||
*
|
||||
* \param r_library_path: The returned asset library path with a trailing slash, or an empty string
|
||||
* if no suitable path is found. Assumed to be a buffer of at least
|
||||
* #FILE_MAXDIR bytes.
|
||||
*
|
||||
* \return True if the function could find a valid, that is, a non-empty path to return in \a
|
||||
* r_library_path.
|
||||
*/
|
||||
std::string BKE_asset_library_find_suitable_root_path_from_path(blender::StringRefNull input_path);
|
||||
|
||||
/**
|
||||
* Uses the current location on disk of the file represented by \a bmain as input to
|
||||
* #BKE_asset_library_find_suitable_root_path_from_path(). Refer to it for a design
|
||||
* description.
|
||||
*
|
||||
* \return True if the function could find a valid, that is, a non-empty path to return in \a
|
||||
* r_library_path. If \a bmain wasn't saved into a file yet, the return value will be
|
||||
* false.
|
||||
*/
|
||||
std::string BKE_asset_library_find_suitable_root_path_from_main(const struct Main *bmain);
|
||||
|
||||
blender::bke::AssetCatalogService *BKE_asset_library_get_catalog_service(
|
||||
const ::AssetLibrary *library);
|
||||
blender::bke::AssetCatalogTree *BKE_asset_library_get_catalog_tree(const ::AssetLibrary *library);
|
||||
|
43
source/blender/blenkernel/BKE_asset_representation.hh
Normal file
43
source/blender/blenkernel/BKE_asset_representation.hh
Normal file
@@ -0,0 +1,43 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
struct AssetMetaData;
|
||||
struct ID;
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
/**
|
||||
* \brief Abstraction to reference an asset, with necessary data for display & interaction.
|
||||
*
|
||||
* #AssetRepresentation is the data-structure to store information about a single asset. It doesn't
|
||||
* contain the asset itself, but information like the metadata and preview, as well as methods to
|
||||
* interact with them. Think of it like a view on an asset.
|
||||
*/
|
||||
class AssetRepresentation {
|
||||
friend class AssetLibrary;
|
||||
|
||||
/** Null if the asset represents a local ID, in which case the ID owns the metadata. */
|
||||
std::unique_ptr<AssetMetaData> metadata_ = nullptr;
|
||||
/** If this asset represents an ID in the current file, this references the ID directly. This
|
||||
* means the represented asset is a fully local, and editable entity. */
|
||||
ID *local_asset_id_ = nullptr; /* Non-owning. */
|
||||
|
||||
public:
|
||||
explicit AssetRepresentation(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);
|
||||
|
||||
AssetMetaData &get_metadata() const;
|
||||
/** Returns if this asset is stored inside this current file, and as such fully editable. */
|
||||
bool is_local_id() const;
|
||||
};
|
||||
|
||||
} // namespace blender::bke
|
@@ -75,6 +75,7 @@ set(SRC
|
||||
intern/asset_catalog_path.cc
|
||||
intern/asset_library.cc
|
||||
intern/asset_library_service.cc
|
||||
intern/asset_representation.cc
|
||||
intern/attribute.cc
|
||||
intern/attribute_access.cc
|
||||
intern/attribute_math.cc
|
||||
@@ -324,6 +325,7 @@ set(SRC
|
||||
BKE_asset_catalog_path.hh
|
||||
BKE_asset_library.h
|
||||
BKE_asset_library.hh
|
||||
BKE_asset_representation.hh
|
||||
BKE_attribute.h
|
||||
BKE_attribute.hh
|
||||
BKE_attribute_math.hh
|
||||
|
@@ -27,23 +27,33 @@ using namespace blender;
|
||||
|
||||
AssetMetaData *BKE_asset_metadata_create()
|
||||
{
|
||||
AssetMetaData *asset_data = (AssetMetaData *)MEM_callocN(sizeof(*asset_data), __func__);
|
||||
memcpy(asset_data, DNA_struct_default_get(AssetMetaData), sizeof(*asset_data));
|
||||
return asset_data;
|
||||
const AssetMetaData *default_metadata = DNA_struct_default_get(AssetMetaData);
|
||||
return MEM_new<AssetMetaData>(__func__, *default_metadata);
|
||||
}
|
||||
|
||||
void BKE_asset_metadata_free(AssetMetaData **asset_data)
|
||||
{
|
||||
if ((*asset_data)->properties) {
|
||||
IDP_FreeProperty((*asset_data)->properties);
|
||||
}
|
||||
MEM_SAFE_FREE((*asset_data)->author);
|
||||
MEM_SAFE_FREE((*asset_data)->description);
|
||||
BLI_freelistN(&(*asset_data)->tags);
|
||||
|
||||
(*asset_data)->~AssetMetaData();
|
||||
MEM_SAFE_FREE(*asset_data);
|
||||
}
|
||||
|
||||
AssetMetaData::~AssetMetaData()
|
||||
{
|
||||
if (properties) {
|
||||
IDP_FreeProperty(properties);
|
||||
}
|
||||
MEM_SAFE_FREE(author);
|
||||
MEM_SAFE_FREE(description);
|
||||
BLI_freelistN(&tags);
|
||||
}
|
||||
|
||||
std::unique_ptr<AssetMetaData> BKE_asset_metadata_move_to_unique_ptr(AssetMetaData *asset_data)
|
||||
{
|
||||
std::unique_ptr unique_asset_data = std::make_unique<AssetMetaData>(*asset_data);
|
||||
*asset_data = *DNA_struct_default_get(AssetMetaData);
|
||||
return unique_asset_data;
|
||||
}
|
||||
|
||||
static AssetTag *asset_metadata_tag_add(AssetMetaData *asset_data, const char *const name)
|
||||
{
|
||||
AssetTag *tag = (AssetTag *)MEM_callocN(sizeof(*tag), __func__);
|
||||
|
@@ -508,14 +508,13 @@ CatalogFilePath AssetCatalogService::find_suitable_cdf_path_for_writing(
|
||||
"catalog definition file should be put");
|
||||
|
||||
/* Ask the asset library API for an appropriate location. */
|
||||
char suitable_root_path[PATH_MAX];
|
||||
const bool asset_lib_root_found = BKE_asset_library_find_suitable_root_path_from_path(
|
||||
blend_file_path.c_str(), suitable_root_path);
|
||||
if (asset_lib_root_found) {
|
||||
const std::string suitable_root_path = BKE_asset_library_find_suitable_root_path_from_path(
|
||||
blend_file_path);
|
||||
if (!suitable_root_path.empty()) {
|
||||
char asset_lib_cdf_path[PATH_MAX];
|
||||
BLI_path_join(asset_lib_cdf_path,
|
||||
sizeof(asset_lib_cdf_path),
|
||||
suitable_root_path,
|
||||
suitable_root_path.c_str(),
|
||||
DEFAULT_CATALOG_FILENAME.c_str());
|
||||
return asset_lib_cdf_path;
|
||||
}
|
||||
|
@@ -7,11 +7,14 @@
|
||||
#include <memory>
|
||||
|
||||
#include "BKE_asset_library.hh"
|
||||
#include "BKE_asset_representation.hh"
|
||||
#include "BKE_lib_remap.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_preferences.h"
|
||||
|
||||
#include "BLI_fileops.h"
|
||||
#include "BLI_path_util.h"
|
||||
#include "BLI_set.hh"
|
||||
|
||||
#include "DNA_asset_types.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
@@ -50,22 +53,22 @@ bool BKE_asset_library_has_any_unsaved_catalogs()
|
||||
return service->has_any_unsaved_catalogs();
|
||||
}
|
||||
|
||||
bool BKE_asset_library_find_suitable_root_path_from_path(const char *input_path,
|
||||
char *r_library_path)
|
||||
std::string BKE_asset_library_find_suitable_root_path_from_path(
|
||||
const blender::StringRefNull input_path)
|
||||
{
|
||||
if (bUserAssetLibrary *preferences_lib = BKE_preferences_asset_library_containing_path(
|
||||
&U, input_path)) {
|
||||
BLI_strncpy(r_library_path, preferences_lib->path, FILE_MAXDIR);
|
||||
return true;
|
||||
&U, input_path.c_str())) {
|
||||
return preferences_lib->path;
|
||||
}
|
||||
|
||||
BLI_split_dir_part(input_path, r_library_path, FILE_MAXDIR);
|
||||
return r_library_path[0] != '\0';
|
||||
char buffer[FILE_MAXDIR];
|
||||
BLI_split_dir_part(input_path.c_str(), buffer, FILE_MAXDIR);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
bool BKE_asset_library_find_suitable_root_path_from_main(const Main *bmain, char *r_library_path)
|
||||
std::string BKE_asset_library_find_suitable_root_path_from_main(const Main *bmain)
|
||||
{
|
||||
return BKE_asset_library_find_suitable_root_path_from_path(bmain->filepath, r_library_path);
|
||||
return BKE_asset_library_find_suitable_root_path_from_path(bmain->filepath);
|
||||
}
|
||||
|
||||
blender::bke::AssetCatalogService *BKE_asset_library_get_catalog_service(
|
||||
@@ -98,6 +101,13 @@ void BKE_asset_library_refresh_catalog_simplename(struct AssetLibrary *asset_lib
|
||||
lib->refresh_catalog_simplename(asset_data);
|
||||
}
|
||||
|
||||
void BKE_asset_library_remap_ids(IDRemapper *mappings)
|
||||
{
|
||||
blender::bke::AssetLibraryService *service = blender::bke::AssetLibraryService::get();
|
||||
service->foreach_loaded_asset_library(
|
||||
[mappings](blender::bke::AssetLibrary &library) { library.remap_ids(*mappings); });
|
||||
}
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
AssetLibrary::AssetLibrary() : catalog_service(std::make_unique<AssetCatalogService>())
|
||||
@@ -111,7 +121,7 @@ AssetLibrary::~AssetLibrary()
|
||||
}
|
||||
}
|
||||
|
||||
void AssetLibrary::load(StringRefNull library_root_directory)
|
||||
void AssetLibrary::load_catalogs(StringRefNull library_root_directory)
|
||||
{
|
||||
auto catalog_service = std::make_unique<AssetCatalogService>(library_root_directory);
|
||||
catalog_service->load_from_disk();
|
||||
@@ -123,6 +133,43 @@ void AssetLibrary::refresh()
|
||||
this->catalog_service->reload_catalogs();
|
||||
}
|
||||
|
||||
AssetRepresentation &AssetLibrary::add_external_asset(std::unique_ptr<AssetMetaData> metadata)
|
||||
{
|
||||
asset_storage_.append(std::make_unique<AssetRepresentation>(std::move(metadata)));
|
||||
return *asset_storage_.last();
|
||||
}
|
||||
|
||||
AssetRepresentation &AssetLibrary::add_local_id_asset(ID &id)
|
||||
{
|
||||
asset_storage_.append(std::make_unique<AssetRepresentation>(id));
|
||||
return *asset_storage_.last();
|
||||
}
|
||||
|
||||
std::optional<int> AssetLibrary::find_asset_index(const AssetRepresentation &asset)
|
||||
{
|
||||
int index = 0;
|
||||
/* Find index of asset. */
|
||||
for (auto &asset_uptr : asset_storage_) {
|
||||
if (&asset == asset_uptr.get()) {
|
||||
return index;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
bool AssetLibrary::remove_asset(AssetRepresentation &asset)
|
||||
{
|
||||
std::optional<int> asset_index = find_asset_index(asset);
|
||||
if (!asset_index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
asset_storage_.remove_and_reorder(*asset_index);
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
void asset_library_on_save_post(struct Main *main,
|
||||
struct PointerRNA **pointers,
|
||||
@@ -166,6 +213,28 @@ void AssetLibrary::on_blend_save_post(struct Main *main,
|
||||
}
|
||||
}
|
||||
|
||||
void AssetLibrary::remap_ids(IDRemapper &mappings)
|
||||
{
|
||||
Set<AssetRepresentation *> removed_id_assets;
|
||||
|
||||
for (auto &asset_uptr : asset_storage_) {
|
||||
if (!asset_uptr->is_local_id()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IDRemapperApplyResult result = BKE_id_remapper_apply(
|
||||
&mappings, &asset_uptr->local_asset_id_, ID_REMAP_APPLY_DEFAULT);
|
||||
if (result == ID_REMAP_RESULT_SOURCE_UNASSIGNED) {
|
||||
removed_id_assets.add(asset_uptr.get());
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove the assets from storage. */
|
||||
for (AssetRepresentation *asset : removed_id_assets) {
|
||||
remove_asset(*asset);
|
||||
}
|
||||
}
|
||||
|
||||
void AssetLibrary::refresh_catalog_simplename(struct AssetMetaData *asset_data)
|
||||
{
|
||||
if (BLI_uuid_is_nil(asset_data->catalog_id)) {
|
||||
|
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "asset_library_service.hh"
|
||||
|
||||
#include "BKE_asset_library.hh"
|
||||
#include "BKE_blender.h"
|
||||
#include "BKE_preferences.h"
|
||||
|
||||
@@ -47,15 +48,10 @@ AssetLibrary *AssetLibraryService::get_asset_library(
|
||||
{
|
||||
if (library_reference.type == ASSET_LIBRARY_LOCAL) {
|
||||
/* For the "Current File" library we get the asset library root path based on main. */
|
||||
char root_path[FILE_MAX];
|
||||
if (bmain) {
|
||||
BKE_asset_library_find_suitable_root_path_from_main(bmain, root_path);
|
||||
}
|
||||
else {
|
||||
root_path[0] = '\0';
|
||||
}
|
||||
std::string root_path = bmain ? BKE_asset_library_find_suitable_root_path_from_main(bmain) :
|
||||
"";
|
||||
|
||||
if (root_path[0] == '\0') {
|
||||
if (root_path.empty()) {
|
||||
/* File wasn't saved yet. */
|
||||
return get_asset_library_current_file();
|
||||
}
|
||||
@@ -104,7 +100,7 @@ AssetLibrary *AssetLibraryService::get_asset_library_on_disk(StringRefNull top_l
|
||||
AssetLibrary *lib = lib_uptr.get();
|
||||
|
||||
lib->on_blend_save_handler_register();
|
||||
lib->load(top_dir_trailing_slash);
|
||||
lib->load_catalogs(top_dir_trailing_slash);
|
||||
|
||||
on_disk_libraries_.add_new(top_dir_trailing_slash, std::move(lib_uptr));
|
||||
CLOG_INFO(&LOG, 2, "get \"%s\" (loaded)", top_dir_trailing_slash.c_str());
|
||||
@@ -180,4 +176,15 @@ bool AssetLibraryService::has_any_unsaved_catalogs() const
|
||||
return false;
|
||||
}
|
||||
|
||||
void AssetLibraryService::foreach_loaded_asset_library(FunctionRef<void(AssetLibrary &)> fn) const
|
||||
{
|
||||
if (current_file_library_) {
|
||||
fn(*current_file_library_);
|
||||
}
|
||||
|
||||
for (const auto &asset_lib_uptr : on_disk_libraries_.values()) {
|
||||
fn(*asset_lib_uptr);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::bke
|
||||
|
@@ -12,10 +12,13 @@
|
||||
|
||||
#include "BKE_asset_library.hh"
|
||||
|
||||
#include "BLI_function_ref.hh"
|
||||
#include "BLI_map.hh"
|
||||
|
||||
#include <memory>
|
||||
|
||||
struct AssetLibraryReference;
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
/**
|
||||
@@ -33,6 +36,8 @@ namespace blender::bke {
|
||||
*/
|
||||
class AssetLibraryService {
|
||||
public:
|
||||
/** TODO use shared pointer to usage-count libraries? Avoids keeping unused libraries in memory.
|
||||
*/
|
||||
using AssetLibraryPtr = std::unique_ptr<AssetLibrary>;
|
||||
|
||||
AssetLibraryService() = default;
|
||||
@@ -58,11 +63,16 @@ class AssetLibraryService {
|
||||
/** Returns whether there are any known asset libraries with unsaved catalog edits. */
|
||||
bool has_any_unsaved_catalogs() const;
|
||||
|
||||
void foreach_loaded_asset_library(FunctionRef<void(AssetLibrary &)> fn) const;
|
||||
|
||||
protected:
|
||||
static std::unique_ptr<AssetLibraryService> instance_;
|
||||
|
||||
/* Mapping absolute path of the library's top-level directory to the AssetLibrary instance. */
|
||||
Map<std::string, AssetLibraryPtr> on_disk_libraries_;
|
||||
/** Library without a known path, i.e. the "Current File" library if the file isn't saved yet. If
|
||||
* the file was saved, a valid path for the library can be determined and #on_disk_libraries_
|
||||
* above should be used. */
|
||||
AssetLibraryPtr current_file_library_;
|
||||
|
||||
/* Handlers for managing the life cycle of the AssetLibraryService instance. */
|
||||
|
@@ -8,6 +8,9 @@
|
||||
|
||||
#include "BKE_appdir.h"
|
||||
#include "BKE_callbacks.h"
|
||||
#include "BKE_main.h"
|
||||
|
||||
#include "DNA_asset_types.h"
|
||||
|
||||
#include "CLG_log.h"
|
||||
|
||||
@@ -102,6 +105,25 @@ TEST_F(AssetLibraryServiceTest, library_pointers)
|
||||
* cannot be reliably tested by just pointer comparison, though. */
|
||||
}
|
||||
|
||||
TEST_F(AssetLibraryServiceTest, library_from_reference)
|
||||
{
|
||||
AssetLibraryService *service = AssetLibraryService::get();
|
||||
AssetLibrary *const lib = service->get_asset_library_on_disk(asset_library_root_);
|
||||
AssetLibrary *const curfile_lib = service->get_asset_library_current_file();
|
||||
|
||||
AssetLibraryReference ref{};
|
||||
ref.type = ASSET_LIBRARY_LOCAL;
|
||||
EXPECT_EQ(curfile_lib, service->get_asset_library(nullptr, ref))
|
||||
<< "Getting the local (current file) reference without a main saved on disk should return "
|
||||
"the current file library";
|
||||
|
||||
Main dummy_main{};
|
||||
BLI_strncpy(dummy_main.filepath, asset_library_root_.c_str(), sizeof(dummy_main.filepath));
|
||||
EXPECT_EQ(lib, service->get_asset_library(&dummy_main, ref))
|
||||
<< "Getting the local (current file) reference with a main saved on disk should return "
|
||||
"the an asset library for this directory";
|
||||
}
|
||||
|
||||
TEST_F(AssetLibraryServiceTest, library_path_trailing_slashes)
|
||||
{
|
||||
AssetLibraryService *service = AssetLibraryService::get();
|
||||
|
61
source/blender/blenkernel/intern/asset_representation.cc
Normal file
61
source/blender/blenkernel/intern/asset_representation.cc
Normal file
@@ -0,0 +1,61 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "DNA_ID.h"
|
||||
#include "DNA_asset_types.h"
|
||||
|
||||
#include "BKE_asset.h"
|
||||
#include "BKE_asset_representation.hh"
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
AssetRepresentation::AssetRepresentation(std::unique_ptr<AssetMetaData> metadata)
|
||||
: metadata_(std::move(metadata))
|
||||
{
|
||||
}
|
||||
|
||||
AssetRepresentation::AssetRepresentation(ID &id) : local_asset_id_(&id)
|
||||
{
|
||||
if (!id.asset_data) {
|
||||
throw std::invalid_argument("Passed ID is not an asset");
|
||||
}
|
||||
}
|
||||
|
||||
AssetMetaData &AssetRepresentation::get_metadata() const
|
||||
{
|
||||
return local_asset_id_ ? *local_asset_id_->asset_data : *metadata_;
|
||||
}
|
||||
|
||||
bool AssetRepresentation::is_local_id() const
|
||||
{
|
||||
return local_asset_id_ != nullptr;
|
||||
}
|
||||
|
||||
} // namespace blender::bke
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/** \name C-API
|
||||
* \{ */
|
||||
|
||||
using namespace blender;
|
||||
|
||||
AssetMetaData *BKE_asset_representation_metadata_get(const AssetRepresentation *asset_handle)
|
||||
{
|
||||
const bke::AssetRepresentation *asset = reinterpret_cast<const bke::AssetRepresentation *>(
|
||||
asset_handle);
|
||||
return &asset->get_metadata();
|
||||
}
|
||||
|
||||
bool BKE_asset_representation_is_local_id(const AssetRepresentation *asset_handle)
|
||||
{
|
||||
const bke::AssetRepresentation *asset = reinterpret_cast<const bke::AssetRepresentation *>(
|
||||
asset_handle);
|
||||
return asset->is_local_id();
|
||||
}
|
||||
|
||||
/** \} */
|
@@ -1495,7 +1495,7 @@ AssetHandle CTX_wm_asset_handle(const bContext *C, bool *r_is_valid)
|
||||
* require returning a non-owning pointer, which we don't have in the Asset Browser (yet). */
|
||||
FileDirEntry *file =
|
||||
(FileDirEntry *)CTX_data_pointer_get_type(C, "active_file", &RNA_FileSelectEntry).data;
|
||||
if (file && file->asset_data) {
|
||||
if (file && file->asset) {
|
||||
*r_is_valid = true;
|
||||
return (AssetHandle){.file_data = file};
|
||||
}
|
||||
|
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "BKE_anim_data.h"
|
||||
#include "BKE_asset.h"
|
||||
#include "BKE_asset_library.h"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_idtype.h"
|
||||
#include "BKE_key.h"
|
||||
@@ -137,16 +138,16 @@ void BKE_id_free_ex(Main *bmain, void *idv, int flag, const bool use_flag_from_i
|
||||
BKE_main_lock(bmain);
|
||||
}
|
||||
|
||||
struct IDRemapper *remapper = BKE_id_remapper_create();
|
||||
BKE_id_remapper_add(remapper, id, NULL);
|
||||
|
||||
if ((flag & LIB_ID_FREE_NO_UI_USER) == 0) {
|
||||
if (free_notifier_reference_cb) {
|
||||
free_notifier_reference_cb(id);
|
||||
}
|
||||
|
||||
if (remap_editor_id_reference_cb) {
|
||||
struct IDRemapper *remapper = BKE_id_remapper_create();
|
||||
BKE_id_remapper_add(remapper, id, NULL);
|
||||
remap_editor_id_reference_cb(remapper);
|
||||
BKE_id_remapper_free(remapper);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,6 +159,9 @@ void BKE_id_free_ex(Main *bmain, void *idv, int flag, const bool use_flag_from_i
|
||||
}
|
||||
}
|
||||
|
||||
BKE_asset_library_remap_ids(remapper);
|
||||
BKE_id_remapper_free(remapper);
|
||||
|
||||
BKE_libblock_free_data(id, (flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0);
|
||||
|
||||
if ((flag & LIB_ID_FREE_NO_MAIN) == 0) {
|
||||
|
@@ -8,6 +8,9 @@
|
||||
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "BKE_asset.h"
|
||||
#include "BKE_asset_representation.hh"
|
||||
|
||||
#include "BLO_readfile.h"
|
||||
|
||||
#include "ED_asset_handle.h"
|
||||
@@ -20,9 +23,9 @@ const char *ED_asset_handle_get_name(const AssetHandle *asset)
|
||||
return asset->file_data->name;
|
||||
}
|
||||
|
||||
AssetMetaData *ED_asset_handle_get_metadata(const AssetHandle *asset)
|
||||
AssetMetaData *ED_asset_handle_get_metadata(const AssetHandle *asset_handle)
|
||||
{
|
||||
return asset->file_data->asset_data;
|
||||
return BKE_asset_representation_metadata_get(asset_handle->file_data->asset);
|
||||
}
|
||||
|
||||
ID *ED_asset_handle_get_local_id(const AssetHandle *asset)
|
||||
|
@@ -72,7 +72,7 @@ AssetTempIDConsumer *ED_asset_temp_id_consumer_create(const AssetHandle *handle)
|
||||
if (!handle) {
|
||||
return nullptr;
|
||||
}
|
||||
BLI_assert(handle->file_data->asset_data != nullptr);
|
||||
BLI_assert(handle->file_data->asset != nullptr);
|
||||
return reinterpret_cast<AssetTempIDConsumer *>(
|
||||
MEM_new<AssetTemporaryIDConsumer>(__func__, *handle));
|
||||
}
|
||||
|
@@ -1789,7 +1789,6 @@ void UI_but_drag_attach_image(uiBut *but, struct ImBuf *imb, float scale);
|
||||
void UI_but_drag_set_asset(uiBut *but,
|
||||
const struct AssetHandle *asset,
|
||||
const char *path,
|
||||
struct AssetMetaData *metadata,
|
||||
int import_type, /* eFileAssetImportType */
|
||||
int icon,
|
||||
struct ImBuf *imb,
|
||||
|
@@ -27,15 +27,14 @@ void UI_but_drag_attach_image(uiBut *but, struct ImBuf *imb, const float scale)
|
||||
}
|
||||
|
||||
void UI_but_drag_set_asset(uiBut *but,
|
||||
const AssetHandle *asset,
|
||||
const AssetHandle *asset_handle,
|
||||
const char *path,
|
||||
struct AssetMetaData *metadata,
|
||||
int import_type,
|
||||
int icon,
|
||||
struct ImBuf *imb,
|
||||
float scale)
|
||||
{
|
||||
wmDragAsset *asset_drag = WM_drag_create_asset_data(asset, metadata, path, import_type);
|
||||
wmDragAsset *asset_drag = WM_drag_create_asset_data(asset_handle, path, import_type);
|
||||
|
||||
/* FIXME: This is temporary evil solution to get scene/view-layer/etc in the copy callback of the
|
||||
* #wmDropBox.
|
||||
|
@@ -57,7 +57,6 @@ static void asset_view_item_but_drag_set(uiBut *but,
|
||||
UI_but_drag_set_asset(but,
|
||||
asset_handle,
|
||||
BLI_strdup(blend_path),
|
||||
ED_asset_handle_get_metadata(asset_handle),
|
||||
FILE_ASSET_IMPORT_APPEND,
|
||||
ED_asset_handle_get_preview_icon_id(asset_handle),
|
||||
imbuf,
|
||||
|
@@ -708,12 +708,11 @@ bool file_set_asset_catalog_filter_settings(
|
||||
|
||||
void file_ensure_updated_catalog_filter_data(
|
||||
FileAssetCatalogFilterSettingsHandle *filter_settings_handle,
|
||||
const ::AssetLibrary *asset_library)
|
||||
const bke::AssetLibrary *asset_library)
|
||||
{
|
||||
AssetCatalogFilterSettings *filter_settings = reinterpret_cast<AssetCatalogFilterSettings *>(
|
||||
filter_settings_handle);
|
||||
const AssetCatalogService *catalog_service = BKE_asset_library_get_catalog_service(
|
||||
asset_library);
|
||||
const AssetCatalogService *catalog_service = asset_library->catalog_service.get();
|
||||
|
||||
if (filter_settings->asset_catalog_visibility != FILE_SHOW_ASSETS_ALL_CATALOGS) {
|
||||
filter_settings->catalog_filter = std::make_unique<AssetCatalogFilter>(
|
||||
|
@@ -171,7 +171,6 @@ static void file_draw_icon(const SpaceFile *sfile,
|
||||
UI_but_drag_set_asset(but,
|
||||
&(AssetHandle){.file_data = file},
|
||||
BLI_strdup(blend_path),
|
||||
file->asset_data,
|
||||
asset_params->import_type,
|
||||
icon,
|
||||
preview_image,
|
||||
@@ -565,7 +564,6 @@ static void file_draw_preview(const SpaceFile *sfile,
|
||||
UI_but_drag_set_asset(but,
|
||||
&(AssetHandle){.file_data = file},
|
||||
BLI_strdup(blend_path),
|
||||
file->asset_data,
|
||||
asset_params->import_type,
|
||||
icon,
|
||||
imb,
|
||||
|
@@ -67,8 +67,9 @@ void ED_file_indexer_entries_extend_from_datablock_infos(
|
||||
}
|
||||
}
|
||||
|
||||
static void ED_file_indexer_entry_free(void *indexer_entry)
|
||||
static void ED_file_indexer_entry_free(void *indexer_entry_ptr)
|
||||
{
|
||||
FileIndexerEntry *indexer_entry = static_cast<FileIndexerEntry *>(indexer_entry_ptr);
|
||||
MEM_freeN(indexer_entry);
|
||||
}
|
||||
|
||||
|
@@ -218,6 +218,17 @@ void file_path_to_ui_path(const char *path, char *r_pathi, int max_size);
|
||||
/* C-handle for #ed::asset_browser::AssetCatalogFilterSettings. */
|
||||
typedef struct FileAssetCatalogFilterSettingsHandle FileAssetCatalogFilterSettingsHandle;
|
||||
|
||||
void file_create_asset_catalog_tree_view_in_layout(struct AssetLibrary *asset_library,
|
||||
struct uiLayout *layout,
|
||||
SpaceFile *space_file,
|
||||
FileAssetSelectParams *params);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace blender::bke {
|
||||
struct AssetLibrary;
|
||||
}
|
||||
|
||||
FileAssetCatalogFilterSettingsHandle *file_create_asset_catalog_filter_settings(void);
|
||||
void file_delete_asset_catalog_filter_settings(
|
||||
FileAssetCatalogFilterSettingsHandle **filter_settings_handle);
|
||||
@@ -231,15 +242,12 @@ bool file_set_asset_catalog_filter_settings(
|
||||
bUUID catalog_id);
|
||||
void file_ensure_updated_catalog_filter_data(
|
||||
FileAssetCatalogFilterSettingsHandle *filter_settings_handle,
|
||||
const struct AssetLibrary *asset_library);
|
||||
const blender::bke::AssetLibrary *asset_library);
|
||||
bool file_is_asset_visible_in_catalog_filter_settings(
|
||||
const FileAssetCatalogFilterSettingsHandle *filter_settings_handle,
|
||||
const AssetMetaData *asset_data);
|
||||
|
||||
void file_create_asset_catalog_tree_view_in_layout(struct AssetLibrary *asset_library,
|
||||
struct uiLayout *layout,
|
||||
struct SpaceFile *space_file,
|
||||
struct FileAssetSelectParams *params);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@@ -43,6 +43,8 @@
|
||||
|
||||
#include "BKE_asset.h"
|
||||
#include "BKE_asset_library.h"
|
||||
#include "BKE_asset_library.hh"
|
||||
#include "BKE_asset_representation.hh"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_icons.h"
|
||||
@@ -78,6 +80,8 @@
|
||||
#include "file_intern.h"
|
||||
#include "filelist.h"
|
||||
|
||||
using namespace blender;
|
||||
|
||||
#define FILEDIR_NBR_ENTRIES_UNSET -1
|
||||
|
||||
/* ------------------FILELIST------------------------ */
|
||||
@@ -112,9 +116,8 @@ struct FileListInternEntry {
|
||||
PreviewImage *preview_image;
|
||||
} local_data;
|
||||
|
||||
/** When the file represents an asset read from another file, it is stored here.
|
||||
* Owning pointer. */
|
||||
AssetMetaData *imported_asset_data;
|
||||
/* References an asset in the asset library storage. */
|
||||
bke::AssetRepresentation *asset; /* Non-owning. */
|
||||
|
||||
/* See #FILE_ENTRY_BLENDERLIB_NO_PREVIEW. */
|
||||
bool blenderlib_has_no_preview;
|
||||
@@ -210,7 +213,7 @@ struct FileList {
|
||||
eFileSelectType type;
|
||||
/* The library this list was created for. Stored here so we know when to re-read. */
|
||||
AssetLibraryReference *asset_library_ref;
|
||||
AssetLibrary *asset_library; /* Non-owning pointer. */
|
||||
bke::AssetLibrary *asset_library; /* Non-owning pointer. */
|
||||
|
||||
short flags;
|
||||
|
||||
@@ -776,8 +779,10 @@ static bool is_filtered_id_file_type(const FileListInternEntry *file,
|
||||
*/
|
||||
static AssetMetaData *filelist_file_internal_get_asset_data(const FileListInternEntry *file)
|
||||
{
|
||||
const ID *local_id = file->local_data.id;
|
||||
return local_id ? local_id->asset_data : file->imported_asset_data;
|
||||
if (!file->asset) {
|
||||
return nullptr;
|
||||
}
|
||||
return &file->asset->get_metadata();
|
||||
}
|
||||
|
||||
static void prepare_filter_asset_library(const FileList *filelist, FileListFilter *filter)
|
||||
@@ -1016,7 +1021,7 @@ void filelist_setindexer(FileList *filelist, const FileIndexerType *indexer)
|
||||
void filelist_set_asset_catalog_filter_options(
|
||||
FileList *filelist,
|
||||
eFileSel_Params_AssetCatalogVisibility catalog_visibility,
|
||||
const bUUID *catalog_id)
|
||||
const ::bUUID *catalog_id)
|
||||
{
|
||||
if (!filelist->filter_data.asset_catalog_filter) {
|
||||
/* There's no filter data yet. */
|
||||
@@ -1399,8 +1404,13 @@ static void filelist_direntryarr_free(FileDirEntryArr *array)
|
||||
array->entries_filtered_num = FILEDIR_NBR_ENTRIES_UNSET;
|
||||
}
|
||||
|
||||
static void filelist_intern_entry_free(FileListInternEntry *entry)
|
||||
static void filelist_intern_entry_free(FileList *filelist, FileListInternEntry *entry)
|
||||
{
|
||||
if (entry->asset) {
|
||||
BLI_assert(filelist->asset_library);
|
||||
filelist->asset_library->remove_asset(*entry->asset);
|
||||
}
|
||||
|
||||
if (entry->relpath) {
|
||||
MEM_freeN(entry->relpath);
|
||||
}
|
||||
@@ -1410,17 +1420,14 @@ static void filelist_intern_entry_free(FileListInternEntry *entry)
|
||||
if (entry->name && entry->free_name) {
|
||||
MEM_freeN(entry->name);
|
||||
}
|
||||
/* If we own the asset-data (it was generated from external file data), free it. */
|
||||
if (entry->imported_asset_data) {
|
||||
BKE_asset_metadata_free(&entry->imported_asset_data);
|
||||
}
|
||||
MEM_freeN(entry);
|
||||
}
|
||||
|
||||
static void filelist_intern_free(FileListIntern *filelist_intern)
|
||||
static void filelist_intern_free(FileList *filelist)
|
||||
{
|
||||
FileListIntern *filelist_intern = &filelist->filelist_intern;
|
||||
LISTBASE_FOREACH_MUTABLE (FileListInternEntry *, entry, &filelist_intern->entries) {
|
||||
filelist_intern_entry_free(entry);
|
||||
filelist_intern_entry_free(filelist, entry);
|
||||
}
|
||||
BLI_listbase_clear(&filelist_intern->entries);
|
||||
|
||||
@@ -1430,8 +1437,9 @@ static void filelist_intern_free(FileListIntern *filelist_intern)
|
||||
/**
|
||||
* \return the number of main files removed.
|
||||
*/
|
||||
static int filelist_intern_free_main_files(FileListIntern *filelist_intern)
|
||||
static int filelist_intern_free_main_files(FileList *filelist)
|
||||
{
|
||||
FileListIntern *filelist_intern = &filelist->filelist_intern;
|
||||
int removed_counter = 0;
|
||||
LISTBASE_FOREACH_MUTABLE (FileListInternEntry *, entry, &filelist_intern->entries) {
|
||||
if (!filelist_intern_entry_is_main_file(entry)) {
|
||||
@@ -1439,7 +1447,7 @@ static int filelist_intern_free_main_files(FileListIntern *filelist_intern)
|
||||
}
|
||||
|
||||
BLI_remlink(&filelist_intern->entries, entry);
|
||||
filelist_intern_entry_free(entry);
|
||||
filelist_intern_entry_free(filelist, entry);
|
||||
removed_counter++;
|
||||
}
|
||||
|
||||
@@ -1794,7 +1802,7 @@ void filelist_clear_ex(struct FileList *filelist,
|
||||
filelist_cache_clear(&filelist->filelist_cache, filelist->filelist_cache.size);
|
||||
}
|
||||
|
||||
filelist_intern_free(&filelist->filelist_intern);
|
||||
filelist_intern_free(filelist);
|
||||
|
||||
filelist_direntryarr_free(&filelist->filelist);
|
||||
|
||||
@@ -1822,7 +1830,7 @@ static void filelist_clear_main_files(FileList *filelist,
|
||||
filelist_cache_clear(&filelist->filelist_cache, filelist->filelist_cache.size);
|
||||
}
|
||||
|
||||
const int removed_files = filelist_intern_free_main_files(&filelist->filelist_intern);
|
||||
const int removed_files = filelist_intern_free_main_files(filelist);
|
||||
|
||||
filelist->filelist.entries_num -= removed_files;
|
||||
filelist->filelist.entries_filtered_num = FILEDIR_NBR_ENTRIES_UNSET;
|
||||
@@ -1881,7 +1889,7 @@ void filelist_free(struct FileList *filelist)
|
||||
|
||||
AssetLibrary *filelist_asset_library(FileList *filelist)
|
||||
{
|
||||
return filelist->asset_library;
|
||||
return reinterpret_cast<::AssetLibrary *>(filelist->asset_library);
|
||||
}
|
||||
|
||||
void filelist_freelib(struct FileList *filelist)
|
||||
@@ -2042,10 +2050,7 @@ static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int in
|
||||
ret->redirection_path = BLI_strdup(entry->redirection_path);
|
||||
}
|
||||
ret->id = entry->local_data.id;
|
||||
ret->asset_data = entry->imported_asset_data ? entry->imported_asset_data : nullptr;
|
||||
if (ret->id && (ret->asset_data == nullptr)) {
|
||||
ret->asset_data = ret->id->asset_data;
|
||||
}
|
||||
ret->asset = reinterpret_cast<::AssetRepresentation *>(entry->asset);
|
||||
/* For some file types the preview is already available. */
|
||||
if (entry->local_data.preview_image &&
|
||||
BKE_previewimg_is_finished(entry->local_data.preview_image, ICON_SIZE_PREVIEW)) {
|
||||
@@ -2996,8 +3001,13 @@ static FileListInternEntry *filelist_readjob_list_lib_group_create(const int idc
|
||||
return entry;
|
||||
}
|
||||
|
||||
static void filelist_readjob_list_lib_add_datablock(ListBase *entries,
|
||||
const BLODataBlockInfo *datablock_info,
|
||||
/**
|
||||
* \warning: This "steals" the asset metadata from \a datablock_info. Not great design but fixing
|
||||
* this requires redesigning things on the caller side for proper ownership management.
|
||||
*/
|
||||
static void filelist_readjob_list_lib_add_datablock(FileList *filelist,
|
||||
ListBase *entries,
|
||||
BLODataBlockInfo *datablock_info,
|
||||
const bool prefix_relpath_with_group_name,
|
||||
const int idcode,
|
||||
const char *group_name)
|
||||
@@ -3010,21 +3020,28 @@ static void filelist_readjob_list_lib_add_datablock(ListBase *entries,
|
||||
entry->relpath = BLI_strdup(datablock_info->name);
|
||||
}
|
||||
entry->typeflag |= FILE_TYPE_BLENDERLIB;
|
||||
|
||||
if (datablock_info) {
|
||||
entry->blenderlib_has_no_preview = datablock_info->no_preview_found;
|
||||
|
||||
if (datablock_info->asset_data) {
|
||||
entry->typeflag |= FILE_TYPE_ASSET;
|
||||
/* Moves ownership! */
|
||||
entry->imported_asset_data = datablock_info->asset_data;
|
||||
|
||||
if (filelist->asset_library) {
|
||||
/** XXX Moving out the asset metadata like this isn't great. */
|
||||
std::unique_ptr metadata = BKE_asset_metadata_move_to_unique_ptr(
|
||||
datablock_info->asset_data);
|
||||
BKE_asset_metadata_free(&datablock_info->asset_data);
|
||||
|
||||
entry->asset = &filelist->asset_library->add_external_asset(std::move(metadata));
|
||||
}
|
||||
}
|
||||
}
|
||||
entry->blentype = idcode;
|
||||
BLI_addtail(entries, entry);
|
||||
}
|
||||
|
||||
static void filelist_readjob_list_lib_add_datablocks(ListBase *entries,
|
||||
static void filelist_readjob_list_lib_add_datablocks(FileList *filelist,
|
||||
ListBase *entries,
|
||||
LinkNode *datablock_infos,
|
||||
const bool prefix_relpath_with_group_name,
|
||||
const int idcode,
|
||||
@@ -3033,19 +3050,21 @@ static void filelist_readjob_list_lib_add_datablocks(ListBase *entries,
|
||||
for (LinkNode *ln = datablock_infos; ln; ln = ln->next) {
|
||||
struct BLODataBlockInfo *datablock_info = static_cast<BLODataBlockInfo *>(ln->link);
|
||||
filelist_readjob_list_lib_add_datablock(
|
||||
entries, datablock_info, prefix_relpath_with_group_name, idcode, group_name);
|
||||
filelist, entries, datablock_info, prefix_relpath_with_group_name, idcode, group_name);
|
||||
}
|
||||
}
|
||||
|
||||
static void filelist_readjob_list_lib_add_from_indexer_entries(
|
||||
FileList *filelist,
|
||||
ListBase *entries,
|
||||
const FileIndexerEntries *indexer_entries,
|
||||
const bool prefix_relpath_with_group_name)
|
||||
{
|
||||
for (const LinkNode *ln = indexer_entries->entries; ln; ln = ln->next) {
|
||||
const FileIndexerEntry *indexer_entry = (const FileIndexerEntry *)ln->link;
|
||||
FileIndexerEntry *indexer_entry = static_cast<FileIndexerEntry *>(ln->link);
|
||||
const char *group_name = BKE_idtype_idcode_to_name(indexer_entry->idcode);
|
||||
filelist_readjob_list_lib_add_datablock(entries,
|
||||
filelist_readjob_list_lib_add_datablock(filelist,
|
||||
entries,
|
||||
&indexer_entry->datablock_info,
|
||||
prefix_relpath_with_group_name,
|
||||
indexer_entry->idcode,
|
||||
@@ -3073,7 +3092,8 @@ typedef struct FileIndexer {
|
||||
void *user_data;
|
||||
} FileIndexer;
|
||||
|
||||
static int filelist_readjob_list_lib_populate_from_index(ListBase *entries,
|
||||
static int filelist_readjob_list_lib_populate_from_index(FileList *filelist,
|
||||
ListBase *entries,
|
||||
const ListLibOptions options,
|
||||
const int read_from_index,
|
||||
const FileIndexerEntries *indexer_entries)
|
||||
@@ -3085,11 +3105,12 @@ static int filelist_readjob_list_lib_populate_from_index(ListBase *entries,
|
||||
navigate_to_parent_len = 1;
|
||||
}
|
||||
|
||||
filelist_readjob_list_lib_add_from_indexer_entries(entries, indexer_entries, true);
|
||||
filelist_readjob_list_lib_add_from_indexer_entries(filelist, entries, indexer_entries, true);
|
||||
return read_from_index + navigate_to_parent_len;
|
||||
}
|
||||
|
||||
static int filelist_readjob_list_lib(const char *root,
|
||||
static int filelist_readjob_list_lib(FileList *filelist,
|
||||
const char *root,
|
||||
ListBase *entries,
|
||||
const ListLibOptions options,
|
||||
FileIndexer *indexer_runtime)
|
||||
@@ -3128,7 +3149,7 @@ static int filelist_readjob_list_lib(const char *root,
|
||||
dir, &indexer_entries, &read_from_index, indexer_runtime->user_data);
|
||||
if (indexer_result == FILE_INDEXER_ENTRIES_LOADED) {
|
||||
int entries_read = filelist_readjob_list_lib_populate_from_index(
|
||||
entries, options, read_from_index, &indexer_entries);
|
||||
filelist, entries, options, read_from_index, &indexer_entries);
|
||||
ED_file_indexer_entries_clear(&indexer_entries);
|
||||
return entries_read;
|
||||
}
|
||||
@@ -3158,7 +3179,8 @@ static int filelist_readjob_list_lib(const char *root,
|
||||
const int idcode = groupname_to_code(group);
|
||||
LinkNode *datablock_infos = BLO_blendhandle_get_datablock_info(
|
||||
libfiledata, idcode, options & LIST_LIB_ASSETS_ONLY, &datablock_len);
|
||||
filelist_readjob_list_lib_add_datablocks(entries, datablock_infos, false, idcode, group);
|
||||
filelist_readjob_list_lib_add_datablocks(
|
||||
filelist, entries, datablock_infos, false, idcode, group);
|
||||
BLI_linklist_freeN(datablock_infos);
|
||||
}
|
||||
else {
|
||||
@@ -3177,7 +3199,7 @@ static int filelist_readjob_list_lib(const char *root,
|
||||
LinkNode *group_datablock_infos = BLO_blendhandle_get_datablock_info(
|
||||
libfiledata, idcode, options & LIST_LIB_ASSETS_ONLY, &group_datablock_len);
|
||||
filelist_readjob_list_lib_add_datablocks(
|
||||
entries, group_datablock_infos, true, idcode, group_name);
|
||||
filelist, entries, group_datablock_infos, true, idcode, group_name);
|
||||
if (use_indexer) {
|
||||
ED_file_indexer_entries_extend_from_datablock_infos(
|
||||
&indexer_entries, group_datablock_infos, idcode);
|
||||
@@ -3529,7 +3551,7 @@ static void filelist_readjob_recursive_dir_add_items(const bool do_lib,
|
||||
list_lib_options |= LIST_LIB_ASSETS_ONLY;
|
||||
}
|
||||
entries_num = filelist_readjob_list_lib(
|
||||
subdir, &entries, list_lib_options, &indexer_runtime);
|
||||
filelist, subdir, &entries, list_lib_options, &indexer_runtime);
|
||||
if (entries_num > 0) {
|
||||
is_lib = true;
|
||||
}
|
||||
@@ -3626,20 +3648,6 @@ static void filelist_readjob_lib(FileListReadJob *job_params,
|
||||
filelist_readjob_do(true, job_params, stop, do_update, progress);
|
||||
}
|
||||
|
||||
static void filelist_asset_library_path(const FileListReadJob *job_params,
|
||||
char r_library_root_path[FILE_MAX])
|
||||
{
|
||||
if (job_params->filelist->type == FILE_MAIN_ASSET) {
|
||||
/* For the "Current File" library (#FILE_MAIN_ASSET) we get the asset library root path based
|
||||
* on main. */
|
||||
BKE_asset_library_find_suitable_root_path_from_main(job_params->current_main,
|
||||
r_library_root_path);
|
||||
}
|
||||
else {
|
||||
BLI_strncpy(r_library_root_path, job_params->tmp_filelist->filelist.root, FILE_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load asset library data, which currently means loading the asset catalogs for the library.
|
||||
*/
|
||||
@@ -3657,12 +3665,10 @@ static void filelist_readjob_load_asset_library_data(FileListReadJob *job_params
|
||||
return;
|
||||
}
|
||||
|
||||
char library_root_path[FILE_MAX];
|
||||
filelist_asset_library_path(job_params, library_root_path);
|
||||
|
||||
/* Load asset catalogs, into the temp filelist for thread-safety.
|
||||
* #filelist_readjob_endjob() will move it into the real filelist. */
|
||||
tmp_filelist->asset_library = BKE_asset_library_load(library_root_path);
|
||||
tmp_filelist->asset_library = BKE_asset_library_load(job_params->current_main,
|
||||
*job_params->filelist->asset_library_ref);
|
||||
*do_update = true;
|
||||
}
|
||||
|
||||
@@ -3699,6 +3705,9 @@ static void filelist_readjob_main_assets_add_items(FileListReadJob *job_params,
|
||||
entry->local_data.preview_image = BKE_asset_metadata_preview_get_from_id(id_iter->asset_data,
|
||||
id_iter);
|
||||
entry->local_data.id = id_iter;
|
||||
if (filelist->asset_library) {
|
||||
entry->asset = &filelist->asset_library->add_local_id_asset(*id_iter);
|
||||
}
|
||||
entries_num++;
|
||||
BLI_addtail(&tmp_entries, entry);
|
||||
}
|
||||
|
@@ -950,7 +950,7 @@ static int /*eContextResult*/ file_context(const bContext *C,
|
||||
for (int file_index = 0; file_index < num_files_filtered; file_index++) {
|
||||
if (filelist_entry_is_selected(sfile->files, file_index)) {
|
||||
FileDirEntry *entry = filelist_file(sfile->files, file_index);
|
||||
if (entry->asset_data) {
|
||||
if (entry->asset) {
|
||||
CTX_data_list_add(result, &screen->id, &RNA_FileSelectEntry, entry);
|
||||
}
|
||||
}
|
||||
|
@@ -42,6 +42,10 @@ typedef struct AssetFilterSettings {
|
||||
* more than that from the file. So pointers to other IDs or ID data are strictly forbidden.
|
||||
*/
|
||||
typedef struct AssetMetaData {
|
||||
#ifdef __cplusplus
|
||||
~AssetMetaData();
|
||||
#endif
|
||||
|
||||
/** Runtime type, to reference event callbacks. Only valid for local assets. */
|
||||
struct AssetTypeInfo *local_type_info;
|
||||
|
||||
|
@@ -1134,7 +1134,7 @@ typedef struct FileDirEntry {
|
||||
/** If this file represents an asset, its asset data is here. Note that we may show assets of
|
||||
* external files in which case this is set but not the id above.
|
||||
* Note comment for FileListInternEntry.local_data, the same applies here! */
|
||||
struct AssetMetaData *asset_data;
|
||||
struct AssetRepresentation *asset;
|
||||
|
||||
/* The icon_id for the preview image. */
|
||||
int preview_icon_id;
|
||||
|
@@ -540,6 +540,7 @@ static const EnumPropertyItem rna_enum_curve_display_handle_items[] = {
|
||||
# include "BLI_string.h"
|
||||
|
||||
# include "BKE_anim_data.h"
|
||||
# include "BKE_asset.h"
|
||||
# include "BKE_brush.h"
|
||||
# include "BKE_colortools.h"
|
||||
# include "BKE_context.h"
|
||||
@@ -2761,18 +2762,24 @@ static PointerRNA rna_FileBrowser_FileSelectEntry_asset_data_get(PointerRNA *ptr
|
||||
{
|
||||
const FileDirEntry *entry = ptr->data;
|
||||
|
||||
if (!entry->asset) {
|
||||
return PointerRNA_NULL;
|
||||
}
|
||||
|
||||
AssetMetaData *asset_data = BKE_asset_representation_metadata_get(entry->asset);
|
||||
|
||||
/* Note that the owning ID of the RNA pointer (`ptr->owner_id`) has to be set carefully:
|
||||
* Local IDs (`entry->id`) own their asset metadata themselves. Asset metadata from other blend
|
||||
* files are owned by the file browser (`entry`). Only if this is set correctly, we can tell from
|
||||
* the metadata RNA pointer if the metadata is stored locally and can thus be edited or not. */
|
||||
|
||||
if (entry->id) {
|
||||
if (BKE_asset_representation_is_local_id(entry->asset)) {
|
||||
PointerRNA id_ptr;
|
||||
RNA_id_pointer_create(entry->id, &id_ptr);
|
||||
return rna_pointer_inherit_refine(&id_ptr, &RNA_AssetMetaData, entry->asset_data);
|
||||
return rna_pointer_inherit_refine(&id_ptr, &RNA_AssetMetaData, asset_data);
|
||||
}
|
||||
|
||||
return rna_pointer_inherit_refine(ptr, &RNA_AssetMetaData, entry->asset_data);
|
||||
return rna_pointer_inherit_refine(ptr, &RNA_AssetMetaData, asset_data);
|
||||
}
|
||||
|
||||
static int rna_FileBrowser_FileSelectEntry_name_editable(PointerRNA *ptr, const char **r_info)
|
||||
@@ -2782,7 +2789,7 @@ static int rna_FileBrowser_FileSelectEntry_name_editable(PointerRNA *ptr, const
|
||||
/* This actually always returns 0 (the name is never editable) but we want to get a disabled
|
||||
* message returned to `r_info` in some cases. */
|
||||
|
||||
if (entry->asset_data) {
|
||||
if (entry->asset) {
|
||||
PointerRNA asset_data_ptr = rna_FileBrowser_FileSelectEntry_asset_data_get(ptr);
|
||||
/* Get disabled hint from asset metadata polling. */
|
||||
rna_AssetMetaData_editable(&asset_data_ptr, r_info);
|
||||
|
@@ -1302,7 +1302,6 @@ bool WM_drag_is_ID_type(const struct wmDrag *drag, int idcode);
|
||||
* \note Does not store \a asset in any way, so it's fine to pass a temporary.
|
||||
*/
|
||||
wmDragAsset *WM_drag_create_asset_data(const struct AssetHandle *asset,
|
||||
struct AssetMetaData *metadata,
|
||||
const char *path,
|
||||
int import_type);
|
||||
struct wmDragAsset *WM_drag_get_asset_data(const struct wmDrag *drag, int idcode);
|
||||
|
@@ -556,15 +556,12 @@ bool WM_drag_is_ID_type(const wmDrag *drag, int idcode)
|
||||
return WM_drag_get_local_ID(drag, idcode) || WM_drag_get_asset_data(drag, idcode);
|
||||
}
|
||||
|
||||
wmDragAsset *WM_drag_create_asset_data(const AssetHandle *asset,
|
||||
AssetMetaData *metadata,
|
||||
const char *path,
|
||||
int import_type)
|
||||
wmDragAsset *WM_drag_create_asset_data(const AssetHandle *asset, const char *path, int import_type)
|
||||
{
|
||||
wmDragAsset *asset_drag = MEM_new<wmDragAsset>(__func__);
|
||||
|
||||
BLI_strncpy(asset_drag->name, ED_asset_handle_get_name(asset), sizeof(asset_drag->name));
|
||||
asset_drag->metadata = metadata;
|
||||
asset_drag->metadata = ED_asset_handle_get_metadata(asset);
|
||||
asset_drag->path = path;
|
||||
asset_drag->id_type = ED_asset_handle_get_id_type(asset);
|
||||
asset_drag->import_type = import_type;
|
||||
@@ -733,12 +730,11 @@ void WM_drag_add_asset_list_item(
|
||||
drag_asset->asset_data.local_id = local_id;
|
||||
}
|
||||
else {
|
||||
AssetMetaData *metadata = ED_asset_handle_get_metadata(asset);
|
||||
char asset_blend_path[FILE_MAX_LIBEXTRA];
|
||||
ED_asset_handle_get_full_library_path(C, asset_library_ref, asset, asset_blend_path);
|
||||
drag_asset->is_external = true;
|
||||
drag_asset->asset_data.external_info = WM_drag_create_asset_data(
|
||||
asset, metadata, BLI_strdup(asset_blend_path), FILE_ASSET_IMPORT_APPEND);
|
||||
asset, BLI_strdup(asset_blend_path), FILE_ASSET_IMPORT_APPEND);
|
||||
}
|
||||
BLI_addtail(&drag->asset_items, drag_asset);
|
||||
}
|
||||
|
Reference in New Issue
Block a user