[Bf-blender-cvs] [cc0c4c17f01] blender-v3.2-release: Fix T95752: crash 'Select Linked' after loopcut in multiobject editmode

Philipp Oeser noreply at git.blender.org
Tue May 3 09:50:02 CEST 2022


Commit: cc0c4c17f011f7f687f7719aab1568c9a5a38217
Author: Philipp Oeser
Date:   Thu Apr 28 13:51:14 2022 +0200
Branches: blender-v3.2-release
https://developer.blender.org/rBcc0c4c17f011f7f687f7719aab1568c9a5a38217

Fix T95752: crash 'Select Linked' after loopcut in multiobject editmode

This was reported explicitly for originally being in face selectmode,
but could also crash when in vertex selectmode (when doing multiple
cuts).

The reason here is that `MESH_OT_loopcut` switches to edge select mode
(needed for `TRANSFORM_OT_edge_slide`, done in `ringsel_finish`), but was
only doing this on the active object's editmesh, all other participating
meshes would keep their selectmode which would now be out of sync with
both the active object's editmesh and scene settings for these.

This causes problems later in 'Select Linked'. Here, a mixture of
objects are used. First the viewcontext is set up with the active
object, then all participating objects are iterated (changing the
viewcontext to another object), then `unified_findnearest` would use that
changed viewcontext which would now contain the last object iterated. To
repeat: this could now have a different selectmode than the active
object which is later **again** used to get the nearest `BMElem` from in
`EDBM_elem_from_selectmode`. So in the failing case, we could get an
edge (but no face because of edge selectmode) from `unified_findnearest`,
`EDBM_elem_from_selectmode` would return NULL though (edge provided, but
in face selectmode), leading to the crash.

To solve this I assume it is best to change selectmode on all
participating meshes in multi-object editmode loopcut if necessary so
these are always in sync for following operations.
Alternatively, `Select Linked` (and probably lots more operators) would
have to be tweaked to pay closer attention which object is really used
to get selectmode from.

Note the selectmode is actually set back from edge selectmode in certain
cases (see `USE_LOOPSLIDE_HACK`), this patch changes that as well to act
on all participating meshes.

Maniphest Tasks: T95752

Differential Revision: https://developer.blender.org/D14791

===================================================================

M	source/blender/editors/mesh/editmesh_loopcut.c
M	source/blender/editors/transform/transform_ops.c

===================================================================

diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index c9fc48c3568..5a4b12c2209 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -208,12 +208,15 @@ static void ringsel_finish(bContext *C, wmOperator *op)
 
         EDBM_selectmode_flush_ex(lcd->em, SCE_SELECT_VERTEX);
       }
-      /* we can't slide multiple edges in vertex select mode */
+      /* We can't slide multiple edges in vertex select mode, force edge select mode. Do this for
+       * all meshes in multi-object editmode so their selectmode is in sync for following
+       * operators. */
       else if (is_macro && (cuts > 1) && (em->selectmode & SCE_SELECT_VERTEX)) {
-        EDBM_selectmode_disable(lcd->vc.scene, em, SCE_SELECT_VERTEX, SCE_SELECT_EDGE);
+        EDBM_selectmode_disable_multi(C, SCE_SELECT_VERTEX, SCE_SELECT_EDGE);
       }
-      /* Force edge slide to edge select mode in face select mode. */
-      else if (EDBM_selectmode_disable(lcd->vc.scene, em, SCE_SELECT_FACE, SCE_SELECT_EDGE)) {
+      /* Force edge slide to edge select mode in face select mode. Do this for all meshes in
+       * multi-object editmode so their selectmode is in sync for following operators. */
+      else if (EDBM_selectmode_disable_multi(C, SCE_SELECT_FACE, SCE_SELECT_EDGE)) {
         /* pass, the change will flush selection */
       }
       else {
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index ec49cef4067..600f525b428 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -315,6 +315,8 @@ static void TRANSFORM_OT_create_orientation(struct wmOperatorType *ot)
 #ifdef USE_LOOPSLIDE_HACK
 /**
  * Special hack for MESH_OT_loopcut_slide so we get back to the selection mode
+ * Do this for all meshes in multi-object editmode so their selectmode is in sync for following
+ * operators
  */
 static void transformops_loopsel_hack(bContext *C, wmOperator *op)
 {
@@ -334,12 +336,10 @@ static void transformops_loopsel_hack(bContext *C, wmOperator *op)
                            (mesh_select_mode[1] ? SCE_SELECT_EDGE : 0) |
                            (mesh_select_mode[2] ? SCE_SELECT_FACE : 0));
 
-        /* still switch if we were originally in face select mode */
+        /* Still switch if we were originally in face select mode. */
         if ((ts->selectmode != selectmode_orig) && (selectmode_orig != SCE_SELECT_FACE)) {
-          Object *obedit = CTX_data_edit_object(C);
-          BMEditMesh *em = BKE_editmesh_from_object(obedit);
-          em->selectmode = ts->selectmode = selectmode_orig;
-          EDBM_selectmode_set(em);
+          ts->selectmode = selectmode_orig;
+          EDBM_selectmode_set_multi(C, selectmode_orig);
         }
       }
     }



More information about the Bf-blender-cvs mailing list