diff --git a/source/blender/blenkernel/BKE_asset.h b/source/blender/blenkernel/BKE_asset.h index 81a132a8f91..81b520a1db0 100644 --- a/source/blender/blenkernel/BKE_asset.h +++ b/source/blender/blenkernel/BKE_asset.h @@ -71,12 +71,3 @@ void BKE_asset_metadata_read(struct BlendDataReader *reader, struct AssetMetaDat #ifdef __cplusplus } #endif - -#ifdef __cplusplus - -# include - -[[nodiscard]] std::unique_ptr BKE_asset_metadata_move_to_unique_ptr( - AssetMetaData *asset_data); - -#endif diff --git a/source/blender/blenkernel/intern/asset.cc b/source/blender/blenkernel/intern/asset.cc index 7103e017847..74605af815d 100644 --- a/source/blender/blenkernel/intern/asset.cc +++ b/source/blender/blenkernel/intern/asset.cc @@ -47,13 +47,6 @@ AssetMetaData::~AssetMetaData() BLI_freelistN(&tags); } -std::unique_ptr BKE_asset_metadata_move_to_unique_ptr(AssetMetaData *asset_data) -{ - std::unique_ptr unique_asset_data = std::make_unique(*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__); diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index 75a1956ce12..4c34b628a6d 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -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, diff --git a/source/blender/blenloader/intern/readblenentry.cc b/source/blender/blenloader/intern/readblenentry.cc index ead796c0e28..6b59ef87cec 100644 --- a/source/blender/blenloader/intern/readblenentry.cc +++ b/source/blender/blenloader/intern/readblenentry.cc @@ -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(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. */ diff --git a/source/blender/editors/asset/intern/asset_indexer.cc b/source/blender/editors/asset/intern/asset_indexer.cc index a604ab813d7..23d6a9d1edc 100644 --- a/source/blender/editors/asset/intern/asset_indexer.cc +++ b/source/blender/editors/asset/intern/asset_indexer.cc @@ -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(); diff --git a/source/blender/editors/space_file/file_indexer.cc b/source/blender/editors/space_file/file_indexer.cc index 8520ac34122..7670f475599 100644 --- a/source/blender/editors/space_file/file_indexer.cc +++ b/source/blender/editors/space_file/file_indexer.cc @@ -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(indexer_entry_ptr); + BLO_datablock_info_free(&indexer_entry->datablock_info); MEM_freeN(indexer_entry); } diff --git a/source/blender/editors/space_file/filelist.cc b/source/blender/editors/space_file/filelist.cc index 44bfa7fcbaf..bf0f9c865a8 100644 --- a/source/blender/editors/space_file/filelist.cc +++ b/source/blender/editors/space_file/filelist.cc @@ -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(*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 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 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; } } diff --git a/source/blender/makesdna/DNA_asset_types.h b/source/blender/makesdna/DNA_asset_types.h index d7e3bcfc919..f4a57644dff 100644 --- a/source/blender/makesdna/DNA_asset_types.h +++ b/source/blender/makesdna/DNA_asset_types.h @@ -43,6 +43,7 @@ typedef struct AssetFilterSettings { */ typedef struct AssetMetaData { #ifdef __cplusplus + /** Enables use with `std::unique_ptr`. */ ~AssetMetaData(); #endif