UI Experiment: Named Undo Snapshots #118091
|
@ -40,6 +40,7 @@ void ED_undo_pop(bContext *C);
|
|||
void ED_undo_redo(bContext *C);
|
||||
void ED_OT_undo(wmOperatorType *ot);
|
||||
void ED_OT_undo_push(wmOperatorType *ot);
|
||||
void ED_OT_undo_push_snapshot(wmOperatorType *ot);
|
||||
void ED_OT_redo(wmOperatorType *ot);
|
||||
void ED_OT_undo_redo(wmOperatorType *ot);
|
||||
void ED_OT_undo_history(wmOperatorType *ot);
|
||||
|
|
|
@ -216,34 +216,30 @@ static void undo_history_draw_menu(const bContext *C, Menu *menu)
|
|||
return;
|
||||
}
|
||||
|
||||
int undo_step_count = 0;
|
||||
int undo_step_count_all = 0;
|
||||
LISTBASE_FOREACH_BACKWARD (UndoStep *, us, &wm->undo_stack->steps) {
|
||||
undo_step_count_all += 1;
|
||||
if (us->skip) {
|
||||
continue;
|
||||
}
|
||||
undo_step_count += 1;
|
||||
}
|
||||
|
||||
uiLayout *split = uiLayoutSplit(menu->layout, 0.0f, false);
|
||||
uiLayout *column = nullptr;
|
||||
uiLayout *column = uiLayoutColumn(split, false);
|
||||
|
||||
const int col_size = 20 + (undo_step_count / 12);
|
||||
uiItemO(column, IFACE_("Add Snapshot"), ICON_ADD, "ED_OT_undo_push_snapshot");
|
||||
uiItemS(column);
|
||||
|
||||
undo_step_count = 0;
|
||||
int rows = 2;
|
||||
|
||||
int undo_steps = BLI_listbase_count(&wm->undo_stack->steps);
|
||||
const int col_size = 20 + (undo_steps / 12);
|
||||
|
||||
/* Reverse the order so the most recent state is first in the menu. */
|
||||
int i = undo_step_count_all - 1;
|
||||
for (UndoStep *us = static_cast<UndoStep *>(wm->undo_stack->steps.last); us; us = us->prev, i--)
|
||||
{
|
||||
int i = undo_steps;
|
||||
LISTBASE_FOREACH_BACKWARD (UndoStep *, us, &wm->undo_stack->steps) {
|
||||
i--;
|
||||
if (us->skip) {
|
||||
continue;
|
||||
}
|
||||
if (!(undo_step_count % col_size)) {
|
||||
|
||||
if (rows > 0 && !(rows % col_size)) {
|
||||
column = uiLayoutColumn(split, false);
|
||||
}
|
||||
const bool is_active = (us == wm->undo_stack->step_active);
|
||||
|
||||
uiLayout *row = uiLayoutRow(column, false);
|
||||
uiLayoutSetEnabled(row, !is_active);
|
||||
uiItemIntO(row,
|
||||
|
@ -252,7 +248,7 @@ static void undo_history_draw_menu(const bContext *C, Menu *menu)
|
|||
"ED_OT_undo_history",
|
||||
"item",
|
||||
i);
|
||||
undo_step_count += 1;
|
||||
rows += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BLT_translation.hh"
|
||||
|
@ -625,6 +626,67 @@ void ED_OT_undo_push(wmOperatorType *ot)
|
|||
"");
|
||||
}
|
||||
|
||||
static int ed_undo_push_snapshot_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
if (G.background) {
|
||||
/* Exception for background mode, see: #60934.
|
||||
* NOTE: since the undo stack isn't initialized on startup, background mode behavior
|
||||
* won't match regular usage, this is just for scripts to do explicit undo pushes. */
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
if (wm->undo_stack == nullptr) {
|
||||
wm->undo_stack = BKE_undosys_stack_create();
|
||||
}
|
||||
}
|
||||
|
||||
char str[BKE_UNDO_STR_MAX];
|
||||
RNA_string_get(op->ptr, "message", str);
|
||||
ED_undo_push(C, str);
|
||||
RNA_string_set(op->ptr, "message", "");
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int ed_undo_push_snapshot_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
|
||||
{
|
||||
return WM_operator_props_dialog_popup(C, op, 200, IFACE_("Add Undo Snapshot"), IFACE_("Add"));
|
||||
}
|
||||
|
||||
static void ed_undo_push_snapshot_ui(bContext *C, wmOperator *op)
|
||||
{
|
||||
uiLayout *layout = op->layout;
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
|
||||
char str[FILE_MAX];
|
||||
RNA_string_get(op->ptr, "message", str);
|
||||
if (!str[0]) {
|
||||
time_t time_now = time(NULL);
|
||||
struct tm *tm_local = localtime(&time_now);
|
||||
char time_str[26];
|
||||
strftime(time_str, 26, "%H:%M:%S", tm_local);
|
||||
SNPRINTF_RLEN(str, "Snapshot at %s", time_str);
|
||||
RNA_string_set(op->ptr, "message", str);
|
||||
}
|
||||
|
||||
uiItemL(layout, "Description", ICON_NONE);
|
||||
uiItemR(layout, op->ptr, "message", UI_ITEM_NONE, "", ICON_NONE);
|
||||
}
|
||||
|
||||
void ED_OT_undo_push_snapshot(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Add Snapshot";
|
||||
ot->description = "Add an undo snapshot";
|
||||
ot->idname = "ED_OT_undo_push_snapshot";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = ed_undo_push_snapshot_invoke;
|
||||
ot->exec = ed_undo_push_snapshot_exec;
|
||||
ot->poll = ED_operator_screenactive;
|
||||
ot->ui = ed_undo_push_snapshot_ui;
|
||||
|
||||
/* properties */
|
||||
RNA_def_string(ot->srna, "message", nullptr, BKE_UNDO_STR_MAX, "Snapshot description", "");
|
||||
}
|
||||
|
||||
static bool ed_redo_poll(bContext *C)
|
||||
{
|
||||
if (!ed_undo_is_init_and_screenactive_poll(C)) {
|
||||
|
|
|
@ -415,6 +415,7 @@ void ED_operatortypes_edutils()
|
|||
|
||||
WM_operatortype_append(ED_OT_undo);
|
||||
WM_operatortype_append(ED_OT_undo_push);
|
||||
WM_operatortype_append(ED_OT_undo_push_snapshot);
|
||||
WM_operatortype_append(ED_OT_redo);
|
||||
WM_operatortype_append(ED_OT_undo_redo);
|
||||
WM_operatortype_append(ED_OT_undo_history);
|
||||
|
|
Loading…
Reference in New Issue