UI: File Save Incremental Operator #104678
|
@ -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},
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
Harley marked this conversation as resolved
Outdated
|
||||
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'
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -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";
|
||||
Harley marked this conversation as resolved
Outdated
Campbell Barton
commented
Again, doesn't mention incrementing doesn't overwrite. Again, doesn't mention incrementing doesn't overwrite.
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
Loading…
Reference in New Issue
Use
enabled
otherwise this is still clickable (which isn't expected for greyed out menu items).