From ca1bca442ab3ae6ab4332a24a784a1c79bde4e27 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 25 Aug 2014 16:48:47 +1000 Subject: Fix T40993: Store selection history for extrude --- source/blender/bmesh/intern/bmesh_marking.c | 21 +++ source/blender/bmesh/intern/bmesh_marking.h | 7 + source/blender/bmesh/intern/bmesh_opdefines.c | 5 + source/blender/bmesh/intern/bmesh_operator_api.h | 3 +- source/blender/bmesh/intern/bmesh_operators.c | 5 +- source/blender/bmesh/operators/bmo_dupe.c | 11 ++ source/blender/bmesh/operators/bmo_extrude.c | 64 +++++++- .../blender/bmesh/operators/bmo_fill_attribute.c | 2 +- source/blender/editors/mesh/editmesh_extrude.c | 182 +++++++++++++-------- source/blender/editors/mesh/editmesh_tools.c | 23 +-- source/blender/editors/mesh/editmesh_utils.c | 9 + 11 files changed, 239 insertions(+), 93 deletions(-) (limited to 'source') diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c index e23a5721234..cde842cab3e 100644 --- a/source/blender/bmesh/intern/bmesh_marking.c +++ b/source/blender/bmesh/intern/bmesh_marking.c @@ -899,6 +899,27 @@ bool BM_select_history_active_get(BMesh *bm, BMEditSelection *ese) return true; } +/** + * Return a map from BMVert/Edge/Face -> BMEditSelection + */ +GHash *BM_select_history_map_create(BMesh *bm) +{ + BMEditSelection *ese; + GHash *map; + + if (BLI_listbase_is_empty(&bm->selected)) { + return NULL; + } + + map = BLI_ghash_ptr_new(__func__); + + for (ese = bm->selected.first; ese; ese = ese->next) { + BLI_ghash_insert(map, ese->ele, ese); + } + + return map; +} + void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hflag, const bool respecthide, const bool overwrite, const char hflag_test) { diff --git a/source/blender/bmesh/intern/bmesh_marking.h b/source/blender/bmesh/intern/bmesh_marking.h index 655ace6de5f..9e0c0923164 100644 --- a/source/blender/bmesh/intern/bmesh_marking.h +++ b/source/blender/bmesh/intern/bmesh_marking.h @@ -100,5 +100,12 @@ void _bm_select_history_store_after_notest(BMesh *bm, BMEditSelection *ese_ref, void BM_select_history_validate(BMesh *bm); void BM_select_history_clear(BMesh *bm); bool BM_select_history_active_get(BMesh *bm, struct BMEditSelection *ese); +struct GHash *BM_select_history_map_create(BMesh *bm); + +#define BM_SELECT_HISTORY_BACKUP(bm) { \ + ListBase _bm_prev_selected = (bm)->selected; BLI_listbase_clear(&(bm)->selected) + +#define BM_SELECT_HISTORY_RESTORE(bm) \ + (bm)->selected = _bm_prev_selected; } (void)0 #endif /* __BMESH_MARKING_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 5e568f88843..886181cd204 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -854,6 +854,7 @@ static BMOpDefine bmo_extrude_discrete_faces_def = { "extrude_discrete_faces", /* slots_in */ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */ {{'\0'}}, }, /* slots_out */ @@ -874,6 +875,7 @@ static BMOpDefine bmo_extrude_edge_only_def = { "extrude_edge_only", /* slots_in */ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input vertices */ + {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */ {{'\0'}}, }, /* slots_out */ @@ -893,6 +895,7 @@ static BMOpDefine bmo_extrude_vert_indiv_def = { "extrude_vert_indiv", /* slots_in */ {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */ {{'\0'}}, }, /* slots_out */ @@ -982,6 +985,7 @@ static BMOpDefine bmo_extrude_face_region_def = { {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* edges and faces */ {"edges_exclude", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_EMPTY}}, {"use_keep_orig", BMO_OP_SLOT_BOOL}, /* keep original geometry */ + {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */ {{'\0'}}, }, /* slots_out */ @@ -1267,6 +1271,7 @@ static BMOpDefine bmo_duplicate_def = { {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* destination bmesh, if NULL will use current on */ {"dest", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_BMESH}}, + {"use_select_history", BMO_OP_SLOT_BOOL}, {{'\0'}}, }, /* slots_out */ diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index ef4990ab56e..287aafc8f9f 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -338,7 +338,8 @@ void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *op, const char htype, cons void BMO_mesh_selected_remap(BMesh *bm, BMOpSlot *slot_vert_map, BMOpSlot *slot_edge_map, - BMOpSlot *slot_face_map); + BMOpSlot *slot_face_map, + const bool check_select); /* copies the values from another slot to the end of the output slot */ #define BMO_slot_buffer_append(op_src, slots_src, slot_name_src, \ diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index 7f872613896..6bca5ca7a43 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -605,7 +605,8 @@ void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char hty void BMO_mesh_selected_remap(BMesh *bm, BMOpSlot *slot_vert_map, BMOpSlot *slot_edge_map, - BMOpSlot *slot_face_map) + BMOpSlot *slot_face_map, + const bool check_select) { if (bm->selected.first) { BMEditSelection *ese, *ese_next; @@ -623,7 +624,7 @@ void BMO_mesh_selected_remap(BMesh *bm, ese->ele = BMO_slot_map_elem_get(slot_elem_map, ese->ele); if (UNLIKELY((ese->ele == NULL) || - (BM_elem_flag_test(ese->ele, BM_ELEM_SELECT) == false))) + (check_select && (BM_elem_flag_test(ese->ele, BM_ELEM_SELECT) == false)))) { BLI_remlink(&bm->selected, ese); MEM_freeN(ese); diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c index 794c688b26b..cd5592f08c9 100644 --- a/source/blender/bmesh/operators/bmo_dupe.c +++ b/source/blender/bmesh/operators/bmo_dupe.c @@ -183,6 +183,7 @@ static BMFace *bmo_face_copy(BMOperator *op, */ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_dst, BMesh *bm_src) { + const bool use_select_history = BMO_slot_bool_get(op->slots_in, "use_select_history"); BMVert *v = NULL, *v2; BMEdge *e = NULL; @@ -285,6 +286,16 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_dst, BMesh *bm_src) /* free pointer hashes */ BLI_ghash_free(vhash, NULL, NULL); BLI_ghash_free(ehash, NULL, NULL); + + if (use_select_history) { + BLI_assert(bm_src == bm_dst); + BMO_mesh_selected_remap( + bm_dst, + slot_vert_map_out, + slot_edge_map_out, + slot_face_map_out, + false); + } } /** diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c index 510c3ae0078..88b53b63abb 100644 --- a/source/blender/bmesh/operators/bmo_extrude.c +++ b/source/blender/bmesh/operators/bmo_extrude.c @@ -53,9 +53,16 @@ enum { void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op) { + const bool use_select_history = BMO_slot_bool_get(op->slots_in, "use_select_history"); + GHash *select_history_map = NULL; + BMOIter siter; BMFace *f_org; + if (use_select_history) { + select_history_map = BM_select_history_map_create(bm); + } + BMO_ITER (f_org, &siter, op->slots_in, "faces", BM_FACE) { BMFace *f_new; BMLoop *l_org, *l_org_first; @@ -66,6 +73,14 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op) f_new = BM_face_copy(bm, bm, f_org, true, true); BMO_elem_flag_enable(bm, f_new, EXT_KEEP); + if (select_history_map) { + BMEditSelection *ese; + ese = BLI_ghash_lookup(select_history_map, f_org); + if (ese) { + ese->ele = (BMElem *)f_new; + } + } + l_org = l_org_first = BM_FACE_FIRST_LOOP(f_org); l_new = BM_FACE_FIRST_LOOP(f_new); @@ -85,10 +100,28 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op) BM_elem_attrs_copy(bm, bm, l_org->next, l_side_iter); l_side_iter = l_side_iter->next; BM_elem_attrs_copy(bm, bm, l_org, l_side_iter); l_side_iter = l_side_iter->next; BM_elem_attrs_copy(bm, bm, l_org, l_side_iter); + + if (select_history_map) { + BMEditSelection *ese; + + ese = BLI_ghash_lookup(select_history_map, l_org->v); + if (ese) { + ese->ele = (BMElem *)l_new->v; + } + ese = BLI_ghash_lookup(select_history_map, l_org->e); + if (ese) { + ese->ele = (BMElem *)l_new->e; + } + } + } while (((l_new = l_new->next), (l_org = l_org->next)) != l_org_first); } + if (select_history_map) { + BLI_ghash_free(select_history_map, NULL, NULL); + } + BMO_op_callf(bm, op->flag, "delete geom=%ff context=%i", EXT_DEL, DEL_ONLYFACES); @@ -157,7 +190,11 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op) BMO_elem_flag_enable(bm, e->v2, EXT_INPUT); } - BMO_op_initf(bm, &dupeop, op->flag, "duplicate geom=%fve", EXT_INPUT); + BMO_op_initf( + bm, &dupeop, op->flag, + "duplicate geom=%fve use_select_history=%b", + EXT_INPUT, BMO_slot_bool_get(op->slots_in, "use_select_history")); + BMO_op_exec(bm, &dupeop); /* disable root flag on all new skin nodes */ @@ -205,10 +242,16 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op) void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op) { + const bool use_select_history = BMO_slot_bool_get(op->slots_in, "use_select_history"); BMOIter siter; BMVert *v, *dupev; BMEdge *e; const bool has_vskin = CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN); + GHash *select_history_map = NULL; + + if (use_select_history) { + select_history_map = BM_select_history_map_create(bm); + } for (v = BMO_iter_new(&siter, op->slots_in, "verts", BM_VERT); v; v = BMO_iter_step(&siter)) { dupev = BM_vert_create(bm, v->co, v, BM_CREATE_NOP); @@ -217,6 +260,14 @@ void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op) if (has_vskin) bm_extrude_disable_skin_root(bm, v); + if (select_history_map) { + BMEditSelection *ese; + ese = BLI_ghash_lookup(select_history_map, v); + if (ese) { + ese->ele = (BMElem *)dupev; + } + } + /* not essential, but ensures face normals from extruded edges are contiguous */ if (BM_vert_is_wire_endpoint(v)) { if (v->e->v1 == v) { @@ -228,6 +279,10 @@ void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op) BMO_elem_flag_enable(bm, e, EXT_KEEP); } + if (select_history_map) { + BLI_ghash_free(select_history_map, NULL, NULL); + } + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, EXT_KEEP); BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EXT_KEEP); } @@ -245,8 +300,11 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) BMOpSlot *slot_edges_exclude; /* initialize our sub-operators */ - BMO_op_init(bm, &dupeop, op->flag, "duplicate"); - + BMO_op_initf( + bm, &dupeop, op->flag, + "duplicate use_select_history=%b", + BMO_slot_bool_get(op->slots_in, "use_select_history")); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "geom", BM_EDGE | BM_FACE, EXT_INPUT); /* if one flagged face is bordered by an un-flagged face, then we delete diff --git a/source/blender/bmesh/operators/bmo_fill_attribute.c b/source/blender/bmesh/operators/bmo_fill_attribute.c index fa77e6b509c..d9f50ac891c 100644 --- a/source/blender/bmesh/operators/bmo_fill_attribute.c +++ b/source/blender/bmesh/operators/bmo_fill_attribute.c @@ -154,7 +154,7 @@ static unsigned int bmesh_face_attribute_fill(BMesh *bm, return face_tot; } -void bmo_face_attribute_fill_exec(BMesh *bm, BMOperator *op) +void bmo_face_attribute_fill_exec(BMesh *bm, BMOperator *op) { const bool use_normals = BMO_slot_bool_get(op->slots_in, "use_normals"); const bool use_data = BMO_slot_bool_get(op->slots_in, "use_data"); diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c index 595c43c1060..3e403387a67 100644 --- a/source/blender/editors/mesh/editmesh_extrude.c +++ b/source/blender/editors/mesh/editmesh_extrude.c @@ -33,6 +33,7 @@ #include "DNA_object_types.h" #include "BLI_math.h" +#include "BLI_listbase.h" #include "BKE_context.h" #include "BKE_global.h" @@ -65,6 +66,75 @@ static void add_normal_aligned(float nor[3], const float add[3]) } } +static void edbm_extrude_edge_exclude_mirror( + Object *obedit, BMEditMesh *em, + const char hflag, + BMOperator *op, BMOpSlot *slot_edges_exclude) +{ + BMesh *bm = em->bm; + ModifierData *md; + + /* If a mirror modifier with clipping is on, we need to adjust some + * of the cases above to handle edges on the line of symmetry. + */ + for (md = obedit->modifiers.first; md; md = md->next) { + if ((md->type == eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) { + MirrorModifierData *mmd = (MirrorModifierData *) md; + + if (mmd->flag & MOD_MIR_CLIPPING) { + BMIter iter; + BMEdge *edge; + + float mtx[4][4]; + if (mmd->mirror_ob) { + float imtx[4][4]; + invert_m4_m4(imtx, mmd->mirror_ob->obmat); + mul_m4_m4m4(mtx, imtx, obedit->obmat); + } + + BM_ITER_MESH (edge, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(edge, hflag) && + BM_edge_is_boundary(edge) && + BM_elem_flag_test(edge->l->f, hflag)) + { + float co1[3], co2[3]; + + copy_v3_v3(co1, edge->v1->co); + copy_v3_v3(co2, edge->v2->co); + + if (mmd->mirror_ob) { + mul_v3_m4v3(co1, mtx, co1); + mul_v3_m4v3(co2, mtx, co2); + } + + if (mmd->flag & MOD_MIR_AXIS_X) { + if ((fabsf(co1[0]) < mmd->tolerance) && + (fabsf(co2[0]) < mmd->tolerance)) + { + BMO_slot_map_empty_insert(op, slot_edges_exclude, edge); + } + } + if (mmd->flag & MOD_MIR_AXIS_Y) { + if ((fabsf(co1[1]) < mmd->tolerance) && + (fabsf(co2[1]) < mmd->tolerance)) + { + BMO_slot_map_empty_insert(op, slot_edges_exclude, edge); + } + } + if (mmd->flag & MOD_MIR_AXIS_Z) { + if ((fabsf(co1[2]) < mmd->tolerance) && + (fabsf(co2[2]) < mmd->tolerance)) + { + BMO_slot_map_empty_insert(op, slot_edges_exclude, edge); + } + } + } + } + } + } + } +} + /* individual face extrude */ /* will use vertex normals for extrusion directions, so *nor is unaffected */ static short edbm_extrude_discrete_faces(BMEditMesh *em, wmOperator *op, const char hflag, float *UNUSED(nor)) @@ -75,7 +145,10 @@ static short edbm_extrude_discrete_faces(BMEditMesh *em, wmOperator *op, const c BMLoop *l; BMOperator bmop; - EDBM_op_init(em, &bmop, op, "extrude_discrete_faces faces=%hf", hflag); + EDBM_op_init( + em, &bmop, op, + "extrude_discrete_faces faces=%hf use_select_history=%b", + hflag, true); /* deselect original verts */ EDBM_flag_disable_all(em, BM_ELEM_SELECT); @@ -101,12 +174,18 @@ static short edbm_extrude_discrete_faces(BMEditMesh *em, wmOperator *op, const c /* extrudes individual edges */ static short edbm_extrude_edges_indiv(BMEditMesh *em, wmOperator *op, const char hflag, float *UNUSED(nor)) { + BMesh *bm = em->bm; BMOperator bmop; - EDBM_op_init(em, &bmop, op, "extrude_edge_only edges=%he", hflag); + EDBM_op_init( + em, &bmop, op, + "extrude_edge_only edges=%he use_select_history=%b", + hflag, true); /* deselect original verts */ + BM_SELECT_HISTORY_BACKUP(bm); EDBM_flag_disable_all(em, BM_ELEM_SELECT); + BM_SELECT_HISTORY_RESTORE(bm); BMO_op_exec(em->bm, &bmop); BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_VERT | BM_EDGE, BM_ELEM_SELECT, true); @@ -123,7 +202,10 @@ static short edbm_extrude_verts_indiv(BMEditMesh *em, wmOperator *op, const char { BMOperator bmop; - EDBM_op_init(em, &bmop, op, "extrude_vert_indiv verts=%hv", hflag); + EDBM_op_init( + em, &bmop, op, + "extrude_vert_indiv verts=%hv use_select_history=%b", + hflag, true); /* deselect original verts */ BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_in, "verts", BM_VERT, BM_ELEM_SELECT, true); @@ -138,82 +220,32 @@ static short edbm_extrude_verts_indiv(BMEditMesh *em, wmOperator *op, const char return 'g'; /* g is grab */ } -static short edbm_extrude_edge(Object *obedit, BMEditMesh *em, const char hflag, float nor[3]) +static short edbm_extrude_edge_ex( + Object *obedit, BMEditMesh *em, + const char hflag, float nor[3], + const bool use_mirror, + const bool use_select_history) { BMesh *bm = em->bm; - BMIter iter; BMOIter siter; BMOperator extop; - BMEdge *edge; BMFace *f; - ModifierData *md; BMElem *ele; - BMOpSlot *slot_edges_exclude; BMO_op_init(bm, &extop, BMO_FLAG_DEFAULTS, "extrude_face_region"); + BMO_slot_bool_set(extop.slots_in, "use_select_history", use_select_history); BMO_slot_buffer_from_enabled_hflag(bm, &extop, extop.slots_in, "geom", BM_VERT | BM_EDGE | BM_FACE, hflag); - slot_edges_exclude = BMO_slot_get(extop.slots_in, "edges_exclude"); + if (use_mirror) { + BMOpSlot *slot_edges_exclude; + slot_edges_exclude = BMO_slot_get(extop.slots_in, "edges_exclude"); - /* If a mirror modifier with clipping is on, we need to adjust some - * of the cases above to handle edges on the line of symmetry. - */ - md = obedit->modifiers.first; - for (; md; md = md->next) { - if ((md->type == eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) { - MirrorModifierData *mmd = (MirrorModifierData *) md; - - if (mmd->flag & MOD_MIR_CLIPPING) { - float mtx[4][4]; - if (mmd->mirror_ob) { - float imtx[4][4]; - invert_m4_m4(imtx, mmd->mirror_ob->obmat); - mul_m4_m4m4(mtx, imtx, obedit->obmat); - } - - BM_ITER_MESH (edge, &iter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(edge, hflag) && - BM_edge_is_boundary(edge) && - BM_elem_flag_test(edge->l->f, hflag)) - { - float co1[3], co2[3]; - - copy_v3_v3(co1, edge->v1->co); - copy_v3_v3(co2, edge->v2->co); - - if (mmd->mirror_ob) { - mul_v3_m4v3(co1, mtx, co1); - mul_v3_m4v3(co2, mtx, co2); - } - - if (mmd->flag & MOD_MIR_AXIS_X) { - if ((fabsf(co1[0]) < mmd->tolerance) && - (fabsf(co2[0]) < mmd->tolerance)) - { - BMO_slot_map_empty_insert(&extop, slot_edges_exclude, edge); - } - } - if (mmd->flag & MOD_MIR_AXIS_Y) { - if ((fabsf(co1[1]) < mmd->tolerance) && - (fabsf(co2[1]) < mmd->tolerance)) - { - BMO_slot_map_empty_insert(&extop, slot_edges_exclude, edge); - } - } - if (mmd->flag & MOD_MIR_AXIS_Z) { - if ((fabsf(co1[2]) < mmd->tolerance) && - (fabsf(co2[2]) < mmd->tolerance)) - { - BMO_slot_map_empty_insert(&extop, slot_edges_exclude, edge); - } - } - } - } - } - } + edbm_extrude_edge_exclude_mirror(obedit, em, hflag, &extop, slot_edges_exclude); } + BM_SELECT_HISTORY_BACKUP(bm); EDBM_flag_disable_all(em, BM_ELEM_SELECT); + BM_SELECT_HISTORY_RESTORE(bm); BMO_op_exec(bm, &extop); @@ -236,6 +268,13 @@ static short edbm_extrude_edge(Object *obedit, BMEditMesh *em, const char hflag, return is_zero_v3(nor) ? 'g' : 'n'; } +static short edbm_extrude_edge( + Object *obedit, BMEditMesh *em, + const char hflag, float nor[3]) +{ + return edbm_extrude_edge_ex(obedit, em, hflag, nor, true, true); +} + static short edbm_extrude_vert(Object *obedit, BMEditMesh *em, const char hflag, float nor[3]) { BMIter iter; @@ -288,13 +327,12 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op) mul_m3_v3(tmat, dvec); for (a = 0; a < steps; a++) { - edbm_extrude_edge(obedit, em, BM_ELEM_SELECT, nor); - //BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, "extrude_face_region geom=%hef", BM_ELEM_SELECT); - BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, - "translate vec=%v verts=%hv", - dvec, BM_ELEM_SELECT); - //extrudeflag(obedit, em, SELECT, nor); - //translateflag(em, SELECT, dvec); + edbm_extrude_edge_ex(obedit, em, BM_ELEM_SELECT, nor, false, false); + + BMO_op_callf( + em->bm, BMO_FLAG_DEFAULTS, + "translate vec=%v verts=%hv", + dvec, BM_ELEM_SELECT); } EDBM_mesh_normals_update(em); diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 92bbd9482e2..12b6428f0fe 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -1019,28 +1019,23 @@ static int edbm_duplicate_exec(bContext *C, wmOperator *op) BMEditMesh *em = BKE_editmesh_from_object(ob); BMesh *bm = em->bm; BMOperator bmop; - ListBase bm_selected_store = {NULL, NULL}; - /* de-select all would clear otherwise */ - SWAP(ListBase, bm->selected, bm_selected_store); + EDBM_op_init( + em, &bmop, op, + "duplicate geom=%hvef use_select_history=%b", + BM_ELEM_SELECT, true); - EDBM_op_init(em, &bmop, op, "duplicate geom=%hvef", BM_ELEM_SELECT); - BMO_op_exec(bm, &bmop); + + /* de-select all would clear otherwise */ + BM_SELECT_HISTORY_BACKUP(bm); + EDBM_flag_disable_all(em, BM_ELEM_SELECT); BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true); /* rebuild editselection */ - bm->selected = bm_selected_store; - - if (bm->selected.first) { - BMOpSlot *slot_vert_map_out = BMO_slot_get(bmop.slots_out, "vert_map.out"); - BMOpSlot *slot_edge_map_out = BMO_slot_get(bmop.slots_out, "edge_map.out"); - BMOpSlot *slot_face_map_out = BMO_slot_get(bmop.slots_out, "face_map.out"); - - BMO_mesh_selected_remap(bm, slot_vert_map_out, slot_edge_map_out, slot_face_map_out); - } + BM_SELECT_HISTORY_RESTORE(bm); if (!EDBM_op_finish(em, &bmop, op, true)) { return OPERATOR_CANCELLED; diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 8adaae5fe42..c7d1d883537 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -1328,6 +1328,15 @@ void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_d /* don't keep stale derivedMesh data around, see: [#38872] */ BKE_editmesh_free_derivedmesh(em); + +#ifdef DEBUG + { + BMEditSelection *ese; + for (ese = em->bm->selected.first; ese; ese = ese->next) { + BLI_assert(BM_elem_flag_test(ese->ele, BM_ELEM_SELECT)); + } + } +#endif } /* poll call for mesh operators requiring a view3d context */ -- cgit v1.2.3