From ac7bd05b2e2d55f60f2e65c3fba6bed02e95116f Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Wed, 17 May 2023 13:35:59 -0700 Subject: [PATCH] Updated to the current state of main. --- .../keyconfig/keymap_data/blender_default.py | 5 ++- .../keymap_data/industry_compatible_data.py | 1 + scripts/startup/bl_ui/space_topbar.py | 4 ++ source/blender/blenlib/BLI_string.h | 9 ++++ source/blender/blenlib/intern/string.c | 11 +++++ .../blender/windowmanager/intern/wm_files.cc | 45 +++++++++++++++++++ 6 files changed, 73 insertions(+), 2 deletions(-) diff --git a/scripts/presets/keyconfig/keymap_data/blender_default.py b/scripts/presets/keyconfig/keymap_data/blender_default.py index a1545836f56..dd22ead9973 100644 --- a/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -590,6 +590,7 @@ def km_window(params): ("wm.open_mainfile", {"type": 'O', "value": 'PRESS', "ctrl": True}, None), ("wm.save_mainfile", {"type": 'S', "value": 'PRESS', "ctrl": True}, None), ("wm.save_as_mainfile", {"type": 'S', "value": 'PRESS', "shift": True, "ctrl": True}, None), + ("wm.save_mainfile", {"type": 'S', "value": 'PRESS', "ctrl": True, "alt": True}, {"properties": [("incremental", True)]}), ("wm.quit_blender", {"type": 'Q', "value": 'PRESS', "ctrl": True}, None), # Quick menu and toolbar @@ -4555,7 +4556,7 @@ def km_pose(params): ("armature.layers_show_all", {"type": 'ACCENT_GRAVE', "value": 'PRESS', "ctrl": True}, None), ("armature.armature_layers", {"type": 'M', "value": 'PRESS', "shift": True}, None), ("pose.bone_layers", {"type": 'M', "value": 'PRESS'}, None), - ("transform.bbone_resize", {"type": 'S', "value": 'PRESS', "ctrl": True, "alt": True}, None), + ("transform.bbone_resize", {"type": 'S', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None), ("anim.keyframe_insert_menu", {"type": 'I', "value": 'PRESS'}, None), ("anim.keyframe_delete_v3d", {"type": 'I', "value": 'PRESS', "alt": True}, None), ("anim.keying_set_active_set", {"type": 'I', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None), @@ -5484,7 +5485,7 @@ def km_armature(params): ("armature.bone_layers", {"type": 'M', "value": 'PRESS'}, None), # Special transforms. op_tool_optional( - ("transform.bbone_resize", {"type": 'S', "value": 'PRESS', "ctrl": True, "alt": True}, None), + ("transform.bbone_resize", {"type": 'S', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None), (op_tool_cycle, "builtin.bone_size"), params), op_tool_optional( ("transform.transform", {"type": 'S', "value": 'PRESS', "alt": True}, diff --git a/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py b/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py index 1c6ac26c7e9..ac6330bfb07 100644 --- a/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py +++ b/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py @@ -188,6 +188,7 @@ def km_window(params): ("wm.open_mainfile", {"type": 'O', "value": 'PRESS', "ctrl": True}, None), ("wm.save_mainfile", {"type": 'S', "value": 'PRESS', "ctrl": True}, None), ("wm.save_as_mainfile", {"type": 'S', "value": 'PRESS', "shift": True, "ctrl": True}, None), + ("wm.save_mainfile", {"type": 'S', "value": 'PRESS', "ctrl": True, "alt": True}, {"properties": [("incremental", True)]}), ("wm.quit_blender", {"type": 'Q', "value": 'PRESS', "ctrl": True}, None), # Quick menu and toolbar diff --git a/scripts/startup/bl_ui/space_topbar.py b/scripts/startup/bl_ui/space_topbar.py index 53cd5072c9a..f3dcc7feef4 100644 --- a/scripts/startup/bl_ui/space_topbar.py +++ b/scripts/startup/bl_ui/space_topbar.py @@ -283,6 +283,10 @@ class TOPBAR_MT_file(Menu): layout.operator_context = 'EXEC_AREA' if context.blend_data.is_saved else 'INVOKE_AREA' layout.operator("wm.save_mainfile", text="Save", icon='FILE_TICK') + sub = layout.row() + sub.enabled = context.blend_data.is_saved + sub.operator("wm.save_mainfile", text="Save Incremental").incremental = True + layout.operator_context = 'INVOKE_AREA' layout.operator("wm.save_as_mainfile", text="Save As...") layout.operator_context = 'INVOKE_AREA' diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h index 785904ff87e..d9d8460f7f4 100644 --- a/source/blender/blenlib/BLI_string.h +++ b/source/blender/blenlib/BLI_string.h @@ -435,6 +435,15 @@ void BLI_str_rstrip(char *str) ATTR_NONNULL(1); */ int BLI_str_rstrip_float_zero(char *str, char pad) ATTR_NONNULL(1); +/** + * Strip trailing digits. + * ABC123 -> ABC + * + * \param str: + * \return The number of digits stripped. + */ +int BLI_str_rstrip_digits(char *str) ATTR_NONNULL(); + /** * Return index of a string in a string array. * diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index b6fad00ff0a..ceb8d04890c 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -1057,6 +1057,17 @@ int BLI_str_rstrip_float_zero(char *str, const char pad) return totstrip; } +int BLI_str_rstrip_digits(char *str) +{ + int totstrip = 0; + int str_len = strlen(str); + while (str_len > 0 && isdigit(str[--str_len])) { + str[str_len] = '\0'; + totstrip++; + } + return totstrip; +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/windowmanager/intern/wm_files.cc b/source/blender/windowmanager/intern/wm_files.cc index a6c644d155a..c22a68896f5 100644 --- a/source/blender/windowmanager/intern/wm_files.cc +++ b/source/blender/windowmanager/intern/wm_files.cc @@ -3257,6 +3257,31 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } + if (RNA_boolean_get(op->ptr, "incremental")) { + char head[FILE_MAXFILE], tail[FILE_MAXFILE]; + ushort digits; + int num = BLI_path_sequence_decode(filepath, head, sizeof(head), tail, sizeof(tail), &digits); + /* Numbers greater than INT_MAX return 0, resulting in always appending "1" to the name. */ + if (num == 0 && digits == 0) { + /* This does nothing if there are no numbers at the end of the head. */ + BLI_str_rstrip_digits(head); + } + + const int tries_limit = 1000; + int tries = 0; + bool in_use = true; + do { + num++; + tries++; + BLI_path_sequence_encode(filepath, sizeof(filepath), head, tail, digits, num); + in_use = BLI_exists(filepath); + } while (in_use && tries < tries_limit && num < INT_MAX); + if (in_use) { + BKE_report(op->reports, RPT_ERROR, "Unable to find an available incremented file name"); + return OPERATOR_CANCELLED; + } + } + const int fileflags_orig = G.fileflags; int fileflags = G.fileflags; @@ -3391,6 +3416,18 @@ static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent * return ret; } +static char *wm_save_mainfile_get_description(bContext * /*C*/, + wmOperatorType * /*ot*/, + PointerRNA *ptr) +{ + if (RNA_boolean_get(ptr, "incremental")) { + return BLI_strdup( + TIP_("Save the current Blender file with a numerically incremented name that does not " + "overwrite any existing files")); + } + return nullptr; +} + void WM_OT_save_mainfile(wmOperatorType *ot) { ot->name = "Save Blender File"; @@ -3419,6 +3456,14 @@ void WM_OT_save_mainfile(wmOperatorType *ot) prop = RNA_def_boolean(ot->srna, "exit", false, "Exit", "Exit Blender after saving"); RNA_def_property_flag(prop, PropertyFlag(PROP_HIDDEN | PROP_SKIP_SAVE)); + + prop = RNA_def_boolean(ot->srna, + "incremental", + false, + "Incremental", + "Save the current Blender file with a numerically incremented name that " + "does not overwrite any existing files"); + RNA_def_property_flag(prop, PropertyFlag(PROP_HIDDEN | PROP_SKIP_SAVE)); } /** \} */ -- 2.30.2