[Bf-blender-cvs] [c1beaea80f9] master: Fix T103587: Redo panel doesn't appear for spin operator

Campbell Barton noreply at git.blender.org
Thu Jan 26 01:10:51 CET 2023


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)) {



More information about the Bf-blender-cvs mailing list