diff options
author | Bastien Montagne <bastien@blender.org> | 2021-06-23 10:51:11 +0300 |
---|---|---|
committer | Bastien Montagne <bastien@blender.org> | 2021-06-23 11:37:00 +0300 |
commit | 82c17082ba0e53d782ac6be703d71d188a331dde (patch) | |
tree | 3bdb6f1a86bc8bf506d28046ada40b7f881dba86 /source | |
parent | 071799d4fc44f422abacbdad09bb45fb95de89f2 (diff) |
Revert "Revert "Enhanced stats/reports for blendfile reading.""
This reverts commit rB3a48147b8ab92, and fixes the issues with linking
etc.
Change compared to previous buggy commit (rBf8d219dfd4c31) is that
new `BlendFileReadReports` reports are now passed to the lowest level
function generating the `FileData` (`filedata_new()`), which ensures
(and asserts) that all code using it does have a valid non-NULL pointer
to a `BlendFileReadReport` data.
Sorry for the noise, it's always when you think a change is trivial and
do not test it well enough that you end up doing those kind of
mistakes...
Diffstat (limited to 'source')
21 files changed, 293 insertions, 102 deletions
diff --git a/source/blender/blenkernel/BKE_blendfile.h b/source/blender/blenkernel/BKE_blendfile.h index 429e294a337..3e0a343a766 100644 --- a/source/blender/blenkernel/BKE_blendfile.h +++ b/source/blender/blenkernel/BKE_blendfile.h @@ -25,6 +25,7 @@ extern "C" { struct BlendFileData; struct BlendFileReadParams; +struct BlendFileReadReport; struct ID; struct Main; struct MemFile; @@ -35,7 +36,7 @@ struct bContext; void BKE_blendfile_read_setup_ex(struct bContext *C, struct BlendFileData *bfd, const struct BlendFileReadParams *params, - struct ReportList *reports, + struct BlendFileReadReport *reports, /* Extra args. */ const bool startup_update_defaults, const char *startup_app_template); @@ -43,11 +44,11 @@ void BKE_blendfile_read_setup_ex(struct bContext *C, void BKE_blendfile_read_setup(struct bContext *C, struct BlendFileData *bfd, const struct BlendFileReadParams *params, - struct ReportList *reports); + struct BlendFileReadReport *reports); struct BlendFileData *BKE_blendfile_read(const char *filepath, const struct BlendFileReadParams *params, - struct ReportList *reports); + struct BlendFileReadReport *reports); struct BlendFileData *BKE_blendfile_read_from_memory(const void *filebuf, int filelength, diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h index 4dc99e64cf2..3eb0ff44129 100644 --- a/source/blender/blenkernel/BKE_lib_override.h +++ b/source/blender/blenkernel/BKE_lib_override.h @@ -43,6 +43,7 @@ extern "C" { #endif struct Collection; +struct BlendFileReadReport; struct ID; struct IDOverrideLibrary; struct IDOverrideLibraryProperty; @@ -90,11 +91,11 @@ bool BKE_lib_override_library_resync(struct Main *bmain, struct Collection *override_resync_residual_storage, const bool do_hierarchy_enforce, const bool do_post_process, - struct ReportList *reports); + struct BlendFileReadReport *reports); void BKE_lib_override_library_main_resync(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, - struct ReportList *reports); + struct BlendFileReadReport *reports); void BKE_lib_override_library_delete(struct Main *bmain, struct ID *id_root); diff --git a/source/blender/blenkernel/intern/blender_copybuffer.c b/source/blender/blenkernel/intern/blender_copybuffer.c index dfd49a347ca..c8fedc086b8 100644 --- a/source/blender/blenkernel/intern/blender_copybuffer.c +++ b/source/blender/blenkernel/intern/blender_copybuffer.c @@ -87,7 +87,7 @@ bool BKE_copybuffer_read(Main *bmain_dst, ReportList *reports, const uint64_t id_types_mask) { - BlendHandle *bh = BLO_blendhandle_from_file(libname, reports); + BlendHandle *bh = BLO_blendhandle_from_file(libname, &(BlendFileReadReport){.reports = reports}); if (bh == NULL) { /* Error reports will have been made by BLO_blendhandle_from_file(). */ return false; @@ -133,7 +133,7 @@ int BKE_copybuffer_paste(bContext *C, BlendHandle *bh; const int id_tag_extra = 0; - bh = BLO_blendhandle_from_file(libname, reports); + bh = BLO_blendhandle_from_file(libname, &(BlendFileReadReport){.reports = reports}); if (bh == NULL) { /* error reports will have been made by BLO_blendhandle_from_file() */ diff --git a/source/blender/blenkernel/intern/blender_undo.c b/source/blender/blenkernel/intern/blender_undo.c index ba41786c7fd..6f47cd1336e 100644 --- a/source/blender/blenkernel/intern/blender_undo.c +++ b/source/blender/blenkernel/intern/blender_undo.c @@ -78,9 +78,10 @@ bool BKE_memfile_undo_decode(MemFileUndoData *mfu, if (UNDO_DISK) { const struct BlendFileReadParams params = {0}; - struct BlendFileData *bfd = BKE_blendfile_read(mfu->filename, ¶ms, NULL); + struct BlendFileData *bfd = BKE_blendfile_read( + mfu->filename, ¶ms, &(BlendFileReadReport){NULL}); if (bfd != NULL) { - BKE_blendfile_read_setup(C, bfd, ¶ms, NULL); + BKE_blendfile_read_setup(C, bfd, ¶ms, &(BlendFileReadReport){NULL}); success = true; } } @@ -93,7 +94,7 @@ bool BKE_memfile_undo_decode(MemFileUndoData *mfu, struct BlendFileData *bfd = BKE_blendfile_read_from_memfile( bmain, &mfu->memfile, ¶ms, NULL); if (bfd != NULL) { - BKE_blendfile_read_setup(C, bfd, ¶ms, NULL); + BKE_blendfile_read_setup(C, bfd, ¶ms, &(BlendFileReadReport){NULL}); success = true; } } diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c index e335dd4bdcd..9ea1c8fedda 100644 --- a/source/blender/blenkernel/intern/blendfile.c +++ b/source/blender/blenkernel/intern/blendfile.c @@ -36,6 +36,8 @@ #include "BLI_system.h" #include "BLI_utildefines.h" +#include "PIL_time.h" + #include "IMB_colormanagement.h" #include "BKE_addon.h" @@ -136,7 +138,7 @@ static void setup_app_userdef(BlendFileData *bfd) static void setup_app_data(bContext *C, BlendFileData *bfd, const struct BlendFileReadParams *params, - ReportList *reports) + BlendFileReadReport *reports) { Main *bmain = G_MAIN; Scene *curscene = NULL; @@ -155,7 +157,7 @@ static void setup_app_data(bContext *C, /* may happen with library files - UNDO file should never have NULL curscene (but may have a * NULL curscreen)... */ else if (ELEM(NULL, bfd->curscreen, bfd->curscene)) { - BKE_report(reports, RPT_WARNING, "Library file, loading empty scene"); + BKE_report(reports->reports, RPT_WARNING, "Library file, loading empty scene"); mode = LOAD_UI_OFF; } else if (G.fileflags & G_FILE_NO_UI) { @@ -396,11 +398,17 @@ static void setup_app_data(bContext *C, } if (mode != LOAD_UNDO && !USER_EXPERIMENTAL_TEST(&U, no_override_auto_resync)) { + reports->duration.lib_overrides_resync = PIL_check_seconds_timer(); + BKE_lib_override_library_main_resync( bmain, curscene, bfd->cur_view_layer ? bfd->cur_view_layer : BKE_view_layer_default_view(curscene), reports); + + reports->duration.lib_overrides_resync = PIL_check_seconds_timer() - + reports->duration.lib_overrides_resync; + /* We need to rebuild some of the deleted override rules (for UI feedback purpose). */ BKE_lib_override_library_main_operations_create(bmain, true); } @@ -409,7 +417,7 @@ static void setup_app_data(bContext *C, static void setup_app_blend_file_data(bContext *C, BlendFileData *bfd, const struct BlendFileReadParams *params, - ReportList *reports) + BlendFileReadReport *reports) { if ((params->skip_flags & BLO_READ_SKIP_USERDEF) == 0) { setup_app_userdef(bfd); @@ -419,12 +427,12 @@ static void setup_app_blend_file_data(bContext *C, } } -static void handle_subversion_warning(Main *main, ReportList *reports) +static void handle_subversion_warning(Main *main, BlendFileReadReport *reports) { if (main->minversionfile > BLENDER_FILE_VERSION || (main->minversionfile == BLENDER_FILE_VERSION && main->minsubversionfile > BLENDER_FILE_SUBVERSION)) { - BKE_reportf(reports, + BKE_reportf(reports->reports, RPT_ERROR, "File written by newer Blender binary (%d.%d), expect loss of data!", main->minversionfile, @@ -443,7 +451,7 @@ static void handle_subversion_warning(Main *main, ReportList *reports) void BKE_blendfile_read_setup_ex(bContext *C, BlendFileData *bfd, const struct BlendFileReadParams *params, - ReportList *reports, + BlendFileReadReport *reports, /* Extra args. */ const bool startup_update_defaults, const char *startup_app_template) @@ -460,7 +468,7 @@ void BKE_blendfile_read_setup_ex(bContext *C, void BKE_blendfile_read_setup(bContext *C, BlendFileData *bfd, const struct BlendFileReadParams *params, - ReportList *reports) + BlendFileReadReport *reports) { BKE_blendfile_read_setup_ex(C, bfd, params, reports, false, NULL); } @@ -470,7 +478,7 @@ void BKE_blendfile_read_setup(bContext *C, */ struct BlendFileData *BKE_blendfile_read(const char *filepath, const struct BlendFileReadParams *params, - ReportList *reports) + BlendFileReadReport *reports) { /* Don't print startup file loading. */ if (params->is_startup == false) { @@ -482,7 +490,7 @@ struct BlendFileData *BKE_blendfile_read(const char *filepath, handle_subversion_warning(bfd->main, reports); } else { - BKE_reports_prependf(reports, "Loading '%s' failed: ", filepath); + BKE_reports_prependf(reports->reports, "Loading '%s' failed: ", filepath); } return bfd; } @@ -559,7 +567,9 @@ UserDef *BKE_blendfile_userdef_read(const char *filepath, ReportList *reports) BlendFileData *bfd; UserDef *userdef = NULL; - bfd = BLO_read_from_file(filepath, BLO_READ_SKIP_ALL & ~BLO_READ_SKIP_USERDEF, reports); + bfd = BLO_read_from_file(filepath, + BLO_READ_SKIP_ALL & ~BLO_READ_SKIP_USERDEF, + &(struct BlendFileReadReport){.reports = reports}); if (bfd) { if (bfd->user) { userdef = bfd->user; @@ -770,7 +780,8 @@ WorkspaceConfigFileData *BKE_blendfile_workspace_config_read(const char *filepat WorkspaceConfigFileData *workspace_config = NULL; if (filepath) { - bfd = BLO_read_from_file(filepath, BLO_READ_SKIP_USERDEF, reports); + bfd = BLO_read_from_file( + filepath, BLO_READ_SKIP_USERDEF, &(struct BlendFileReadReport){.reports = reports}); } else { bfd = BLO_read_from_memory(filebuf, filelength, BLO_READ_SKIP_USERDEF, reports); diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index c93971e7b11..270d7ca358a 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -52,12 +52,17 @@ #include "BKE_report.h" #include "BKE_scene.h" +#include "BLO_readfile.h" + #include "BLI_ghash.h" +#include "BLI_linklist.h" #include "BLI_listbase.h" #include "BLI_string.h" #include "BLI_task.h" #include "BLI_utildefines.h" +#include "PIL_time.h" + #include "RNA_access.h" #include "RNA_types.h" @@ -958,7 +963,7 @@ bool BKE_lib_override_library_resync(Main *bmain, Collection *override_resync_residual_storage, const bool do_hierarchy_enforce, const bool do_post_process, - ReportList *reports) + BlendFileReadReport *reports) { BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root)); @@ -1286,7 +1291,7 @@ bool BKE_lib_override_library_resync(Main *bmain, id_root = id_root_reference->newid; if (user_edited_overrides_deletion_count > 0) { - BKE_reportf(reports, + BKE_reportf(reports != NULL ? reports->reports : NULL, RPT_WARNING, "During resync of data-block %s, %d obsolete overrides were deleted, that had " "local changes defined by user", @@ -1438,8 +1443,11 @@ static void lib_override_library_main_resync_on_library_indirect_level( ViewLayer *view_layer, Collection *override_resync_residual_storage, const int library_indirect_level, - ReportList *reports) + BlendFileReadReport *reports) { + const bool do_reports_recursive_resync_timing = (library_indirect_level != 0); + const double init_time = do_reports_recursive_resync_timing ? PIL_check_seconds_timer() : 0.0; + BKE_main_relations_create(bmain, 0); BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); @@ -1530,6 +1538,7 @@ static void lib_override_library_main_resync_on_library_indirect_level( (!ID_IS_LINKED(id) && library_indirect_level != 0)) { continue; } + Library *library = id->lib; int level = 0; /* In complex non-supported cases, with several different override hierarchies sharing @@ -1541,12 +1550,21 @@ static void lib_override_library_main_resync_on_library_indirect_level( id = lib_override_library_main_resync_find_root_recurse(id, &level); id->tag &= ~LIB_TAG_LIB_OVERRIDE_NEED_RESYNC; BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id)); + BLI_assert(id->lib == library); do_continue = true; - CLOG_INFO(&LOG, 2, "Resyncing %s (%p)...", id->name, id->lib); + CLOG_INFO(&LOG, 2, "Resyncing %s (%p)...", id->name, library); const bool success = BKE_lib_override_library_resync( bmain, scene, view_layer, id, override_resync_residual_storage, false, false, reports); CLOG_INFO(&LOG, 2, "\tSuccess: %d", success); + if (success) { + reports->count.resynced_lib_overrides++; + if (library_indirect_level > 0 && + BLI_linklist_index(reports->resynced_lib_overrides_libraries, library) < 0) { + BLI_linklist_prepend(&reports->resynced_lib_overrides_libraries, library); + reports->resynced_lib_overrides_libraries_count++; + } + } break; } FOREACH_MAIN_LISTBASE_ID_END; @@ -1556,6 +1574,10 @@ static void lib_override_library_main_resync_on_library_indirect_level( } FOREACH_MAIN_LISTBASE_END; } + + if (do_reports_recursive_resync_timing) { + reports->duration.lib_overrides_recursive_resync += PIL_check_seconds_timer() - init_time; + } } static int lib_override_sort_libraries_func(LibraryIDLinkCallbackData *cb_data) @@ -1633,7 +1655,7 @@ static int lib_override_libraries_index_define(Main *bmain) void BKE_lib_override_library_main_resync(Main *bmain, Scene *scene, ViewLayer *view_layer, - ReportList *reports) + BlendFileReadReport *reports) { /* We use a specific collection to gather/store all 'orphaned' override collections and objects * generated by re-sync-process. This avoids putting them in scene's master collection. */ diff --git a/source/blender/blenloader/BLO_read_write.h b/source/blender/blenloader/BLO_read_write.h index ea0532d884b..86c7c367816 100644 --- a/source/blender/blenloader/BLO_read_write.h +++ b/source/blender/blenloader/BLO_read_write.h @@ -54,6 +54,7 @@ typedef struct BlendExpander BlendExpander; typedef struct BlendLibReader BlendLibReader; typedef struct BlendWriter BlendWriter; +struct BlendFileReadReport; struct Main; struct ReportList; @@ -216,7 +217,7 @@ bool BLO_read_requires_endian_switch(BlendDataReader *reader); bool BLO_read_data_is_undo(BlendDataReader *reader); void BLO_read_data_globmap_add(BlendDataReader *reader, void *oldaddr, void *newaddr); void BLO_read_glob_list(BlendDataReader *reader, struct ListBase *list); -struct ReportList *BLO_read_data_reports(BlendDataReader *reader); +struct BlendFileReadReport *BLO_read_data_reports(BlendDataReader *reader); /* Blend Read Lib API * =================== @@ -233,7 +234,7 @@ ID *BLO_read_get_new_id_address(BlendLibReader *reader, struct Library *lib, str /* Misc. */ bool BLO_read_lib_is_undo(BlendLibReader *reader); struct Main *BLO_read_lib_get_main(BlendLibReader *reader); -struct ReportList *BLO_read_lib_reports(BlendLibReader *reader); +struct BlendFileReadReport *BLO_read_lib_reports(BlendLibReader *reader); /* Blend Expand API * =================== @@ -250,8 +251,10 @@ void BLO_expand_id(BlendExpander *expander, struct ID *id); * =================== */ -void BLO_reportf_wrap(struct ReportList *reports, ReportType type, const char *format, ...) - ATTR_PRINTF_FORMAT(3, 4); +void BLO_reportf_wrap(struct BlendFileReadReport *reports, + ReportType type, + const char *format, + ...) ATTR_PRINTF_FORMAT(3, 4); #ifdef __cplusplus } diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index 89db216aada..307c09f8ff5 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -89,6 +89,35 @@ struct BlendFileReadParams { int undo_direction; /* eUndoStepDir */ }; +typedef struct BlendFileReadReport { + /* General reports handling. */ + struct ReportList *reports; + + /* Timing informations .*/ + struct { + double whole; + double libraries; + double lib_overrides; + double lib_overrides_resync; + double lib_overrides_recursive_resync; + } duration; + + /* Count informations. */ + struct { + /* Some numbers of IDs that ended up in a specific state, or required some specific process + * during this file read. */ + int missing_libraries; + int missing_linked_id; + /* Number of root override IDs that were resynced. */ + int resynced_lib_overrides; + } count; + + /* Number of libraries which had overrides that needed to be resynced, and a single linked list + * of those. */ + int resynced_lib_overrides_libraries_count; + struct LinkNode *resynced_lib_overrides_libraries; +} BlendFileReadReport; + /* skip reading some data-block types (may want to skip screen data too). */ typedef enum eBLOReadSkip { BLO_READ_SKIP_NONE = 0, @@ -101,7 +130,7 @@ typedef enum eBLOReadSkip { BlendFileData *BLO_read_from_file(const char *filepath, eBLOReadSkip skip_flags, - struct ReportList *reports); + struct BlendFileReadReport *reports); BlendFileData *BLO_read_from_memory(const void *mem, int memsize, eBLOReadSkip skip_flags, @@ -125,7 +154,7 @@ struct BLODataBlockInfo { struct AssetMetaData *asset_data; }; -BlendHandle *BLO_blendhandle_from_file(const char *filepath, struct ReportList *reports); +BlendHandle *BLO_blendhandle_from_file(const char *filepath, struct BlendFileReadReport *reports); BlendHandle *BLO_blendhandle_from_memory(const void *mem, int memsize); struct LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh, diff --git a/source/blender/blenloader/intern/blend_validate.c b/source/blender/blenloader/intern/blend_validate.c index f3fc1453461..0f729304128 100644 --- a/source/blender/blenloader/intern/blend_validate.c +++ b/source/blender/blenloader/intern/blend_validate.c @@ -83,7 +83,8 @@ bool BLO_main_validate_libraries(Main *bmain, ReportList *reports) } BKE_library_filepath_set(bmain, curlib, curlib->filepath); - BlendHandle *bh = BLO_blendhandle_from_file(curlib->filepath_abs, reports); + BlendHandle *bh = BLO_blendhandle_from_file(curlib->filepath_abs, + &(BlendFileReadReport){.reports = reports}); if (bh == NULL) { BKE_reportf(reports, diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c index 19033ba9bf1..1a324d56f06 100644 --- a/source/blender/blenloader/intern/readblenentry.c +++ b/source/blender/blenloader/intern/readblenentry.c @@ -68,7 +68,7 @@ void BLO_blendhandle_print_sizes(BlendHandle *bh, void *fp); * \param reports: Report errors in opening the file (can be NULL). * \return A handle on success, or NULL on failure. */ -BlendHandle *BLO_blendhandle_from_file(const char *filepath, ReportList *reports) +BlendHandle *BLO_blendhandle_from_file(const char *filepath, BlendFileReadReport *reports) { BlendHandle *bh; @@ -88,7 +88,8 @@ BlendHandle *BLO_blendhandle_from_memory(const void *mem, int memsize) { BlendHandle *bh; - bh = (BlendHandle *)blo_filedata_from_memory(mem, memsize, NULL); + bh = (BlendHandle *)blo_filedata_from_memory( + mem, memsize, &(BlendFileReadReport){.reports = NULL}); return bh; } @@ -366,14 +367,13 @@ void BLO_blendhandle_close(BlendHandle *bh) */ BlendFileData *BLO_read_from_file(const char *filepath, eBLOReadSkip skip_flags, - ReportList *reports) + BlendFileReadReport *reports) { BlendFileData *bfd = NULL; FileData *fd; fd = blo_filedata_from_file(filepath, reports); if (fd) { - fd->reports = reports; fd->skip_flags = skip_flags; bfd = blo_read_file_internal(fd, filepath); blo_filedata_free(fd); @@ -399,9 +399,8 @@ BlendFileData *BLO_read_from_memory(const void *mem, BlendFileData *bfd = NULL; FileData *fd; - fd = blo_filedata_from_memory(mem, memsize, reports); + fd = blo_filedata_from_memory(mem, memsize, &(BlendFileReadReport){.reports = reports}); if (fd) { - fd->reports = reports; fd->skip_flags = skip_flags; bfd = blo_read_file_internal(fd, ""); blo_filedata_free(fd); @@ -428,9 +427,8 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, FileData *fd; ListBase old_mainlist; - fd = blo_filedata_from_memfile(memfile, params, reports); + fd = blo_filedata_from_memfile(memfile, params, &(BlendFileReadReport){.reports = reports}); if (fd) { - fd->reports = reports; fd->skip_flags = params->skip_flags; BLI_strncpy(fd->relabase, filename, sizeof(fd->relabase)); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index dab630d451c..9a3da412524 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -72,6 +72,8 @@ #include "BLI_mmap.h" #include "BLI_threads.h" +#include "PIL_time.h" + #include "BLT_translation.h" #include "BKE_anim_data.h" @@ -227,7 +229,7 @@ typedef struct BHeadN { * bit kludge but better than doubling up on prints, * we could alternatively have a versions of a report function which forces printing - campbell */ -void BLO_reportf_wrap(ReportList *reports, ReportType type, const char *format, ...) +void BLO_reportf_wrap(BlendFileReadReport *reports, ReportType type, const char *format, ...) { char fixed_buf[1024]; /* should be long enough */ @@ -239,7 +241,7 @@ void BLO_reportf_wrap(ReportList *reports, ReportType type, const char *format, fixed_buf[sizeof(fixed_buf) - 1] = '\0'; - BKE_report(reports, type, fixed_buf); + BKE_report(reports->reports, type, fixed_buf); if (G.background == 0) { printf("%s: %s\n", BKE_report_type_str(type), fixed_buf); @@ -1331,8 +1333,10 @@ static ssize_t fd_read_from_memfile(FileData *filedata, return 0; } -static FileData *filedata_new(void) +static FileData *filedata_new(BlendFileReadReport *reports) { + BLI_assert(reports != NULL); + FileData *fd = MEM_callocN(sizeof(FileData), "FileData"); fd->filedes = -1; @@ -1344,6 +1348,8 @@ static FileData *filedata_new(void) fd->globmap = oldnewmap_new(); fd->libmap = oldnewmap_new(); + fd->reports = reports; + return fd; } @@ -1371,7 +1377,7 @@ static FileData *blo_decode_and_check(FileData *fd, ReportList *reports) } static FileData *blo_filedata_from_file_descriptor(const char *filepath, - ReportList *reports, + BlendFileReadReport *reports, int file) { FileDataReadFn *read_fn = NULL; @@ -1386,7 +1392,7 @@ static FileData *blo_filedata_from_file_descriptor(const char *filepath, /* Regular file. */ errno = 0; if (read(file, header, sizeof(header)) != sizeof(header)) { - BKE_reportf(reports, + BKE_reportf(reports->reports, RPT_WARNING, "Unable to read '%s': %s", filepath, @@ -1416,7 +1422,7 @@ static FileData *blo_filedata_from_file_descriptor(const char *filepath, (header[0] == 0x1f && header[1] == 0x8b)) { gzfile = BLI_gzopen(filepath, "rb"); if (gzfile == (gzFile)Z_NULL) { - BKE_reportf(reports, + BKE_reportf(reports->reports, RPT_WARNING, "Unable to open '%s': %s", filepath, @@ -1431,11 +1437,11 @@ static FileData *blo_filedata_from_file_descriptor(const char *filepath, } if (read_fn == NULL) { - BKE_reportf(reports, RPT_WARNING, "Unrecognized file format '%s'", filepath); + BKE_reportf(reports->reports, RPT_WARNING, "Unrecognized file format '%s'", filepath); return NULL; } - FileData *fd = filedata_new(); + FileData *fd = filedata_new(reports); fd->filedes = file; fd->gzfiledes = gzfile; @@ -1448,12 +1454,12 @@ static FileData *blo_filedata_from_file_descriptor(const char *filepath, return fd; } -static FileData *blo_filedata_from_file_open(const char *filepath, ReportList *reports) +static FileData *blo_filedata_from_file_open(const char *filepath, BlendFileReadReport *reports) { errno = 0; const int file = BLI_open(filepath, O_BINARY | O_RDONLY, 0); if (file == -1) { - BKE_reportf(reports, + BKE_reportf(reports->reports, RPT_WARNING, "Unable to open '%s': %s", filepath, @@ -1469,14 +1475,14 @@ static FileData *blo_filedata_from_file_open(const char *filepath, ReportList *r /* cannot be called with relative paths anymore! */ /* on each new library added, it now checks for the current FileData and expands relativeness */ -FileData *blo_filedata_from_file(const char *filepath, ReportList *reports) +FileData *blo_filedata_from_file(const char *filepath, BlendFileReadReport *reports) { FileData *fd = blo_filedata_from_file_open(filepath, reports); if (fd != NULL) { /* needed for library_append and read_libraries */ BLI_strncpy(fd->relabase, filepath, sizeof(fd->relabase)); - return blo_decode_and_check(fd, reports); + return blo_decode_and_check(fd, reports->reports); } return NULL; } @@ -1487,7 +1493,7 @@ FileData *blo_filedata_from_file(const char *filepath, ReportList *reports) */ static FileData *blo_filedata_from_file_minimal(const char *filepath) { - FileData *fd = blo_filedata_from_file_open(filepath, NULL); + FileData *fd = blo_filedata_from_file_open(filepath, &(BlendFileReadReport){.reports = NULL}); if (fd != NULL) { decode_blender_header(fd); if (fd->flags & FD_FLAGS_FILE_OK) { @@ -1542,14 +1548,15 @@ static int fd_read_gzip_from_memory_init(FileData *fd) return 1; } -FileData *blo_filedata_from_memory(const void *mem, int memsize, ReportList *reports) +FileData *blo_filedata_from_memory(const void *mem, int memsize, BlendFileReadReport *reports) { if (!mem || memsize < SIZEOFBLENDERHEADER) { - BKE_report(reports, RPT_WARNING, (mem) ? TIP_("Unable to read") : TIP_("Unable to open")); + BKE_report( + reports->reports, RPT_WARNING, (mem) ? TIP_("Unable to read") : TIP_("Unable to open")); return NULL; } - FileData *fd = filedata_new(); + FileData *fd = filedata_new(reports); const char *cp = mem; fd->buffer = mem; @@ -1568,26 +1575,26 @@ FileData *blo_filedata_from_memory(const void *mem, int memsize, ReportList *rep fd->flags |= FD_FLAGS_NOT_MY_BUFFER; - return blo_decode_and_check(fd, reports); + return blo_decode_and_check(fd, reports->reports); } FileData *blo_filedata_from_memfile(MemFile *memfile, const struct BlendFileReadParams *params, - ReportList *reports) + BlendFileReadReport *reports) { if (!memfile) { - BKE_report(reports, RPT_WARNING, "Unable to open blend <memory>"); + BKE_report(reports->reports, RPT_WARNING, "Unable to open blend <memory>"); return NULL; } - FileData *fd = filedata_new(); + FileData *fd = filedata_new(reports); fd->memfile = memfile; fd->undo_direction = params->undo_direction; fd->read = fd_read_from_memfile; fd->flags |= FD_FLAGS_NOT_MY_BUFFER; - return blo_decode_and_check(fd, reports); + return blo_decode_and_check(fd, reports->reports); } void blo_filedata_free(FileData *fd) @@ -4206,6 +4213,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) } if ((fd->skip_flags & BLO_READ_SKIP_DATA) == 0) { + fd->reports->duration.libraries = PIL_check_seconds_timer(); read_libraries(fd, &mainlist); blo_join_main(&mainlist); @@ -4213,6 +4221,8 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) lib_link_all(fd, bfd->main); after_liblink_merged_bmain_process(bfd->main); + fd->reports->duration.libraries = PIL_check_seconds_timer() - fd->reports->duration.libraries; + /* Skip in undo case. */ if (fd->memfile == NULL) { /* Note that we can't recompute user-counts at this point in undo case, we play too much with @@ -4228,7 +4238,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) blo_split_main(&mainlist, bfd->main); LISTBASE_FOREACH (Main *, mainvar, &mainlist) { BLI_assert(mainvar->versionfile != 0); - do_versions_after_linking(mainvar, fd->reports); + do_versions_after_linking(mainvar, fd->reports->reports); } blo_join_main(&mainlist); @@ -4249,8 +4259,13 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) * we can re-generate overrides from their references. */ if (fd->memfile == NULL) { /* Do not apply in undo case! */ - BKE_lib_override_library_main_validate(bfd->main, fd->reports); + fd->reports->duration.lib_overrides = PIL_check_seconds_timer(); + + BKE_lib_override_library_main_validate(bfd->main, fd->reports->reports); BKE_lib_override_library_main_update(bfd->main); + + fd->reports->duration.lib_overrides = PIL_check_seconds_timer() - + fd->reports->duration.lib_overrides; } BKE_collections_after_lib_link(bfd->main); @@ -5206,7 +5221,7 @@ static void library_link_end(Main *mainl, * or they will go again through do_versions - bad, very bad! */ split_main_newid(mainvar, main_newid); - do_versions_after_linking(main_newid, (*fd)->reports); + do_versions_after_linking(main_newid, (*fd)->reports->reports); add_main_to_main(mainvar, main_newid); } @@ -5340,7 +5355,7 @@ static void read_library_linked_id( id->name + 2, mainvar->curlib->filepath_abs, library_parent_filepath(mainvar->curlib)); - basefd->library_id_missing_count++; + basefd->reports->count.missing_linked_id++; /* Generate a placeholder for this ID (simplified version of read_libblock actually...). */ if (r_id) { @@ -5495,7 +5510,7 @@ static FileData *read_library_file_data(FileData *basefd, if (fd == NULL) { BLO_reportf_wrap( basefd->reports, RPT_INFO, TIP_("Cannot find lib '%s'"), mainptr->curlib->filepath_abs); - basefd->library_file_missing_count++; + basefd->reports->count.missing_libraries++; } return fd; @@ -5589,15 +5604,6 @@ static void read_libraries(FileData *basefd, ListBase *mainlist) mainptr->curlib->filedata = NULL; } BKE_main_free(main_newid); - - if (basefd->library_file_missing_count != 0 || basefd->library_id_missing_count != 0) { - BKE_reportf(basefd->reports, - RPT_WARNING, - "LIB: %d libraries and %d linked data-blocks are missing, please check the " - "Info and Outliner editors for details", - basefd->library_file_missing_count, - basefd->library_id_missing_count); - } } void *BLO_read_get_new_data_address(BlendDataReader *reader, const void *old_address) @@ -5785,7 +5791,7 @@ void BLO_read_glob_list(BlendDataReader *reader, ListBase *list) link_glob_list(reader->fd, list); } -ReportList *BLO_read_data_reports(BlendDataReader *reader) +BlendFileReadReport *BLO_read_data_reports(BlendDataReader *reader) { return reader->fd->reports; } @@ -5800,7 +5806,7 @@ Main *BLO_read_lib_get_main(BlendLibReader *reader) return reader->main; } -ReportList *BLO_read_lib_reports(BlendLibReader *reader) +BlendFileReadReport *BLO_read_lib_reports(BlendLibReader *reader) { return reader->fd->reports; } diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h index d1d4e0b3256..b04043f9641 100644 --- a/source/blender/blenloader/intern/readfile.h +++ b/source/blender/blenloader/intern/readfile.h @@ -145,11 +145,7 @@ typedef struct FileData { ListBase *old_mainlist; struct IDNameLib_Map *old_idmap; - struct ReportList *reports; - /* Counters for amount of missing libraries, and missing IDs in libraries. - * Used to generate a synthetic report in the UI. */ - int library_file_missing_count; - int library_id_missing_count; + struct BlendFileReadReport *reports; } FileData; #define SIZEOFBLENDERHEADER 12 @@ -161,11 +157,13 @@ void blo_split_main(ListBase *mainlist, struct Main *main); BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath); -FileData *blo_filedata_from_file(const char *filepath, struct ReportList *reports); -FileData *blo_filedata_from_memory(const void *mem, int memsize, struct ReportList *reports); +FileData *blo_filedata_from_file(const char *filepath, struct BlendFileReadReport *reports); +FileData *blo_filedata_from_memory(const void *mem, + int memsize, + struct BlendFileReadReport *reports); FileData *blo_filedata_from_memfile(struct MemFile *memfile, const struct BlendFileReadParams *params, - struct ReportList *reports); + struct BlendFileReadReport *reports); void blo_clear_proxy_pointers_from_lib(struct Main *oldmain); void blo_make_packed_pointer_map(FileData *fd, struct Main *oldmain); diff --git a/source/blender/blenloader/intern/readfile_tempload.c b/source/blender/blenloader/intern/readfile_tempload.c index 4566e1e9b4d..f440a06acf8 100644 --- a/source/blender/blenloader/intern/readfile_tempload.c +++ b/source/blender/blenloader/intern/readfile_tempload.c @@ -40,7 +40,8 @@ TempLibraryContext *BLO_library_temp_load_id(struct Main *real_main, /* Copy the file path so any path remapping is performed properly. */ STRNCPY(temp_lib_ctx->bmain_base->name, real_main->name); - temp_lib_ctx->blendhandle = BLO_blendhandle_from_file(blend_file_path, reports); + temp_lib_ctx->blendhandle = BLO_blendhandle_from_file( + blend_file_path, &(BlendFileReadReport){.reports = reports}); BLO_library_link_params_init( &temp_lib_ctx->liblink_params, temp_lib_ctx->bmain_base, 0, LIB_TAG_TEMP_MAIN); diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index bf8f7eeca5c..0059074c8ad 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -1912,7 +1912,9 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) FOREACH_NODETREE_END; if (error & NTREE_DOVERSION_NEED_OUTPUT) { - BKE_report(fd->reports, RPT_ERROR, "Eevee material conversion problem. Error in console"); + BKE_report(fd->reports != NULL ? fd->reports->reports : NULL, + RPT_ERROR, + "Eevee material conversion problem. Error in console"); printf( "You need to connect Principled and Eevee Specular shader nodes to new material " "output " @@ -1920,7 +1922,9 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } if (error & NTREE_DOVERSION_TRANSPARENCY_EMISSION) { - BKE_report(fd->reports, RPT_ERROR, "Eevee material conversion problem. Error in console"); + BKE_report(fd->reports != NULL ? fd->reports->reports : NULL, + RPT_ERROR, + "Eevee material conversion problem. Error in console"); printf( "You need to combine transparency and emission shaders to the converted Principled " "shader nodes.\n"); diff --git a/source/blender/blenloader/tests/blendfile_loading_base_test.cc b/source/blender/blenloader/tests/blendfile_loading_base_test.cc index 280a4b42b36..e93348b2158 100644 --- a/source/blender/blenloader/tests/blendfile_loading_base_test.cc +++ b/source/blender/blenloader/tests/blendfile_loading_base_test.cc @@ -123,7 +123,8 @@ bool BlendfileLoadingBaseTest::blendfile_load(const char *filepath) char abspath[FILENAME_MAX]; BLI_path_join(abspath, sizeof(abspath), test_assets_dir.c_str(), filepath, NULL); - bfile = BLO_read_from_file(abspath, BLO_READ_SKIP_NONE, nullptr /* reports */); + BlendFileReadReport bf_reports = {NULL}; + bfile = BLO_read_from_file(abspath, BLO_READ_SKIP_NONE, &bf_reports); if (bfile == nullptr) { ADD_FAILURE() << "Unable to load file '" << filepath << "' from test assets dir '" << test_assets_dir << "'"; diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 37a32164cfc..e43000d3f64 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -2894,7 +2894,7 @@ static int filelist_readjob_list_lib(const char *root, ListBase *entries, const } /* there we go */ - libfiledata = BLO_blendhandle_from_file(dir, NULL); + libfiledata = BLO_blendhandle_from_file(dir, &(BlendFileReadReport){.reports = NULL}); if (libfiledata == NULL) { return nbr_entries; } diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index f809bb13b42..d59d04b6ac2 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -86,6 +86,8 @@ #include "UI_resources.h" #include "UI_view2d.h" +#include "../../blender/blenloader/BLO_readfile.h" + #include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" @@ -930,8 +932,14 @@ static void id_override_library_resync_fn(bContext *C, te->store_elem->id->tag |= LIB_TAG_DOIT; } - BKE_lib_override_library_resync( - bmain, scene, CTX_data_view_layer(C), id_root, NULL, do_hierarchy_enforce, true, reports); + BKE_lib_override_library_resync(bmain, + scene, + CTX_data_view_layer(C), + id_root, + NULL, + do_hierarchy_enforce, + true, + &(struct BlendFileReadReport){.reports = reports}); WM_event_add_notifier(C, NC_WINDOW, NULL); } diff --git a/source/blender/imbuf/intern/thumbs_blend.c b/source/blender/imbuf/intern/thumbs_blend.c index b7b31b3e56a..48e7f171bb4 100644 --- a/source/blender/imbuf/intern/thumbs_blend.c +++ b/source/blender/imbuf/intern/thumbs_blend.c @@ -47,7 +47,8 @@ ImBuf *IMB_thumb_load_blend(const char *blen_path, const char *blen_group, const if (blen_group && blen_id) { LinkNode *ln, *names, *lp, *previews = NULL; - struct BlendHandle *libfiledata = BLO_blendhandle_from_file(blen_path, NULL); + struct BlendHandle *libfiledata = BLO_blendhandle_from_file( + blen_path, &(BlendFileReadReport){.reports = NULL}); int idcode = BKE_idtype_idcode_from_name(blen_group); int i, nprevs, nnames; diff --git a/source/blender/python/intern/bpy_library_load.c b/source/blender/python/intern/bpy_library_load.c index 7a688b8c77d..5f97e11b412 100644 --- a/source/blender/python/intern/bpy_library_load.c +++ b/source/blender/python/intern/bpy_library_load.c @@ -258,7 +258,8 @@ static PyObject *bpy_lib_enter(BPy_Library *self) BKE_reports_init(&reports, RPT_STORE); - self->blo_handle = BLO_blendhandle_from_file(self->abspath, &reports); + self->blo_handle = BLO_blendhandle_from_file(self->abspath, + &(BlendFileReadReport){.reports = &reports}); if (self->blo_handle == NULL) { if (BPy_reports_to_error(&reports, PyExc_IOError, true) != -1) { diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 93a62bb5831..d165f8c37d5 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -52,12 +52,15 @@ #include "BLI_blenlib.h" #include "BLI_fileops_types.h" #include "BLI_linklist.h" +#include "BLI_math.h" #include "BLI_system.h" #include "BLI_threads.h" #include "BLI_timer.h" #include "BLI_utildefines.h" #include BLI_SYSTEM_PID_H +#include "PIL_time.h" + #include "BLT_translation.h" #include "BLF_api.h" @@ -733,6 +736,97 @@ static void wm_file_read_post(bContext *C, /** \name Read Main Blend-File API * \{ */ +static void file_read_reports_finalize(BlendFileReadReport *bf_reports) +{ + double duration_whole_minutes, duration_whole_seconds; + double duration_libraries_minutes, duration_libraries_seconds; + double duration_lib_override_minutes, duration_lib_override_seconds; + double duration_lib_override_resync_minutes, duration_lib_override_resync_seconds; + double duration_lib_override_recursive_resync_minutes, + duration_lib_override_recursive_resync_seconds; + + BLI_math_time_seconds_decompose(bf_reports->duration.whole, + NULL, + NULL, + &duration_whole_minutes, + &duration_whole_seconds, + NULL); + BLI_math_time_seconds_decompose(bf_reports->duration.libraries, + NULL, + NULL, + &duration_libraries_minutes, + &duration_libraries_seconds, + NULL); + BLI_math_time_seconds_decompose(bf_reports->duration.lib_overrides, + NULL, + NULL, + &duration_lib_override_minutes, + &duration_lib_override_seconds, + NULL); + BLI_math_time_seconds_decompose(bf_reports->duration.lib_overrides_resync, + NULL, + NULL, + &duration_lib_override_resync_minutes, + &duration_lib_override_resync_seconds, + NULL); + BLI_math_time_seconds_decompose(bf_reports->duration.lib_overrides_recursive_resync, + NULL, + NULL, + &duration_lib_override_recursive_resync_minutes, + &duration_lib_override_recursive_resync_seconds, + NULL); + + CLOG_INFO( + &LOG, 0, "Blender file read in %.0fm%.2fs", duration_whole_minutes, duration_whole_seconds); + CLOG_INFO(&LOG, + 0, + " * Loading libraries: %.0fm%.2fs", + duration_libraries_minutes, + duration_libraries_seconds); + CLOG_INFO(&LOG, + 0, + " * Applying overrides: %.0fm%.2fs", + duration_lib_override_minutes, + duration_lib_override_seconds); + CLOG_INFO(&LOG, + 0, + " * Resyncing overrides: %.0fm%.2fs (%d root overrides), including recursive " + "resyncs: %.0fm%.2fs)", + duration_lib_override_resync_minutes, + duration_lib_override_resync_seconds, + bf_reports->count.resynced_lib_overrides, + duration_lib_override_recursive_resync_minutes, + duration_lib_override_recursive_resync_seconds); + if (bf_reports->resynced_lib_overrides_libraries_count != 0) { + for (LinkNode *node_lib = bf_reports->resynced_lib_overrides_libraries; node_lib != NULL; + node_lib = node_lib->next) { + Library *library = node_lib->link; + BKE_reportf( + bf_reports->reports, RPT_INFO, "Library %s needs overrides resync.", library->filepath); + } + } + if (bf_reports->count.missing_libraries != 0 || bf_reports->count.missing_linked_id != 0) { + BKE_reportf(bf_reports->reports, + RPT_WARNING, + "%d libraries and %d linked data-blocks are missing, please check the " + "Info and Outliner editors for details", + bf_reports->count.missing_libraries, + bf_reports->count.missing_linked_id); + } + if (bf_reports->resynced_lib_overrides_libraries_count != 0) { + BKE_reportf(bf_reports->reports, + RPT_WARNING, + "%d libraries have overrides needing resync (auto resynced in %.0fm%.2fs), " + "please check the Info editor for details", + bf_reports->resynced_lib_overrides_libraries_count, + duration_lib_override_recursive_resync_minutes, + duration_lib_override_recursive_resync_seconds); + } + + BLI_linklist_free(bf_reports->resynced_lib_overrides_libraries, NULL); + bf_reports->resynced_lib_overrides_libraries = NULL; +} + bool WM_file_read(bContext *C, const char *filepath, ReportList *reports) { /* assume automated tasks with background, don't write recent file list */ @@ -763,7 +857,9 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports) .skip_flags = BLO_READ_SKIP_USERDEF, }; - struct BlendFileData *bfd = BKE_blendfile_read(filepath, ¶ms, reports); + BlendFileReadReport bf_reports = {.reports = reports, + .duration.whole = PIL_check_seconds_timer()}; + struct BlendFileData *bfd = BKE_blendfile_read(filepath, ¶ms, &bf_reports); if (bfd != NULL) { wm_file_read_pre(C, use_data, use_userdef); @@ -776,7 +872,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports) * need to re-enable it here else drivers and registered scripts won't work. */ const int G_f_orig = G.f; - BKE_blendfile_read_setup(C, bfd, ¶ms, reports); + BKE_blendfile_read_setup(C, bfd, ¶ms, &bf_reports); if (G.f != G_f_orig) { const int flags_keep = G_FLAG_ALL_RUNTIME; @@ -807,6 +903,9 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports) wm_file_read_post(C, false, false, use_data, use_userdef, false); + bf_reports.duration.whole = PIL_check_seconds_timer() - bf_reports.duration.whole; + file_read_reports_finalize(&bf_reports); + success = true; } } @@ -1087,10 +1186,15 @@ void wm_homefile_read(bContext *C, .skip_flags = skip_flags | BLO_READ_SKIP_USERDEF, }; - struct BlendFileData *bfd = BKE_blendfile_read(filepath_startup, ¶ms, NULL); + struct BlendFileData *bfd = BKE_blendfile_read( + filepath_startup, ¶ms, &(BlendFileReadReport){NULL}); if (bfd != NULL) { - BKE_blendfile_read_setup_ex( - C, bfd, ¶ms, NULL, update_defaults && use_data, app_template); + BKE_blendfile_read_setup_ex(C, + bfd, + ¶ms, + &(BlendFileReadReport){NULL}, + update_defaults && use_data, + app_template); success = true; } } @@ -1120,7 +1224,7 @@ void wm_homefile_read(bContext *C, struct BlendFileData *bfd = BKE_blendfile_read_from_memory( datatoc_startup_blend, datatoc_startup_blend_size, ¶ms, NULL); if (bfd != NULL) { - BKE_blendfile_read_setup_ex(C, bfd, ¶ms, NULL, true, NULL); + BKE_blendfile_read_setup_ex(C, bfd, ¶ms, &(BlendFileReadReport){NULL}, true, NULL); success = true; } diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c index c1c5eac8382..f938c507818 100644 --- a/source/blender/windowmanager/intern/wm_files_link.c +++ b/source/blender/windowmanager/intern/wm_files_link.c @@ -244,7 +244,7 @@ static void wm_link_do(WMLinkAppendData *lapp_data, bh = BLO_blendhandle_from_memory(datatoc_startup_blend, datatoc_startup_blend_size); } else { - bh = BLO_blendhandle_from_file(libname, reports); + bh = BLO_blendhandle_from_file(libname, &(BlendFileReadReport){.reports = reports}); } if (bh == NULL) { |