Fix T103587: Redo panel doesn't appear for spin operator
Regression in [0] which cleared the redo-panel if an operator added
its own undo step. This worked for sculpt to fix T101743, but caused
the redo-panel to be cleared for actions who's undo steps where created
by nested operators (which is the case for the spin operator).
Fix by checking an undo-step is added without registering an operator.
[0]: f68e50a263
This commit is contained in:
parent
f5d94f97e4
commit
c1beaea80f
Notes:
blender-bot
2023-06-19 06:03:47 +02:00
Referenced by issue #104183, Inconsistent pressure behavior between the size and the strength in the sculpt mode Referenced by issue #103587, Redo panel doesn't appear for spin operator Referenced by issue #101743, Regression: Redo panel created on sculpting Referenced by issue #109112, Mask on mesh with multires modifier looks strange, behave broken
|
@ -944,6 +944,14 @@ static intptr_t wm_operator_undo_active_id(const wmWindowManager *wm)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static intptr_t wm_operator_register_active_id(const wmWindowManager *wm)
|
||||
{
|
||||
if (wm->operators.last) {
|
||||
return intptr_t(wm->operators.last);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool WM_operator_poll(bContext *C, wmOperatorType *ot)
|
||||
{
|
||||
|
||||
|
@ -1078,9 +1086,14 @@ static bool wm_operator_register_check(wmWindowManager *wm, wmOperatorType *ot)
|
|||
/**
|
||||
* \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.
|
||||
* \param has_register: True when an operator was registered.
|
||||
*/
|
||||
static void wm_operator_finished(
|
||||
bContext *C, wmOperator *op, const bool repeat, const bool store, const bool has_undo_step)
|
||||
static void wm_operator_finished(bContext *C,
|
||||
wmOperator *op,
|
||||
const bool repeat,
|
||||
const bool store,
|
||||
const bool has_undo_step,
|
||||
const bool has_register)
|
||||
{
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
enum {
|
||||
|
@ -1088,6 +1101,7 @@ static void wm_operator_finished(
|
|||
SET,
|
||||
CLEAR,
|
||||
} hud_status = NOP;
|
||||
const bool do_register = (repeat == false) && wm_operator_register_check(wm, op->type);
|
||||
|
||||
op->customdata = nullptr;
|
||||
|
||||
|
@ -1112,8 +1126,14 @@ static void wm_operator_finished(
|
|||
}
|
||||
}
|
||||
else if (has_undo_step) {
|
||||
if (repeat == 0) {
|
||||
hud_status = CLEAR;
|
||||
/* An undo step was added but the operator wasn't registered (and won't register it's self),
|
||||
* therefor a redo panel wouldn't redo this action but the previous registered action,
|
||||
* causing the "redo" to remove/loose this operator. See: T101743.
|
||||
* Register check is needed so nested operator calls don't clear the HUD. See: T103587. */
|
||||
if (!(has_register || do_register)) {
|
||||
if (repeat == 0) {
|
||||
hud_status = CLEAR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1125,7 +1145,7 @@ static void wm_operator_finished(
|
|||
MEM_freeN(buf);
|
||||
}
|
||||
|
||||
if (wm_operator_register_check(wm, op->type)) {
|
||||
if (do_register) {
|
||||
/* Take ownership of reports (in case python provided own). */
|
||||
op->reports->flag |= RPT_FREE;
|
||||
|
||||
|
@ -1177,6 +1197,8 @@ static int wm_operator_exec(bContext *C, wmOperator *op, const bool repeat, cons
|
|||
}
|
||||
|
||||
const intptr_t undo_id_prev = wm_operator_undo_active_id(wm);
|
||||
const intptr_t register_id_prev = wm_operator_register_active_id(wm);
|
||||
|
||||
if (op->type->exec) {
|
||||
if (op->type->flag & OPTYPE_UNDO) {
|
||||
wm->op_undo_depth++;
|
||||
|
@ -1199,8 +1221,10 @@ static int wm_operator_exec(bContext *C, wmOperator *op, const bool repeat, cons
|
|||
|
||||
if (retval & OPERATOR_FINISHED) {
|
||||
const bool has_undo_step = (undo_id_prev != wm_operator_undo_active_id(wm));
|
||||
const bool has_register = (register_id_prev != wm_operator_register_active_id(wm));
|
||||
|
||||
wm_operator_finished(C, op, repeat, store && wm->op_undo_depth == 0, has_undo_step);
|
||||
wm_operator_finished(
|
||||
C, op, repeat, store && wm->op_undo_depth == 0, has_undo_step, has_register);
|
||||
}
|
||||
else if (repeat == 0) {
|
||||
/* WARNING: modal from exec is bad practice, but avoid crashing. */
|
||||
|
@ -1442,6 +1466,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);
|
||||
const intptr_t register_id_prev = wm_operator_register_active_id(wm);
|
||||
|
||||
/* If `reports == nullptr`, they'll be initialized. */
|
||||
wmOperator *op = wm_operator_create(wm, ot, properties, reports);
|
||||
|
@ -1511,8 +1536,9 @@ static int wm_operator_invoke(bContext *C,
|
|||
}
|
||||
else if (retval & OPERATOR_FINISHED) {
|
||||
const bool has_undo_step = (undo_id_prev != wm_operator_undo_active_id(wm));
|
||||
const bool has_register = (register_id_prev != wm_operator_register_active_id(wm));
|
||||
const bool store = !is_nested_call && use_last_properties;
|
||||
wm_operator_finished(C, op, false, store, has_undo_step);
|
||||
wm_operator_finished(C, op, false, store, has_undo_step, has_register);
|
||||
}
|
||||
else if (retval & OPERATOR_RUNNING_MODAL) {
|
||||
/* Take ownership of reports (in case python provided own). */
|
||||
|
@ -2402,6 +2428,7 @@ static int wm_handler_operator_call(bContext *C,
|
|||
wm_event_modalkeymap_begin(C, op, event, &event_backup);
|
||||
|
||||
const intptr_t undo_id_prev = wm_operator_undo_active_id(wm);
|
||||
const intptr_t register_id_prev = wm_operator_register_active_id(wm);
|
||||
if (ot->flag & OPTYPE_UNDO) {
|
||||
wm->op_undo_depth++;
|
||||
}
|
||||
|
@ -2438,8 +2465,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) {
|
||||
const bool has_undo_step = (undo_id_prev != wm_operator_undo_active_id(wm));
|
||||
const bool has_register = (register_id_prev != wm_operator_register_active_id(wm));
|
||||
|
||||
wm_operator_finished(C, op, false, true, has_undo_step);
|
||||
wm_operator_finished(C, op, false, true, has_undo_step, has_register);
|
||||
handler->op = nullptr;
|
||||
}
|
||||
else if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) {
|
||||
|
|
Loading…
Reference in New Issue