WM: operators that add their own undo pushes now clears the redo panel
Detect when the operator adds its own undo step and clear the panel.
An alternative fix for [0] which caused T101743.
Needed to prevent changing values in the last operator panel from
destructively undoing brush steps.
[0]: 11bdc321a2.
Reviewed By: mont29, joeedh
Ref D16523
This commit is contained in:
@@ -43,6 +43,7 @@
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_undo_system.h"
|
||||
#include "BKE_workspace.h"
|
||||
|
||||
#include "BKE_sound.h"
|
||||
@@ -928,6 +929,17 @@ void WM_reportf(eReportType type, const char *format, ...)
|
||||
/** \name Operator Logic
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* Return the active undo step as an identifier for the purpose of comparison only.
|
||||
*/
|
||||
static intptr_t wm_operator_undo_active_id(const wmWindowManager *wm)
|
||||
{
|
||||
if (wm->undo_stack) {
|
||||
return intptr_t(wm->undo_stack->step_active);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool WM_operator_poll(bContext *C, wmOperatorType *ot)
|
||||
{
|
||||
|
||||
@@ -1059,7 +1071,12 @@ static bool wm_operator_register_check(wmWindowManager *wm, wmOperatorType *ot)
|
||||
return wm && (wm->op_undo_depth == 0) && (ot->flag & (OPTYPE_REGISTER | OPTYPE_UNDO));
|
||||
}
|
||||
|
||||
static void wm_operator_finished(bContext *C, wmOperator *op, const bool repeat, const bool store)
|
||||
/**
|
||||
* \param has_undo_step: True when an undo step was added,
|
||||
* needed when the operator doesn't use #OPTYPE_UNDO, #OPTYPE_UNDO_GROUPED but adds an undo step.
|
||||
*/
|
||||
static void wm_operator_finished(
|
||||
bContext *C, wmOperator *op, const bool repeat, const bool store, const bool has_undo_step)
|
||||
{
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
enum {
|
||||
@@ -1090,6 +1107,11 @@ static void wm_operator_finished(bContext *C, wmOperator *op, const bool repeat,
|
||||
hud_status = CLEAR;
|
||||
}
|
||||
}
|
||||
else if (has_undo_step) {
|
||||
if (repeat == 0) {
|
||||
hud_status = CLEAR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (repeat == 0) {
|
||||
@@ -1150,6 +1172,7 @@ static int wm_operator_exec(bContext *C, wmOperator *op, const bool repeat, cons
|
||||
return retval;
|
||||
}
|
||||
|
||||
const intptr_t undo_id_prev = wm_operator_undo_active_id(wm);
|
||||
if (op->type->exec) {
|
||||
if (op->type->flag & OPTYPE_UNDO) {
|
||||
wm->op_undo_depth++;
|
||||
@@ -1171,7 +1194,9 @@ static int wm_operator_exec(bContext *C, wmOperator *op, const bool repeat, cons
|
||||
}
|
||||
|
||||
if (retval & OPERATOR_FINISHED) {
|
||||
wm_operator_finished(C, op, repeat, store && wm->op_undo_depth == 0);
|
||||
const bool has_undo_step = (undo_id_prev != wm_operator_undo_active_id(wm));
|
||||
|
||||
wm_operator_finished(C, op, repeat, store && wm->op_undo_depth == 0, has_undo_step);
|
||||
}
|
||||
else if (repeat == 0) {
|
||||
/* WARNING: modal from exec is bad practice, but avoid crashing. */
|
||||
@@ -1412,6 +1437,7 @@ static int wm_operator_invoke(bContext *C,
|
||||
|
||||
if (WM_operator_poll(C, ot)) {
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
const intptr_t undo_id_prev = wm_operator_undo_active_id(wm);
|
||||
|
||||
/* If `reports == nullptr`, they'll be initialized. */
|
||||
wmOperator *op = wm_operator_create(wm, ot, properties, reports);
|
||||
@@ -1480,8 +1506,9 @@ static int wm_operator_invoke(bContext *C,
|
||||
/* Do nothing, #wm_operator_exec() has been called somewhere. */
|
||||
}
|
||||
else if (retval & OPERATOR_FINISHED) {
|
||||
const bool has_undo_step = (undo_id_prev != wm_operator_undo_active_id(wm));
|
||||
const bool store = !is_nested_call && use_last_properties;
|
||||
wm_operator_finished(C, op, false, store);
|
||||
wm_operator_finished(C, op, false, store, has_undo_step);
|
||||
}
|
||||
else if (retval & OPERATOR_RUNNING_MODAL) {
|
||||
/* Take ownership of reports (in case python provided own). */
|
||||
@@ -2378,6 +2405,7 @@ static int wm_handler_operator_call(bContext *C,
|
||||
wmEvent_ModalMapStore event_backup;
|
||||
wm_event_modalkeymap_begin(C, op, event, &event_backup);
|
||||
|
||||
const intptr_t undo_id_prev = wm_operator_undo_active_id(wm);
|
||||
if (ot->flag & OPTYPE_UNDO) {
|
||||
wm->op_undo_depth++;
|
||||
}
|
||||
@@ -2413,7 +2441,9 @@ static int wm_handler_operator_call(bContext *C,
|
||||
|
||||
/* Important to run 'wm_operator_finished' before setting the context members to null. */
|
||||
if (retval & OPERATOR_FINISHED) {
|
||||
wm_operator_finished(C, op, false, true);
|
||||
const bool has_undo_step = (undo_id_prev != wm_operator_undo_active_id(wm));
|
||||
|
||||
wm_operator_finished(C, op, false, true, has_undo_step);
|
||||
handler->op = nullptr;
|
||||
}
|
||||
else if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) {
|
||||
|
||||
Reference in New Issue
Block a user