Fix #136491: crash 'Select Linked' after 'Select Boundary Loop'

...  when in multiobject editmode

We had a similar issue in #95752, so the fix here is similar to
cc0c4c17f0

The reason here is that `edbm_region_to_loop_exec` switches to edge
select mode but was only doing this on objects that actually had faces
selected, all other participating meshes would keep their selectmode
which would now be out of sync with both the objects that had faces
selected 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 it is best to change selectmode on all
participating meshes in multi-object editmode if necessary so
these are always in sync for following operations.

Pull Request: https://projects.blender.org/blender/blender/pulls/136497
This commit is contained in:
Philipp Oeser
2025-03-25 13:54:01 +01:00
committed by Philipp Oeser
parent 6eac902c90
commit a062b334a9

View File

@@ -5251,6 +5251,7 @@ static wmOperatorStatus edbm_region_to_loop_exec(bContext *C, wmOperator * /*op*
ViewLayer *view_layer = CTX_data_view_layer(C);
const Vector<Object *> objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
scene, view_layer, CTX_wm_view3d(C));
bool changed = false;
for (Object *obedit : objects) {
BMEditMesh *em = BKE_editmesh_from_object(obedit);
@@ -5286,21 +5287,21 @@ static wmOperatorStatus edbm_region_to_loop_exec(bContext *C, wmOperator * /*op*
BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
BM_edge_select_set(em->bm, e, true);
changed = true;
}
}
/* If in face-only select mode, switch to edge select mode so that
* an edge-only selection is not inconsistent state. */
if (em->selectmode == SCE_SELECT_FACE) {
em->selectmode = SCE_SELECT_EDGE;
EDBM_selectmode_set(em);
EDBM_selectmode_to_scene(C);
}
DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
if (changed) {
/* If in face-only select mode, switch to edge select mode so that
* an edge-only selection is not inconsistent state. Do this for all meshes in multi-object
* editmode so their selectmode is in sync for following operators. */
EDBM_selectmode_disable_multi(C, SCE_SELECT_FACE, SCE_SELECT_EDGE);
}
return OPERATOR_FINISHED;
}