From 211d7ff3cf27db44d961b704d11cda8d26c0e81a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 13 Oct 2020 16:51:20 +1100 Subject: Fix T81288:Select Linked fails with multi-object edit mode Changing options after using select-linked didn't work when the object being selected wasn't the active object. --- source/blender/editors/mesh/editmesh_select.c | 40 +++++++++++++++---------- source/blender/editors/mesh/editmesh_utils.c | 43 +++++++++++++++++++++++++++ source/blender/editors/mesh/mesh_intern.h | 9 ++++++ 3 files changed, 77 insertions(+), 15 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 52c109b3854..48405c7f534 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -3572,13 +3572,17 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE edbm_select_linked_pick_ex(em, ele, sel, delimit); - /* to support redo */ - BM_mesh_elem_index_ensure(bm, ele->head.htype); - index = EDBM_elem_to_index_any(em, ele); - - /* TODO(MULTI_EDIT), index doesn't know which object, - * index selections isn't very common. */ - RNA_int_set(op->ptr, "index", index); + /* To support redo. */ + { + /* Note that the `base_index` can't be used as the index depends on the view-port + * which might not be available on redo. */ + BM_mesh_elem_index_ensure(bm, ele->head.htype); + int object_index; + index = EDBM_elem_to_index_any_multi(vc.view_layer, em, ele, &object_index); + BLI_assert(object_index >= 0); + RNA_int_set(op->ptr, "object_index", object_index); + RNA_int_set(op->ptr, "index", index); + } DEG_id_tag_update(basact->object->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, basact->object->data); @@ -3589,18 +3593,22 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE static int edbm_select_linked_pick_exec(bContext *C, wmOperator *op) { - Object *obedit = CTX_data_edit_object(C); - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMesh *bm = em->bm; - int index; - const bool sel = !RNA_boolean_get(op->ptr, "deselect"); + Object *obedit = NULL; + BMElem *ele; + + { + ViewLayer *view_layer = CTX_data_view_layer(C); + const int object_index = RNA_int_get(op->ptr, "object_index"); + const int index = RNA_int_get(op->ptr, "index"); + ele = EDBM_elem_from_index_any_multi(view_layer, object_index, index, &obedit); + } - index = RNA_int_get(op->ptr, "index"); - if (index < 0 || index >= (bm->totvert + bm->totedge + bm->totface)) { + if (ele == NULL) { return OPERATOR_CANCELLED; } - BMElem *ele = EDBM_elem_from_index_any(em, index); + BMEditMesh *em = BKE_editmesh_from_object(obedit); + const bool sel = !RNA_boolean_get(op->ptr, "deselect"); #ifdef USE_LINKED_SELECT_DEFAULT_HACK int delimit = select_linked_delimit_default_from_op(op, em->selectmode); @@ -3645,6 +3653,8 @@ void MESH_OT_select_linked_pick(wmOperatorType *ot) #endif /* use for redo */ + prop = RNA_def_int(ot->srna, "object_index", -1, -1, INT_MAX, "", "", 0, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_int(ot->srna, "index", -1, -1, INT_MAX, "", "", 0, INT_MAX); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 1182187b3ff..d7ed3dca1b1 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -38,6 +38,7 @@ #include "BKE_editmesh.h" #include "BKE_editmesh_bvh.h" #include "BKE_global.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_mesh_mapping.h" @@ -1557,6 +1558,48 @@ BMElem *EDBM_elem_from_index_any(BMEditMesh *em, int index) return NULL; } +int EDBM_elem_to_index_any_multi(ViewLayer *view_layer, + BMEditMesh *em, + BMElem *ele, + int *r_object_index) +{ + uint bases_len; + int elem_index = -1; + *r_object_index = -1; + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(view_layer, NULL, &bases_len); + for (uint base_index = 0; base_index < bases_len; base_index++) { + Base *base_iter = bases[base_index]; + if (BKE_editmesh_from_object(base_iter->object) == em) { + *r_object_index = base_index; + elem_index = EDBM_elem_to_index_any(em, ele); + break; + } + } + MEM_freeN(bases); + return elem_index; +} + +BMElem *EDBM_elem_from_index_any_multi(ViewLayer *view_layer, + int object_index, + int elem_index, + Object **r_obedit) +{ + uint bases_len; + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(view_layer, NULL, &bases_len); + *r_obedit = NULL; + Object *obedit = ((uint)object_index < bases_len) ? bases[object_index]->object : NULL; + MEM_freeN(bases); + if (obedit != NULL) { + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMElem *ele = EDBM_elem_from_index_any(em, elem_index); + if (ele != NULL) { + *r_obedit = obedit; + return ele; + } + } + return NULL; +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index a1172d17fb0..21feddfb886 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -79,6 +79,15 @@ struct BMElem *EDBM_elem_from_selectmode(struct BMEditMesh *em, int EDBM_elem_to_index_any(struct BMEditMesh *em, struct BMElem *ele); struct BMElem *EDBM_elem_from_index_any(struct BMEditMesh *em, int index); +int EDBM_elem_to_index_any_multi(struct ViewLayer *view_layer, + struct BMEditMesh *em, + struct BMElem *ele, + int *r_object_index); +struct BMElem *EDBM_elem_from_index_any_multi(struct ViewLayer *view_layer, + int object_index, + int elem_index, + struct Object **r_obedit); + bool edbm_extrude_edges_indiv(struct BMEditMesh *em, struct wmOperator *op, const char hflag, -- cgit v1.2.3