Commit: c1beaea80f97026442a2b81e51ea80ce9dfc492d Author: Campbell Barton Date: Thu Jan 26 11:01:32 2023 +1100 Branches: master https://developer.blender.org/rBc1beaea80f97026442a2b81e51ea80ce9dfc492d
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]: f68e50a263b8a970075c8fd540a985f2798e1d13 =================================================================== M source/blender/windowmanager/intern/wm_event_system.cc =================================================================== diff --git a/source/blender/windowmanager/intern/wm_event_system.cc b/source/blender/windowmanager/intern/wm_event_system.cc index bf549cd00c9..c1ee3d522b6 100644 --- a/source/blender/windowmanager/intern/wm_event_system.cc +++ b/source/blender/windowmanager/intern/wm_event_system.cc @@ -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)) { _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs