diff --git a/source/blender/editors/space_file/file_draw.cc b/source/blender/editors/space_file/file_draw.cc index 80ab76a11c7..e6c53bf8b98 100644 --- a/source/blender/editors/space_file/file_draw.cc +++ b/source/blender/editors/space_file/file_draw.cc @@ -26,6 +26,7 @@ #include "BKE_blendfile.h" #include "BKE_context.h" +#include "BKE_report.h" #include "BLT_translation.h" @@ -1177,12 +1178,11 @@ void file_draw_list(const bContext *C, ARegion *region) layout->curr_size = params->thumbnail_size; } -static void file_draw_invalid_library_hint(const bContext *C, - const SpaceFile *sfile, - ARegion *region) +static void file_draw_invalid_asset_library_hint(const bContext *C, + const SpaceFile *sfile, + ARegion *region, + FileAssetSelectParams *asset_params) { - const FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile); - char library_ui_path[PATH_MAX]; file_path_to_ui_path(asset_params->base_params.dir, library_ui_path, sizeof(library_ui_path)); @@ -1237,21 +1237,112 @@ static void file_draw_invalid_library_hint(const bContext *C, } } +static void file_draw_invalid_library_hint(const bContext * /*C*/, + const SpaceFile *sfile, + ARegion *region, + const char *blendfile_path, + ReportList *reports) +{ + uchar text_col[4]; + UI_GetThemeColor4ubv(TH_TEXT, text_col); + + const View2D *v2d = ®ion->v2d; + const int pad = sfile->layout->tile_border_x; + const int width = BLI_rctf_size_x(&v2d->tot) - (2 * pad); + const int line_height = sfile->layout->textheight; + int sx = v2d->tot.xmin + pad; + /* For some reason no padding needed. */ + int sy = v2d->tot.ymax; + + { + const char *message = TIP_("Unreadable Blender library file:"); + file_draw_string_multiline(sx, sy, message, width, line_height, text_col, nullptr, &sy); + + sy -= line_height; + file_draw_string(sx, sy, blendfile_path, width, line_height, UI_STYLE_TEXT_LEFT, text_col); + } + + /* Separate a bit further. */ + sy -= line_height * 2.2f; + + LISTBASE_FOREACH (Report *, report, &reports->list) { + const short report_type = report->type; + if (report_type <= RPT_INFO) { + continue; + } + + int icon = ICON_INFO; + if (report_type > RPT_WARNING) { + icon = ICON_ERROR; + } + UI_icon_draw(sx, sy - UI_UNIT_Y, icon); + + file_draw_string_multiline(sx + UI_UNIT_X, + sy, + TIP_(report->message), + width - UI_UNIT_X, + line_height, + text_col, + nullptr, + &sy); + sy -= line_height; + } +} + bool file_draw_hint_if_invalid(const bContext *C, const SpaceFile *sfile, ARegion *region) { - FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile); - /* Only for asset browser. */ - if (!ED_fileselect_is_asset_browser(sfile)) { - return false; - } - /* Check if the library exists. */ - if ((asset_params->asset_library_ref.type == ASSET_LIBRARY_LOCAL) || - filelist_is_dir(sfile->files, asset_params->base_params.dir)) - { - return false; + char blendfile_path[FILE_MAX_LIBEXTRA]; + const bool is_asset_browser = ED_fileselect_is_asset_browser(sfile); + const bool is_library_browser = !is_asset_browser && + filelist_islibrary(sfile->files, blendfile_path, nullptr); + + if (is_asset_browser) { + FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile); + + /* Check if the asset library exists. */ + if (!((asset_params->asset_library_ref.type == ASSET_LIBRARY_LOCAL) || + filelist_is_dir(sfile->files, asset_params->base_params.dir))) + { + file_draw_invalid_asset_library_hint(C, sfile, region, asset_params); + return true; + } } - file_draw_invalid_library_hint(C, sfile, region); + /* Check if the blendfile library is valid (has entries). */ + if (is_library_browser) { + if (!filelist_is_ready(sfile->files)) { + return false; + } - return true; + const int numfiles = filelist_files_num_entries(sfile->files); + if (numfiles > 0) { + return false; + } + + /* This could all be part of the file-list loading: + * - When loading fails this could be saved in the file-list, e.g. when + * `BLO_blendhandle_from_file()` returns null in `filelist_readjob_list_lib()`, a + * `FL_HAS_INVALID_LIBRARY` file-list flag could be set. + * - Reports from it could also be stored in `FileList` rather than being ignored + * (`RPT_STORE` must be set!). + * - Then we could just check for `is_library_browser` and the `FL_HAS_INVALID_LIBRARY` flag + * here, and draw the hint with the reports in the file-list. (We would not draw a hint for + * recursive loading, even if the file-list has the "has invalid library" flag set, which + * seems like the wanted behavior.) + * - The call to BKE_blendfile_is_readable() would not be needed then. + */ + if (!sfile->runtime->is_blendfile_status_set) { + BKE_reports_clear(&sfile->runtime->is_blendfile_readable_reports); + sfile->runtime->is_blendfile_readable = BKE_blendfile_is_readable( + blendfile_path, &sfile->runtime->is_blendfile_readable_reports); + sfile->runtime->is_blendfile_status_set = true; + } + if (!sfile->runtime->is_blendfile_readable) { + file_draw_invalid_library_hint( + C, sfile, region, blendfile_path, &sfile->runtime->is_blendfile_readable_reports); + return true; + } + } + + return false; } diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index 7c7b339d5a3..a9353bb0797 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -9,6 +9,7 @@ #pragma once #include "DNA_space_types.h" +#include "DNA_windowmanager_types.h" #ifdef __cplusplus extern "C" { @@ -180,6 +181,12 @@ typedef struct SpaceFile_Runtime { * Use file_on_reload_callback_register() to register a callback. */ onReloadFn on_reload; onReloadFnData on_reload_custom_data; + + /* Indicates, if the current filepath is a blendfile library one, if its status has been checked, + * and if it is readable. */ + bool is_blendfile_status_set; + bool is_blendfile_readable; + ReportList is_blendfile_readable_reports; } SpaceFile_Runtime; /** diff --git a/source/blender/editors/space_file/filelist.cc b/source/blender/editors/space_file/filelist.cc index 9fb94c518f8..2814574604e 100644 --- a/source/blender/editors/space_file/filelist.cc +++ b/source/blender/editors/space_file/filelist.cc @@ -1961,6 +1961,11 @@ BlendHandle *filelist_lib(FileList *filelist) return filelist->libfiledata; } +int filelist_files_num_entries(FileList *filelist) +{ + return filelist->filelist.entries_num; +} + static const char *fileentry_uiname(const char *root, FileListInternEntry *entry, char *buff) { if (entry->asset) { diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h index 56a9e3445d9..3b263e89035 100644 --- a/source/blender/editors/space_file/filelist.h +++ b/source/blender/editors/space_file/filelist.h @@ -206,6 +206,10 @@ struct BlendHandle *filelist_lib(struct FileList *filelist); bool filelist_islibrary(struct FileList *filelist, char *dir, char **r_group); void filelist_freelib(struct FileList *filelist); +/** Return the total raw number of entries listed in the given `filelist`, whether they are + * filtered out or not. */ +int filelist_files_num_entries(struct FileList *filelist); + void filelist_readjob_start(struct FileList *filelist, int space_notifier, const struct bContext *C); diff --git a/source/blender/editors/space_file/space_file.cc b/source/blender/editors/space_file/space_file.cc index a3e07776129..c057779bebc 100644 --- a/source/blender/editors/space_file/space_file.cc +++ b/source/blender/editors/space_file/space_file.cc @@ -20,6 +20,7 @@ #include "BKE_global.h" #include "BKE_lib_remap.h" #include "BKE_main.h" +#include "BKE_report.h" #include "BKE_screen.h" #include "RNA_access.h" @@ -126,6 +127,9 @@ static void file_free(SpaceLink *sl) MEM_SAFE_FREE(sfile->params); MEM_SAFE_FREE(sfile->asset_params); + if (sfile->runtime != nullptr) { + BKE_reports_clear(&sfile->runtime->is_blendfile_readable_reports); + } MEM_SAFE_FREE(sfile->runtime); MEM_SAFE_FREE(sfile->layout); @@ -143,6 +147,7 @@ static void file_init(wmWindowManager * /*wm*/, ScrArea *area) if (sfile->runtime == nullptr) { sfile->runtime = static_cast( MEM_callocN(sizeof(*sfile->runtime), __func__)); + BKE_reports_init(&sfile->runtime->is_blendfile_readable_reports, RPT_STORE); } /* Validate the params right after file read. */ fileselect_refresh_params(sfile); @@ -206,6 +211,10 @@ static void file_refresh(const bContext *C, ScrArea *area) fileselect_refresh_params(sfile); folder_history_list_ensure_for_active_browse_mode(sfile); + if (sfile->runtime != nullptr) { + sfile->runtime->is_blendfile_status_set = false; + } + if (sfile->files && (sfile->tags & FILE_TAG_REBUILD_MAIN_FILES) && filelist_needs_reset_on_main_changes(sfile->files)) {