From f2a800886917a183e5d6de5428233e567ca9644b Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 19 Jan 2024 19:16:25 +0100 Subject: [PATCH 1/3] Protoype to report/confirm overwrite of 'library' blendfiles. This commit extends the reporting and overwrite confirmation system created for blendfiles saved by later Blender version, to also detect and handle 'library' blendfiles (typically saved by partial-write API, they do not have a defined current Screen or Scene in their global data). the implementation details are fairly straightforward, but this commit raises some design questions: * Do we care reporting in the status bar about the 'library blendfile' case? Unlike opening a more recent blender version blendfile, opening a library file has no loss of data. * When both issues are present (and potentially more in the future), do we want a merged info of all present issues, or do we define some sort of priority order, and only report the highest priority issue? As it is right now, this commit can make both the status bar tooltip, and the overwrite confirmation popup, fairly busy... Obviously, naming and UI messages are also open for discussion. --- source/blender/blenkernel/BKE_main.hh | 21 +++ source/blender/blenkernel/intern/blendfile.cc | 1 + source/blender/blenkernel/intern/main.cc | 10 ++ .../editors/interface/interface_templates.cc | 133 +++++++++++------ .../blender/windowmanager/intern/wm_files.cc | 141 +++++++++++------- source/blender/windowmanager/wm_files.hh | 2 +- 6 files changed, 202 insertions(+), 106 deletions(-) diff --git a/source/blender/blenkernel/BKE_main.hh b/source/blender/blenkernel/BKE_main.hh index 174eb7dec05..35f280a74f5 100644 --- a/source/blender/blenkernel/BKE_main.hh +++ b/source/blender/blenkernel/BKE_main.hh @@ -142,6 +142,16 @@ struct Main { * could try to use more refined detection on load. */ bool has_forward_compatibility_issues; + /** + * The currently opened .blend file was 'partial-written' (it does not contain some typical data + * required for a complete normal blendfile, like a current screen and current scene...). + * + * This is used to warn the user when they try to save it from Blender UI, since they are likely + * overwriting a file generated (and potentially managed) by some tool, e.g. some asset library + * file. + */ + bool is_data_only; + /** Commit timestamp from `buildinfo`. */ uint64_t build_commit_timestamp; /** Commit Hash from `buildinfo`. */ @@ -299,6 +309,17 @@ void BKE_main_merge(Main *bmain_dst, Main **r_bmain_src, MainMergeReport &report */ bool BKE_main_is_empty(Main *bmain); +/** + * Check whether the bmain has issues, e.g. for reporting in the status bar. + */ +bool BKE_main_has_issues(const Main *bmain); + +/** + * Check whether user confirmation should be required when overwriting this `bmain` into its source + * blendfile. + */ +bool BKE_main_needs_overwrite_confirm(const Main *bmain); + void BKE_main_lock(Main *bmain); void BKE_main_unlock(Main *bmain); diff --git a/source/blender/blenkernel/intern/blendfile.cc b/source/blender/blenkernel/intern/blendfile.cc index 103f740703a..f17e13803bb 100644 --- a/source/blender/blenkernel/intern/blendfile.cc +++ b/source/blender/blenkernel/intern/blendfile.cc @@ -854,6 +854,7 @@ static void setup_app_data(bContext *C, * nullptr curscreen)... */ else if (ELEM(nullptr, bfd->curscreen, bfd->curscene)) { BKE_report(reports->reports, RPT_WARNING, "Library file, loading empty scene"); + bfd->main->is_data_only = true; mode = LOAD_UI_OFF; } else if (G.fileflags & G_FILE_NO_UI) { diff --git a/source/blender/blenkernel/intern/main.cc b/source/blender/blenkernel/intern/main.cc index 186b3d98e85..ed461a4665b 100644 --- a/source/blender/blenkernel/intern/main.cc +++ b/source/blender/blenkernel/intern/main.cc @@ -444,6 +444,16 @@ bool BKE_main_is_empty(Main *bmain) return result; } +bool BKE_main_has_issues(const Main *bmain) +{ + return bmain->has_forward_compatibility_issues || bmain->is_data_only; +} + +bool BKE_main_needs_overwrite_confirm(const Main *bmain) +{ + return bmain->has_forward_compatibility_issues || bmain->is_data_only; +} + void BKE_main_lock(Main *bmain) { BLI_spin_lock((SpinLock *)bmain->lock); diff --git a/source/blender/editors/interface/interface_templates.cc b/source/blender/editors/interface/interface_templates.cc index c7a1f6616ec..66817a2cc41 100644 --- a/source/blender/editors/interface/interface_templates.cc +++ b/source/blender/editors/interface/interface_templates.cc @@ -11,6 +11,8 @@ #include #include +#include "fmt/format.h" + #include "MEM_guardedalloc.h" #include "DNA_brush_types.h" @@ -6556,13 +6558,46 @@ void uiTemplateInputStatus(uiLayout *layout, bContext *C) } } +static void ui_template_status_info_warnings_messages(Main *bmain, + Scene *scene, + ViewLayer *view_layer, + std::string &warning_message, + std::string ®ular_message, + std::string &tooltip_message) +{ + tooltip_message = ""; + char statusbar_info_flag = U.statusbar_flag; + + if (bmain->has_forward_compatibility_issues) { + warning_message = ED_info_statusbar_string_ex( + bmain, scene, view_layer, STATUSBAR_SHOW_VERSION); + statusbar_info_flag &= ~STATUSBAR_SHOW_VERSION; + + char writer_ver_str[12]; + BKE_blender_version_blendfile_string_from_values( + writer_ver_str, sizeof(writer_ver_str), bmain->versionfile, -1); + tooltip_message += fmt::format(RPT_("File saved by newer Blender\n({}), expect loss of data"), + writer_ver_str); + } + if (bmain->is_data_only) { + if (!tooltip_message.empty()) { + tooltip_message += "\n\n"; + } + tooltip_message += RPT_( + "Not a regular Blender file, overwriting it\nmay break its handling by tools like the " + "Assets system"); + } + + regular_message = ED_info_statusbar_string_ex(bmain, scene, view_layer, statusbar_info_flag); +} + void uiTemplateStatusInfo(uiLayout *layout, bContext *C) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - if (!bmain->has_forward_compatibility_issues) { + if (!BKE_main_has_issues(bmain)) { const char *status_info_txt = ED_info_statusbar_string(bmain, scene, view_layer); uiItemL(layout, status_info_txt, ICON_NONE); return; @@ -6571,13 +6606,13 @@ void uiTemplateStatusInfo(uiLayout *layout, bContext *C) /* Blender version part is shown as warning area when there are forward compatibility issues with * currently loaded .blend file. */ - const char *status_info_txt = ED_info_statusbar_string_ex( - bmain, scene, view_layer, (U.statusbar_flag & ~STATUSBAR_SHOW_VERSION)); - uiItemL(layout, status_info_txt, ICON_NONE); + std::string warning_message; + std::string regular_message; + std::string tooltip_message; + ui_template_status_info_warnings_messages( + bmain, scene, view_layer, warning_message, regular_message, tooltip_message); - status_info_txt = ED_info_statusbar_string_ex(bmain, scene, view_layer, STATUSBAR_SHOW_VERSION); - - uiBut *but; + uiItemL(layout, regular_message.c_str(), ICON_NONE); const uiStyle *style = UI_style_get(); uiLayout *ui_abs = uiLayoutAbsolute(layout, false); @@ -6585,27 +6620,28 @@ void uiTemplateStatusInfo(uiLayout *layout, bContext *C) eUIEmbossType previous_emboss = UI_block_emboss_get(block); UI_fontstyle_set(&style->widgetlabel); - int width = int( - BLF_width(style->widgetlabel.uifont_id, status_info_txt, strlen(status_info_txt))); - width = max_ii(width, int(10 * UI_SCALE_FAC)); + const int width = max_ii(int(BLF_width(style->widgetlabel.uifont_id, + warning_message.c_str(), + warning_message.length())), + int(10 * UI_SCALE_FAC)); UI_block_align_begin(block); /* Background for icon. */ - but = uiDefBut(block, - UI_BTYPE_ROUNDBOX, - 0, - "", - 0, - 0, - UI_UNIT_X + (6 * UI_SCALE_FAC), - UI_UNIT_Y, - nullptr, - 0.0f, - 0.0f, - 0, - 0, - ""); + uiBut *but = uiDefBut(block, + UI_BTYPE_ROUNDBOX, + 0, + "", + 0, + 0, + UI_UNIT_X + (6 * UI_SCALE_FAC), + UI_UNIT_Y, + nullptr, + 0.0f, + 0.0f, + 0, + 0, + ""); /* UI_BTYPE_ROUNDBOX's bg color is set in but->col. */ UI_GetThemeColorType4ubv(TH_INFO_WARNING, SPACE_INFO, but->col); @@ -6632,14 +6668,13 @@ void uiTemplateStatusInfo(uiLayout *layout, bContext *C) UI_block_align_end(block); UI_block_emboss_set(block, UI_EMBOSS_NONE); - /* The report icon itself. */ - static char compat_error_msg[256]; - char writer_ver_str[12]; - BKE_blender_version_blendfile_string_from_values( - writer_ver_str, sizeof(writer_ver_str), bmain->versionfile, -1); - SNPRINTF(compat_error_msg, - RPT_("File saved by newer Blender\n(%s), expect loss of data"), - writer_ver_str); + /* Tool tips have to be static currently. + * FIXME This is a horrible requirement from uiBut, should probably just store an std::string for + * the tooltip as well? */ + static char tooltip_static_storage[256]; + BLI_strncpy(tooltip_static_storage, tooltip_message.c_str(), sizeof(tooltip_static_storage)); + + /* The warning icon itself. */ but = uiDefIconBut(block, UI_BTYPE_BUT, 0, @@ -6653,25 +6688,27 @@ void uiTemplateStatusInfo(uiLayout *layout, bContext *C) 0.0f, 0.0f, 0.0f, - compat_error_msg); + tooltip_static_storage); UI_GetThemeColorType4ubv(TH_INFO_WARNING_TEXT, SPACE_INFO, but->col); but->col[3] = 255; /* This theme color is RBG only, so have to set alpha here. */ - /* The report message. */ - but = uiDefBut(block, - UI_BTYPE_BUT, - 0, - status_info_txt, - UI_UNIT_X, - 0, - short(width + UI_UNIT_X), - UI_UNIT_Y, - nullptr, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - compat_error_msg); + /* The warning message, if any. */ + if (!warning_message.empty()) { + but = uiDefBut(block, + UI_BTYPE_BUT, + 0, + warning_message.c_str(), + UI_UNIT_X, + 0, + short(width + UI_UNIT_X), + UI_UNIT_Y, + nullptr, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + tooltip_static_storage); + } UI_block_emboss_set(block, previous_emboss); } diff --git a/source/blender/windowmanager/intern/wm_files.cc b/source/blender/windowmanager/intern/wm_files.cc index 24594ce224c..63bcf633795 100644 --- a/source/blender/windowmanager/intern/wm_files.cc +++ b/source/blender/windowmanager/intern/wm_files.cc @@ -3548,8 +3548,8 @@ static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent * } if (blendfile_path[0] != '\0') { - if (CTX_data_main(C)->has_forward_compatibility_issues) { - wm_save_file_forwardcompat_dialog(C, op); + if (BKE_main_needs_overwrite_confirm(CTX_data_main(C))) { + wm_save_file_overwrite_dialog(C, op); ret = OPERATOR_INTERFACE; } else { @@ -3903,49 +3903,62 @@ static void wm_free_operator_properties_callback(void *user_data) IDP_FreeProperty(properties); } -static const char *save_file_forwardcompat_dialog_name = "save_file_forwardcompat_popup"; +static const char *save_file_overwrite_dialog_name = "save_file_overwrite_popup"; -static void file_forwardcompat_detailed_info_show(uiLayout *parent_layout, Main *bmain) +static void file_overwrite_detailed_info_show(uiLayout *parent_layout, Main *bmain) { uiLayout *layout = uiLayoutColumn(parent_layout, true); /* Trick to make both lines of text below close enough to look like they are part of a same * block. */ uiLayoutSetScaleY(layout, 0.70f); - char writer_ver_str[16]; - char current_ver_str[16]; - if (bmain->versionfile == BLENDER_VERSION) { - BKE_blender_version_blendfile_string_from_values( - writer_ver_str, sizeof(writer_ver_str), bmain->versionfile, bmain->subversionfile); - BKE_blender_version_blendfile_string_from_values( - current_ver_str, sizeof(current_ver_str), BLENDER_FILE_VERSION, BLENDER_FILE_SUBVERSION); - } - else { - BKE_blender_version_blendfile_string_from_values( - writer_ver_str, sizeof(writer_ver_str), bmain->versionfile, -1); - BKE_blender_version_blendfile_string_from_values( - current_ver_str, sizeof(current_ver_str), BLENDER_VERSION, -1); + if (bmain->has_forward_compatibility_issues) { + char writer_ver_str[16]; + char current_ver_str[16]; + if (bmain->versionfile == BLENDER_VERSION) { + BKE_blender_version_blendfile_string_from_values( + writer_ver_str, sizeof(writer_ver_str), bmain->versionfile, bmain->subversionfile); + BKE_blender_version_blendfile_string_from_values( + current_ver_str, sizeof(current_ver_str), BLENDER_FILE_VERSION, BLENDER_FILE_SUBVERSION); + } + else { + BKE_blender_version_blendfile_string_from_values( + writer_ver_str, sizeof(writer_ver_str), bmain->versionfile, -1); + BKE_blender_version_blendfile_string_from_values( + current_ver_str, sizeof(current_ver_str), BLENDER_VERSION, -1); + } + + char message_line1[256]; + char message_line2[256]; + SNPRINTF(message_line1, + RPT_("This file was saved by a newer version of Blender (%s)"), + writer_ver_str); + SNPRINTF(message_line2, + RPT_("Saving it with this Blender (%s) may cause loss of data"), + current_ver_str); + uiItemL(layout, message_line1, ICON_NONE); + uiItemL(layout, message_line2, ICON_NONE); } - char message_line1[256]; - char message_line2[256]; - SNPRINTF(message_line1, - RPT_("This file was saved by a newer version of Blender (%s)"), - writer_ver_str); - SNPRINTF(message_line2, - RPT_("Saving it with this Blender (%s) may cause loss of data"), - current_ver_str); - uiItemL(layout, message_line1, ICON_NONE); - uiItemL(layout, message_line2, ICON_NONE); + if (bmain->is_data_only) { + if (bmain->has_forward_compatibility_issues) { + uiItemS_ex(layout, 1.4f); + } + + uiItemL(layout, RPT_("This file was detected as a Library file"), ICON_NONE); + uiItemL( + layout, RPT_("It was likely generated by the asset system, or similar tool"), ICON_NONE); + uiItemL(layout, RPT_("Overwriting it may prevent its management by that tool"), ICON_NONE); + } } -static void save_file_forwardcompat_cancel(bContext *C, void *arg_block, void * /*arg_data*/) +static void save_file_overwrite_cancel(bContext *C, void *arg_block, void * /*arg_data*/) { wmWindow *win = CTX_wm_window(C); UI_popup_block_close(C, win, static_cast(arg_block)); } -static void save_file_forwardcompat_cancel_button(uiBlock *block, wmGenericCallback *post_action) +static void save_file_overwrite_cancel_button(uiBlock *block, wmGenericCallback *post_action) { uiBut *but = uiDefIconTextBut(block, UI_BTYPE_BUT, @@ -3962,11 +3975,11 @@ static void save_file_forwardcompat_cancel_button(uiBlock *block, wmGenericCallb 0, 0, ""); - UI_but_func_set(but, save_file_forwardcompat_cancel, block, post_action); + UI_but_func_set(but, save_file_overwrite_cancel, block, post_action); UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT); } -static void save_file_forwardcompat_overwrite(bContext *C, void *arg_block, void *arg_data) +static void save_file_overwrite_confirm(bContext *C, void *arg_block, void *arg_data) { wmWindow *win = CTX_wm_window(C); @@ -3989,8 +4002,7 @@ static void save_file_forwardcompat_overwrite(bContext *C, void *arg_block, void WM_generic_callback_free(callback); } -static void save_file_forwardcompat_overwrite_button(uiBlock *block, - wmGenericCallback *post_action) +static void save_file_overwrite_confirm_button(uiBlock *block, wmGenericCallback *post_action) { uiBut *but = uiDefIconTextBut(block, UI_BTYPE_BUT, @@ -4007,12 +4019,12 @@ static void save_file_forwardcompat_overwrite_button(uiBlock *block, 0, 0, ""); - UI_but_func_set(but, save_file_forwardcompat_overwrite, block, post_action); + UI_but_func_set(but, save_file_overwrite_confirm, block, post_action); UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT); UI_but_flag_enable(but, UI_BUT_REDALERT); } -static void save_file_forwardcompat_saveas(bContext *C, void *arg_block, void * /*arg_data*/) +static void save_file_overwrite_saveas(bContext *C, void *arg_block, void * /*arg_data*/) { wmWindow *win = CTX_wm_window(C); UI_popup_block_close(C, win, static_cast(arg_block)); @@ -4020,7 +4032,7 @@ static void save_file_forwardcompat_saveas(bContext *C, void *arg_block, void * WM_operator_name_call(C, "WM_OT_save_as_mainfile", WM_OP_INVOKE_DEFAULT, nullptr, nullptr); } -static void save_file_forwardcompat_saveas_button(uiBlock *block, wmGenericCallback *post_action) +static void save_file_overwrite_saveas_button(uiBlock *block, wmGenericCallback *post_action) { uiBut *but = uiDefIconTextBut(block, UI_BTYPE_BUT, @@ -4037,19 +4049,17 @@ static void save_file_forwardcompat_saveas_button(uiBlock *block, wmGenericCallb 0, 0, ""); - UI_but_func_set(but, save_file_forwardcompat_saveas, block, post_action); + UI_but_func_set(but, save_file_overwrite_saveas, block, post_action); UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT); UI_but_flag_enable(but, UI_BUT_ACTIVE_DEFAULT); } -static uiBlock *block_create_save_file_forwardcompat_dialog(bContext *C, - ARegion *region, - void *arg1) +static uiBlock *block_create_save_file_overwrite_dialog(bContext *C, ARegion *region, void *arg1) { wmGenericCallback *post_action = static_cast(arg1); Main *bmain = CTX_data_main(C); - uiBlock *block = UI_block_begin(C, region, save_file_forwardcompat_dialog_name, UI_EMBOSS); + uiBlock *block = UI_block_begin(C, region, save_file_overwrite_dialog_name, UI_EMBOSS); UI_block_flag_enable( block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_LOOP | UI_BLOCK_NO_WIN_CLIP | UI_BLOCK_NUMSELECT); UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); @@ -4057,8 +4067,25 @@ static uiBlock *block_create_save_file_forwardcompat_dialog(bContext *C, uiLayout *layout = uiItemsAlertBox(block, 34, ALERT_ICON_WARNING); /* Title. */ - uiItemL_ex( - layout, RPT_("Overwrite file with an older Blender version?"), ICON_NONE, true, false); + if (bmain->has_forward_compatibility_issues) { + if (bmain->is_data_only) { + uiItemL_ex(layout, + RPT_("Overwrite library file with an older Blender version?"), + ICON_NONE, + true, + false); + } + else { + uiItemL_ex( + layout, RPT_("Overwrite file with an older Blender version?"), ICON_NONE, true, false); + } + } + else if (bmain->is_data_only) { + uiItemL_ex(layout, RPT_("Overwrite library file?"), ICON_NONE, true, false); + } + else { + BLI_assert_unreachable(); + } /* Filename. */ const char *blendfile_path = BKE_main_blendfile_path(CTX_data_main(C)); @@ -4075,7 +4102,7 @@ static uiBlock *block_create_save_file_forwardcompat_dialog(bContext *C, uiItemL(layout, filename, ICON_NONE); /* Detailed message info. */ - file_forwardcompat_detailed_info_show(layout, bmain); + file_overwrite_detailed_info_show(layout, bmain); uiItemS_ex(layout, 4.0f); @@ -4085,7 +4112,7 @@ static uiBlock *block_create_save_file_forwardcompat_dialog(bContext *C, uiLayoutSetScaleY(split, 1.2f); uiLayoutColumn(split, false); - save_file_forwardcompat_overwrite_button(block, post_action); + save_file_overwrite_confirm_button(block, post_action); uiLayout *split_right = uiLayoutSplit(split, 0.1f, true); @@ -4093,25 +4120,25 @@ static uiBlock *block_create_save_file_forwardcompat_dialog(bContext *C, /* Empty space. */ uiLayoutColumn(split_right, false); - save_file_forwardcompat_cancel_button(block, post_action); + save_file_overwrite_cancel_button(block, post_action); uiLayoutColumn(split_right, false); - save_file_forwardcompat_saveas_button(block, post_action); + save_file_overwrite_saveas_button(block, post_action); UI_block_bounds_set_centered(block, 14 * UI_SCALE_FAC); return block; } -void wm_save_file_forwardcompat_dialog(bContext *C, wmOperator *op) +void wm_save_file_overwrite_dialog(bContext *C, wmOperator *op) { - if (!UI_popup_block_name_exists(CTX_wm_screen(C), save_file_forwardcompat_dialog_name)) { + if (!UI_popup_block_name_exists(CTX_wm_screen(C), save_file_overwrite_dialog_name)) { wmGenericCallback *callback = MEM_cnew(__func__); callback->exec = nullptr; callback->user_data = IDP_CopyProperty(op->properties); callback->free_user_data = wm_free_operator_properties_callback; UI_popup_block_invoke( - C, block_create_save_file_forwardcompat_dialog, callback, free_post_file_close_action); + C, block_create_save_file_overwrite_dialog, callback, free_post_file_close_action); } } @@ -4241,7 +4268,7 @@ static void wm_block_file_close_discard_button(uiBlock *block, wmGenericCallback static void wm_block_file_close_save_button(uiBlock *block, wmGenericCallback *post_action, - const bool has_forwardcompat_issues) + const bool needs_overwrite_confirm) { uiBut *but = uiDefIconTextBut( block, @@ -4249,7 +4276,7 @@ static void wm_block_file_close_save_button(uiBlock *block, 0, ICON_NONE, /* Forward compatibility issues force using 'save as' operator instead of 'save' one. */ - has_forwardcompat_issues ? IFACE_("Save As...") : IFACE_("Save"), + needs_overwrite_confirm ? IFACE_("Save As...") : IFACE_("Save"), 0, 0, 0, @@ -4285,7 +4312,7 @@ static uiBlock *block_create__close_file_dialog(bContext *C, ARegion *region, vo uiLayout *layout = uiItemsAlertBox(block, 34, ALERT_ICON_QUESTION); - const bool has_forwardcompat_issues = bmain->has_forward_compatibility_issues; + const bool needs_overwrite_confirm = BKE_main_needs_overwrite_confirm(bmain); /* Title. */ uiItemL_ex(layout, RPT_("Save changes before closing?"), ICON_NONE, true, false); @@ -4302,8 +4329,8 @@ static uiBlock *block_create__close_file_dialog(bContext *C, ARegion *region, vo uiItemL(layout, filename, ICON_NONE); /* Potential forward compatibility issues message. */ - if (has_forwardcompat_issues) { - file_forwardcompat_detailed_info_show(layout, bmain); + if (needs_overwrite_confirm) { + file_overwrite_detailed_info_show(layout, bmain); } /* Image Saving Warnings. */ @@ -4412,7 +4439,7 @@ static uiBlock *block_create__close_file_dialog(bContext *C, ARegion *region, vo uiLayoutSetScaleY(split, 1.2f); uiLayoutColumn(split, false); - wm_block_file_close_save_button(block, post_action, has_forwardcompat_issues); + wm_block_file_close_save_button(block, post_action, needs_overwrite_confirm); uiLayoutColumn(split, false); wm_block_file_close_discard_button(block, post_action); @@ -4438,7 +4465,7 @@ static uiBlock *block_create__close_file_dialog(bContext *C, ARegion *region, vo wm_block_file_close_cancel_button(block, post_action); uiLayoutColumn(split_right, false); - wm_block_file_close_save_button(block, post_action, has_forwardcompat_issues); + wm_block_file_close_save_button(block, post_action, needs_overwrite_confirm); } UI_block_bounds_set_centered(block, 14 * UI_SCALE_FAC); diff --git a/source/blender/windowmanager/wm_files.hh b/source/blender/windowmanager/wm_files.hh index d62ef68dc27..26a63fcc65a 100644 --- a/source/blender/windowmanager/wm_files.hh +++ b/source/blender/windowmanager/wm_files.hh @@ -97,7 +97,7 @@ bool wm_file_or_session_data_has_unsaved_changes(const Main *bmain, const wmWind * * Important to ask confirmation, as this is a very common scenario of data loss. */ -void wm_save_file_forwardcompat_dialog(bContext *C, wmOperator *op); +void wm_save_file_overwrite_dialog(bContext *C, wmOperator *op); void WM_OT_save_homefile(wmOperatorType *ot); void WM_OT_save_userpref(wmOperatorType *ot); -- 2.30.2 From 97504185eb1160383582544228d7d23c1fbd92b8 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 23 Jan 2024 17:56:38 +0100 Subject: [PATCH 2/3] Update handling of 'data only' files from review. --- source/blender/blenkernel/BKE_blendfile.hh | 5 +++ source/blender/blenkernel/BKE_main.hh | 10 ++--- source/blender/blenkernel/intern/blendfile.cc | 4 +- source/blender/blenkernel/intern/main.cc | 4 +- .../editors/interface/interface_templates.cc | 4 +- .../blender/windowmanager/intern/wm_files.cc | 45 +++++++++++++------ 6 files changed, 48 insertions(+), 24 deletions(-) diff --git a/source/blender/blenkernel/BKE_blendfile.hh b/source/blender/blenkernel/BKE_blendfile.hh index cdc26d7776c..f55eb005817 100644 --- a/source/blender/blenkernel/BKE_blendfile.hh +++ b/source/blender/blenkernel/BKE_blendfile.hh @@ -19,6 +19,11 @@ struct ReportList; struct UserDef; struct WorkspaceConfigFileData; +/** + * The suffix used for blendfiles managed by the asset system. + */ +#define BLENDER_ASSET_FILE_SUFFIX ".asset.blend" + /** * Check whether given path ends with a blend file compatible extension * (`.blend`, `.ble` or `.blend.gz`). diff --git a/source/blender/blenkernel/BKE_main.hh b/source/blender/blenkernel/BKE_main.hh index 5c8e7ea4f27..89efb43e9d4 100644 --- a/source/blender/blenkernel/BKE_main.hh +++ b/source/blender/blenkernel/BKE_main.hh @@ -143,14 +143,12 @@ struct Main { bool has_forward_compatibility_issues; /** - * The currently opened .blend file was 'partial-written' (it does not contain some typical data - * required for a complete normal blendfile, like a current screen and current scene...). + * The currently opened .blend file was created as an asset library storage. * - * This is used to warn the user when they try to save it from Blender UI, since they are likely - * overwriting a file generated (and potentially managed) by some tool, e.g. some asset library - * file. + * This is used to warn the user when they try to save it from Blender UI, since this will likely + * break the automatic management from the asset library system. */ - bool is_data_only; + bool is_asset_repository; /** Commit timestamp from `buildinfo`. */ uint64_t build_commit_timestamp; diff --git a/source/blender/blenkernel/intern/blendfile.cc b/source/blender/blenkernel/intern/blendfile.cc index 06f334ccf69..f631f9252f5 100644 --- a/source/blender/blenkernel/intern/blendfile.cc +++ b/source/blender/blenkernel/intern/blendfile.cc @@ -853,7 +853,9 @@ static void setup_app_data(bContext *C, * nullptr curscreen)... */ else if (ELEM(nullptr, bfd->curscreen, bfd->curscene)) { BKE_report(reports->reports, RPT_WARNING, "Library file, loading empty scene"); - bfd->main->is_data_only = true; + if (blender::StringRefNull(bfd->main->filepath).endswith(BLENDER_ASSET_FILE_SUFFIX)) { + bfd->main->is_asset_repository = true; + } mode = LOAD_UI_OFF; } else if (G.fileflags & G_FILE_NO_UI) { diff --git a/source/blender/blenkernel/intern/main.cc b/source/blender/blenkernel/intern/main.cc index a66409efed2..373059a3c47 100644 --- a/source/blender/blenkernel/intern/main.cc +++ b/source/blender/blenkernel/intern/main.cc @@ -446,12 +446,12 @@ bool BKE_main_is_empty(Main *bmain) bool BKE_main_has_issues(const Main *bmain) { - return bmain->has_forward_compatibility_issues || bmain->is_data_only; + return bmain->has_forward_compatibility_issues || bmain->is_asset_repository; } bool BKE_main_needs_overwrite_confirm(const Main *bmain) { - return bmain->has_forward_compatibility_issues || bmain->is_data_only; + return bmain->has_forward_compatibility_issues || bmain->is_asset_repository; } void BKE_main_lock(Main *bmain) diff --git a/source/blender/editors/interface/interface_templates.cc b/source/blender/editors/interface/interface_templates.cc index c0717281b8e..d3d1f4f3a1a 100644 --- a/source/blender/editors/interface/interface_templates.cc +++ b/source/blender/editors/interface/interface_templates.cc @@ -6579,12 +6579,12 @@ static void ui_template_status_info_warnings_messages(Main *bmain, tooltip_message += fmt::format(RPT_("File saved by newer Blender\n({}), expect loss of data"), writer_ver_str); } - if (bmain->is_data_only) { + if (bmain->is_asset_repository) { if (!tooltip_message.empty()) { tooltip_message += "\n\n"; } tooltip_message += RPT_( - "Not a regular Blender file, overwriting it\nmay break its handling by tools like the " + "This is an Asset Library Blender file, overwriting it\nmay break its handling by the " "Assets system"); } diff --git a/source/blender/windowmanager/intern/wm_files.cc b/source/blender/windowmanager/intern/wm_files.cc index 4a4e10a1856..33ee1c4f356 100644 --- a/source/blender/windowmanager/intern/wm_files.cc +++ b/source/blender/windowmanager/intern/wm_files.cc @@ -3939,15 +3939,15 @@ static void file_overwrite_detailed_info_show(uiLayout *parent_layout, Main *bma uiItemL(layout, message_line2, ICON_NONE); } - if (bmain->is_data_only) { + if (bmain->is_asset_repository) { if (bmain->has_forward_compatibility_issues) { uiItemS_ex(layout, 1.4f); } - uiItemL(layout, RPT_("This file was detected as a Library file"), ICON_NONE); + uiItemL(layout, RPT_("This file is managed by the Blender asset system"), ICON_NONE); uiItemL( - layout, RPT_("It was likely generated by the asset system, or similar tool"), ICON_NONE); - uiItemL(layout, RPT_("Overwriting it may prevent its management by that tool"), ICON_NONE); + layout, RPT_("By overwriting it as a regular blend file, it will no longer "), ICON_NONE); + uiItemL(layout, RPT_("be possible to update its assets through the asset browser"), ICON_NONE); } } @@ -4025,10 +4025,27 @@ static void save_file_overwrite_confirm_button(uiBlock *block, wmGenericCallback static void save_file_overwrite_saveas(bContext *C, void *arg_block, void * /*arg_data*/) { + Main *bmain = CTX_data_main(C); wmWindow *win = CTX_wm_window(C); UI_popup_block_close(C, win, static_cast(arg_block)); - WM_operator_name_call(C, "WM_OT_save_as_mainfile", WM_OP_INVOKE_DEFAULT, nullptr, nullptr); + PointerRNA props_ptr; + wmOperatorType *ot = WM_operatortype_find("WM_OT_save_as_mainfile", false); + WM_operator_properties_create_ptr(&props_ptr, ot); + + if (bmain->is_asset_repository) { + /* If needed, substitute the 'proposed' Save As filepath by replacing the `.asset.blend` part + * of it by just `.blend`. */ + std::string filepath = BKE_main_blendfile_path(bmain); + if (blender::StringRef(filepath).endswith(BLENDER_ASSET_FILE_SUFFIX)) { + filepath.replace( + filepath.rfind(BLENDER_ASSET_FILE_SUFFIX), strlen(BLENDER_ASSET_FILE_SUFFIX), ".blend"); + RNA_string_set(&props_ptr, "filepath", filepath.c_str()); + } + } + + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr, nullptr); + WM_operator_properties_free(&props_ptr); } static void save_file_overwrite_saveas_button(uiBlock *block, wmGenericCallback *post_action) @@ -4067,20 +4084,22 @@ static uiBlock *block_create_save_file_overwrite_dialog(bContext *C, ARegion *re /* Title. */ if (bmain->has_forward_compatibility_issues) { - if (bmain->is_data_only) { - uiItemL_ex(layout, - RPT_("Overwrite library file with an older Blender version?"), - ICON_NONE, - true, - false); + if (bmain->is_asset_repository) { + uiItemL_ex( + layout, + RPT_("Convert asset blend file to regular blend file with an older Blender version?"), + ICON_NONE, + true, + false); } else { uiItemL_ex( layout, RPT_("Overwrite file with an older Blender version?"), ICON_NONE, true, false); } } - else if (bmain->is_data_only) { - uiItemL_ex(layout, RPT_("Overwrite library file?"), ICON_NONE, true, false); + else if (bmain->is_asset_repository) { + uiItemL_ex( + layout, RPT_("Convert asset blend file to regular blend file?"), ICON_NONE, true, false); } else { BLI_assert_unreachable(); -- 2.30.2 From 3195a0625a1ca7126fe3d63b2ae3afd630da738d Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 25 Jan 2024 11:02:15 +0100 Subject: [PATCH 3/3] Updated tooltip message from review. --- source/blender/editors/interface/interface_templates.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/interface/interface_templates.cc b/source/blender/editors/interface/interface_templates.cc index a14e66e421f..baf25003bcd 100644 --- a/source/blender/editors/interface/interface_templates.cc +++ b/source/blender/editors/interface/interface_templates.cc @@ -6584,8 +6584,9 @@ static void ui_template_status_info_warnings_messages(Main *bmain, tooltip_message += "\n\n"; } tooltip_message += RPT_( - "This is an Asset Library Blender file, overwriting it\nmay break its handling by the " - "Assets system"); + "This file is managed by the Blender asset system\n" + "By editing it as a regular blend file, it will no longer\n" + "be possible to update its assets through the asset browser"); } regular_message = ED_info_statusbar_string_ex(bmain, scene, view_layer, statusbar_info_flag); -- 2.30.2