Compare commits

...

27 Commits

Author SHA1 Message Date
5c342b1000 Do ID remapping for asset libraries 2022-11-08 18:50:54 +01:00
b090c18ce4 Store ID in asset representation directly
This should make some things more convenient in future, since we can
directly access the ID if an asset represents one, without having to
look it up. But also, we need to do ID remapping either way, which
currently requires the ID pointer to identify the ID, not other ID data
(like the contained asset metadata).
2022-11-08 18:43:25 +01:00
2e1ba1ee20 Free asset representations when no longer displayed
The lifetime management of assets should still be improved, but
meanwhile each part of the UI loads its own representation of an asset
into memory. This is still done via the file browser backend, so this
should also remove the representations once it frees its file-list.
2022-11-08 16:33:32 +01:00
ffafde7bd6 Cleanup: Remove unncessary stoarage wrapper class 2022-11-08 16:26:49 +01:00
84cc68b68f Fix uninitialized variable use when dragging in assets 2022-11-08 15:14:07 +01:00
3fb8ad93ad Merge branch 'master' into temp-asset-representation 2022-11-08 12:42:20 +01:00
ab92154104 Fix T102242: Underline shortcut keys not working/appearing in sub-menu
Upon closer inspection, looks like `UI_BLOCK_NUMSELECT` was previously
set for all code paths and 99e5024e97 removed it from one.
2022-11-08 12:42:14 +01:00
e1c0e2f7f1 PyAPI: add invalid objects check for RNA struct keys()/values()/items() 2022-11-08 12:42:14 +01:00
49964a5abe Cleanup: format, remove commented code & unused variable 2022-11-08 12:42:14 +01:00
9ca80d7564 Workaround crash generating Python API documentation
Avoid accessing freed memory from dynamically allocated EnumPropertyItem
arrays. Rely on the memory being held by the iterator which isn't the
case when it was converted to a tuple.
2022-11-08 12:42:14 +01:00
9822a79f90 Fix invalid function signatures for PySequenceMethods callbacks
Function casts hid casting between potentially incompatible type
signatures (using int instead of Py_ssize_t). As it happens this seems
not to have caused any bugs on supported platforms so this change is
mainly for correctness and to avoid problems in the future.
2022-11-08 12:42:14 +01:00
0e2a400f11 Fix T102329: assert when cutting node tree link 2022-11-08 12:42:14 +01:00
9e67d373df Fix T101526: assert due to wrong node tree owner id 2022-11-08 12:42:14 +01:00
0a8effa0f6 Cleanup: correct type of RNA struct methods
Some BPy_StructRNA methods used BPy_PropertyRNA in their function
signatures, while this didn't case any bugs, it could lead to issues
in the future.
2022-11-08 12:42:14 +01:00
cffb0ba217 Cleanup: PyMethodDef formatting
Missed these changes in [0].

Also replace designated initializers in some C code, as it's not used
often and would need to be removed when converting to C++.

[0] e555ede626
2022-11-08 12:42:14 +01:00
98fc2aa93f Fix support for building with ffmpeg < 5.0
Seems like the new audio channel api was not as backwards compatible as we thought.
Therefore we need to reintroduce the usage of the old api to make older ffmpeg version be able to compile Blender.

This change is only intended to stick around for two releases or so. After that we hope that most Linux distros ship
ffmpeg >=5.0 so we can switch to it.

Reviewed By: Sergey

Differential Revision: http://developer.blender.org/D16408
2022-11-08 12:42:14 +01:00
dc5d7441e7 Fix T101533: Wrong DoF when a non-camera object is the active camera
Make sure non-camera data is not casted to a Camera pointer.

Solution suggested by Damien Picard (@pioverfour).
2022-11-08 12:42:14 +01:00
8ed8d21f5e Fix T100872: restrict Python API on built-in nodes
Differential Revision: https://developer.blender.org/D16304
2022-11-08 12:42:14 +01:00
195a1c7fc8 Fix T102324: reverse curve node breaks crazy space editing 2022-11-08 12:42:14 +01:00
14db6975e6 Fix T102311: crash when opening node add menu with assets 2022-11-08 12:42:14 +01:00
61eb425db8 Merge branch 'master' into temp-asset-representation 2022-11-07 15:35:32 +01:00
efaeed1c17 Refactor how asset representations are added to an asset library 2022-11-07 15:11:27 +01:00
3de27e2ed9 Merge branch 'master' into temp-asset-representation 2022-11-02 19:03:14 +01:00
acb8aa8834 Use asset representation in file browser entries, not asset metadata
Rather than having the file entries store the asset metadata (and own it
unless it's a local ID asset), reference the asset representation (owned
by the asset library) and request the metadata through that.
2022-11-02 18:55:00 +01:00
d7936c2de0 Merge branch 'master' into temp-asset-representation 2022-11-02 12:20:55 +01:00
8bc3363c0f Merge branch 'master' into temp-asset-representation 2022-09-22 15:11:50 +02:00
968b0495e2 Initial AssetRepresentation type, storage & construction 2022-09-21 20:29:37 +02:00
30 changed files with 477 additions and 165 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View 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

View File

@@ -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

View File

@@ -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__);

View File

@@ -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;
}

View File

@@ -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)) {

View File

@@ -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

View File

@@ -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. */

View File

@@ -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();

View 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();
}
/** \} */

View File

@@ -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};
}

View 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) {

View File

@@ -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)

View File

@@ -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));
}

View File

@@ -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,

View File

@@ -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.

View File

@@ -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,

View File

@@ -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>(

View File

@@ -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,

View File

@@ -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);
}

View File

@@ -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
}

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}