UI Demonstration: Undo History as Actions, not Waypoints #117096
|
@ -237,6 +237,10 @@ static void undo_history_draw_menu(const bContext *C, Menu *menu)
|
||||||
|
|
||||||
/* Reverse the order so the most recent state is first in the menu. */
|
/* Reverse the order so the most recent state is first in the menu. */
|
||||||
int i = undo_step_count_all - 1;
|
int i = undo_step_count_all - 1;
|
||||||
|
|
||||||
|
/* Is this step an undo or a redo? */
|
||||||
|
bool is_undo = false;
|
||||||
|
|
||||||
for (UndoStep *us = static_cast<UndoStep *>(wm->undo_stack->steps.last); us; us = us->prev, i--)
|
for (UndoStep *us = static_cast<UndoStep *>(wm->undo_stack->steps.last); us; us = us->prev, i--)
|
||||||
{
|
{
|
||||||
if (us->skip) {
|
if (us->skip) {
|
||||||
|
@ -246,14 +250,23 @@ static void undo_history_draw_menu(const bContext *C, Menu *menu)
|
||||||
column = uiLayoutColumn(split, false);
|
column = uiLayoutColumn(split, false);
|
||||||
}
|
}
|
||||||
const bool is_active = (us == wm->undo_stack->step_active);
|
const bool is_active = (us == wm->undo_stack->step_active);
|
||||||
uiLayout *row = uiLayoutRow(column, false);
|
if (is_active) {
|
||||||
uiLayoutSetEnabled(row, !is_active);
|
if (undo_step_count > 0) {
|
||||||
uiItemIntO(row,
|
/* Horizontal line to indicate current position. */
|
||||||
|
uiItemS_ex(column, 0.2f);
|
||||||
|
}
|
||||||
|
/* Items from now on are undo, before this were redo. */
|
||||||
|
is_undo = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int undo_step = MAX2(is_undo ? i - 1 : i, 0);
|
||||||
|
|
||||||
|
uiItemIntO(column,
|
||||||
CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, us->name),
|
CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, us->name),
|
||||||
is_active ? ICON_LAYER_ACTIVE : ICON_NONE,
|
ICON_NONE,
|
||||||
"ED_OT_undo_history",
|
"ED_OT_undo_history",
|
||||||
"item",
|
"item",
|
||||||
i);
|
undo_step);
|
||||||
undo_step_count += 1;
|
undo_step_count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -590,6 +590,18 @@ static bool ed_undo_poll(bContext *C)
|
||||||
return (undo_stack->step_active != nullptr) && (undo_stack->step_active->prev != nullptr);
|
return (undo_stack->step_active != nullptr) && (undo_stack->step_active->prev != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string ed_undo_get_name(wmOperatorType *ot, PointerRNA * /*ptr*/)
|
||||||
|
{
|
||||||
|
UndoStack *undo_stack = ED_undo_stack_get();
|
||||||
|
if ((undo_stack && undo_stack->step_active != NULL) && (undo_stack->step_active->prev != NULL)) {
|
||||||
|
return CTX_IFACE_(ot->translation_context, "Undo") + std::string(" ") +
|
||||||
|
std::string(CTX_IFACE_(ot->translation_context, undo_stack->step_active->name));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ED_OT_undo(wmOperatorType *ot)
|
void ED_OT_undo(wmOperatorType *ot)
|
||||||
{
|
{
|
||||||
/* identifiers */
|
/* identifiers */
|
||||||
|
@ -600,6 +612,7 @@ void ED_OT_undo(wmOperatorType *ot)
|
||||||
/* api callbacks */
|
/* api callbacks */
|
||||||
ot->exec = ed_undo_exec;
|
ot->exec = ed_undo_exec;
|
||||||
ot->poll = ed_undo_poll;
|
ot->poll = ed_undo_poll;
|
||||||
|
ot->get_name = ed_undo_get_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ED_OT_undo_push(wmOperatorType *ot)
|
void ED_OT_undo_push(wmOperatorType *ot)
|
||||||
|
@ -633,6 +646,18 @@ static bool ed_redo_poll(bContext *C)
|
||||||
return (undo_stack->step_active != nullptr) && (undo_stack->step_active->next != nullptr);
|
return (undo_stack->step_active != nullptr) && (undo_stack->step_active->next != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string ed_redo_get_name(wmOperatorType *ot, PointerRNA * /*ptr*/)
|
||||||
|
{
|
||||||
|
UndoStack *undo_stack = ED_undo_stack_get();
|
||||||
|
if ((undo_stack && undo_stack->step_active != NULL) && (undo_stack->step_active->next != NULL)) {
|
||||||
|
return CTX_IFACE_(ot->translation_context, "Redo") + std::string(" ") +
|
||||||
|
std::string(CTX_IFACE_(ot->translation_context, undo_stack->step_active->next->name));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ED_OT_redo(wmOperatorType *ot)
|
void ED_OT_redo(wmOperatorType *ot)
|
||||||
{
|
{
|
||||||
/* identifiers */
|
/* identifiers */
|
||||||
|
@ -643,6 +668,7 @@ void ED_OT_redo(wmOperatorType *ot)
|
||||||
/* api callbacks */
|
/* api callbacks */
|
||||||
ot->exec = ed_redo_exec;
|
ot->exec = ed_redo_exec;
|
||||||
ot->poll = ed_redo_poll;
|
ot->poll = ed_redo_poll;
|
||||||
|
ot->get_name = ed_redo_get_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ED_OT_undo_redo(wmOperatorType *ot)
|
void ED_OT_undo_redo(wmOperatorType *ot)
|
||||||
|
|
|
@ -761,6 +761,10 @@ bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
|
||||||
|
|
||||||
PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
|
PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
|
||||||
{
|
{
|
||||||
|
if (!ptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (identifier[0] == '[' && identifier[1] == '"') {
|
if (identifier[0] == '[' && identifier[1] == '"') {
|
||||||
/* id prop lookup, not so common */
|
/* id prop lookup, not so common */
|
||||||
PropertyRNA *r_prop = nullptr;
|
PropertyRNA *r_prop = nullptr;
|
||||||
|
@ -5377,6 +5381,10 @@ void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values)
|
||||||
|
|
||||||
int RNA_enum_get(PointerRNA *ptr, const char *name)
|
int RNA_enum_get(PointerRNA *ptr, const char *name)
|
||||||
{
|
{
|
||||||
|
if (!ptr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
PropertyRNA *prop = RNA_struct_find_property(ptr, name);
|
PropertyRNA *prop = RNA_struct_find_property(ptr, name);
|
||||||
|
|
||||||
if (prop) {
|
if (prop) {
|
||||||
|
|
|
@ -577,7 +577,7 @@ static void wm_operatortype_free_macro(wmOperatorType *ot)
|
||||||
std::string WM_operatortype_name(wmOperatorType *ot, PointerRNA *properties)
|
std::string WM_operatortype_name(wmOperatorType *ot, PointerRNA *properties)
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
if (ot->get_name && properties) {
|
if (ot->get_name) {
|
||||||
name = ot->get_name(ot, properties);
|
name = ot->get_name(ot, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue