Fix asset index only generating empty entries since 1efc94bb2f

Steps to reproduce were:
- Open a .blend file that is located inside of an asset library and
  contains assets.
- Save and close the file.
- Open a new file (Ctrl+N -> General).
- Open asset browser and load the asset library from above.
- If the assets from the file above still show up, press refresh button.
- -> Assets from the file above don't appear.

Likely fixes the underlying issue for T102610. A followup will be needed
to correct the empty asset index files written because of this bug.

We're in the process of moving responsibilities from the file/asset
browser backend to the asset system. 1efc94bb2f introduces a new
representation for asset, which would own the asset metadata now instead
of the file data.

Since the file-list code still does the loading of asset libraries,
ownership of the asset metadata has to be transferred to the asset
system. However, the asset indexing still requires it to be available,
so it can update the index with latest data. So transfer the ownership,
but still keep a non-owning pointer set.

Differential Revision: https://developer.blender.org/D16665

Reviewed by: Bastien Montagne
This commit is contained in:
Julian Eisel 2022-12-01 15:48:54 +01:00
parent 79498d4463
commit 6a7917162c
Notes: blender-bot 2023-06-16 14:19:17 +02:00
Referenced by commit 1229b96652, Fix empty asset index files after bug in asset loading
Referenced by issue #102610, Regression: Asset disappearing on refresh
Referenced by issue #109053, File Append with recursions leads to crash
8 changed files with 46 additions and 23 deletions

View File

@ -71,12 +71,3 @@ void BKE_asset_metadata_read(struct BlendDataReader *reader, struct AssetMetaDat
#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

@ -47,13 +47,6 @@ AssetMetaData::~AssetMetaData()
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

@ -182,6 +182,7 @@ void BLO_blendfiledata_free(BlendFileData *bfd);
typedef struct BLODataBlockInfo {
char name[64]; /* MAX_NAME */
struct AssetMetaData *asset_data;
bool free_asset_data;
/* Optimization: Tag data-blocks for which we know there is no preview.
* Knowing this can be used to skip the (potentially expensive) preview loading process. If this
* is set to true it means we looked for a preview and couldn't find one. False may mean that
@ -189,6 +190,15 @@ typedef struct BLODataBlockInfo {
bool no_preview_found;
} BLODataBlockInfo;
/**
* Frees contained data, not \a datablock_info itself.
*/
void BLO_datablock_info_free(BLODataBlockInfo *datablock_info);
/**
* Can be used to free the list returned by #BLO_blendhandle_get_datablock_info().
*/
void BLO_datablock_info_linklist_free(struct LinkNode * /*BLODataBlockInfo*/ datablock_infos);
/**
* Open a blendhandle from a file path.
*
@ -231,8 +241,11 @@ struct LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh,
* \param ofblocktype: The type of names to get.
* \param use_assets_only: Limit the result to assets only.
* \param r_tot_info_items: The length of the returned list.
*
* \return A BLI_linklist of `BLODataBlockInfo *`.
* The links and #BLODataBlockInfo.asset_data should be freed with MEM_freeN.
*
* \note The links should be freed using #BLO_datablock_info_free() or the entire list using
* #BLO_datablock_info_linklist_free().
*/
struct LinkNode * /*BLODataBlockInfo*/ BLO_blendhandle_get_datablock_info(BlendHandle *bh,
int ofblocktype,

View File

@ -23,6 +23,7 @@
#include "DNA_genfile.h"
#include "DNA_sdna_types.h"
#include "BKE_asset.h"
#include "BKE_icons.h"
#include "BKE_idtype.h"
#include "BKE_main.h"
@ -44,6 +45,23 @@ void BLO_blendhandle_print_sizes(BlendHandle *bh, void *fp);
/* Access routines used by filesel. */
void BLO_datablock_info_free(BLODataBlockInfo *datablock_info)
{
if (datablock_info->free_asset_data) {
BKE_asset_metadata_free(&datablock_info->asset_data);
datablock_info->free_asset_data = false;
}
}
void BLO_datablock_info_linklist_free(LinkNode *datablock_infos)
{
BLI_linklist_free(datablock_infos, [](void *link) {
BLODataBlockInfo *datablock_info = static_cast<BLODataBlockInfo *>(link);
BLO_datablock_info_free(datablock_info);
MEM_freeN(datablock_info);
});
}
BlendHandle *BLO_blendhandle_from_file(const char *filepath, BlendFileReadReport *reports)
{
BlendHandle *bh;
@ -168,6 +186,7 @@ LinkNode *BLO_blendhandle_get_datablock_info(BlendHandle *bh,
STRNCPY(info->name, name);
info->asset_data = asset_meta_data;
info->free_asset_data = true;
bool has_preview = false;
/* See if we can find a preview in the data of this ID. */

View File

@ -357,6 +357,7 @@ static void init_indexer_entry_from_value(FileIndexerEntry &indexer_entry,
AssetMetaData *asset_data = BKE_asset_metadata_create();
indexer_entry.datablock_info.asset_data = asset_data;
indexer_entry.datablock_info.free_asset_data = true;
if (entry.has_description()) {
const StringRefNull description = entry.get_description();

View File

@ -70,6 +70,7 @@ void ED_file_indexer_entries_extend_from_datablock_infos(
static void ED_file_indexer_entry_free(void *indexer_entry_ptr)
{
FileIndexerEntry *indexer_entry = static_cast<FileIndexerEntry *>(indexer_entry_ptr);
BLO_datablock_info_free(&indexer_entry->datablock_info);
MEM_freeN(indexer_entry);
}

View File

@ -3105,10 +3105,14 @@ static void filelist_readjob_list_lib_add_datablock(FileListReadJob *job_params,
entry->typeflag |= FILE_TYPE_ASSET;
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);
/* Take ownership over the asset data (shallow copies into unique_ptr managed memory) to
* pass it on to the asset system. */
std::unique_ptr metadata = std::make_unique<AssetMetaData>(*datablock_info->asset_data);
MEM_freeN(datablock_info->asset_data);
/* Give back a non-owning pointer, because the data-block info is still needed (e.g. to
* update the asset index). */
datablock_info->asset_data = metadata.get();
datablock_info->free_asset_data = false;
entry->asset = &filelist->asset_library->add_external_asset(
entry->relpath, datablock_info->name, std::move(metadata));
@ -3267,7 +3271,7 @@ static std::optional<int> filelist_readjob_list_lib(FileListReadJob *job_params,
libfiledata, idcode, options & LIST_LIB_ASSETS_ONLY, &datablock_len);
filelist_readjob_list_lib_add_datablocks(
job_params, entries, datablock_infos, false, idcode, group);
BLI_linklist_freeN(datablock_infos);
BLO_datablock_info_linklist_free(datablock_infos);
}
else {
LinkNode *groups = BLO_blendhandle_get_linkable_groups(libfiledata);
@ -3290,7 +3294,7 @@ static std::optional<int> filelist_readjob_list_lib(FileListReadJob *job_params,
ED_file_indexer_entries_extend_from_datablock_infos(
&indexer_entries, group_datablock_infos, idcode);
}
BLI_linklist_freeN(group_datablock_infos);
BLO_datablock_info_linklist_free(group_datablock_infos);
datablock_len += group_datablock_len;
}
}

View File

@ -43,6 +43,7 @@ typedef struct AssetFilterSettings {
*/
typedef struct AssetMetaData {
#ifdef __cplusplus
/** Enables use with `std::unique_ptr<AssetMetaData>`. */
~AssetMetaData();
#endif