diff options
-rw-r--r-- | source/blender/blenlib/intern/math_base_inline.c | 19 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_queries.c | 35 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_queries.h | 4 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_select.c | 55 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_header.c | 31 |
5 files changed, 104 insertions, 40 deletions
diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index f27da759482..8dccded64d1 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -139,6 +139,25 @@ MINLINE int power_of_2_min_i(int n) return n; } +MINLINE unsigned int highest_order_bit_i(unsigned int n) +{ + n |= (n >> 1); + n |= (n >> 2); + n |= (n >> 4); + n |= (n >> 8); + n |= (n >> 16); + return n - (n >> 1); +} + +MINLINE unsigned short highest_order_bit_s(unsigned short n) +{ + n |= (n >> 1); + n |= (n >> 2); + n |= (n >> 4); + n |= (n >> 8); + return n - (n >> 1); +} + MINLINE float min_ff(float a, float b) { return (a < b) ? a : b; diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 1e1d7d1becb..b37a82c7228 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -1419,3 +1419,38 @@ int BM_face_exists_multi_edge(BMEdge **earr, int len) return ok; } + +/* convenience functiosn for checking flags */ +int BM_edge_is_any_vert_flag_test(BMEdge *e, const char hflag) +{ + return (BM_elem_flag_test(e->v1, hflag) || + BM_elem_flag_test(e->v2, hflag)); +} + +int BM_face_is_any_vert_flag_test(BMFace *f, const char hflag) +{ + BMLoop *l_iter; + BMLoop *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (BM_elem_flag_test(l_iter->v, hflag)) { + return TRUE; + } + } while ((l_iter = l_iter->next) != l_first); + return FALSE; +} + +int BM_face_is_any_edge_flag_test(BMFace *f, const char hflag) +{ + BMLoop *l_iter; + BMLoop *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (BM_elem_flag_test(l_iter->e, hflag)) { + return TRUE; + } + } while ((l_iter = l_iter->next) != l_first); + return FALSE; +} diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index 579a1397b0c..7bb456df8e8 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -100,4 +100,8 @@ void BM_edge_ordered_verts(BMEdge *edge, BMVert **r_v1, BMVert **r_v2); void BM_edge_ordered_verts_ex(BMEdge *edge, BMVert **r_v1, BMVert **r_v2, BMLoop *edge_loop); +int BM_edge_is_any_vert_flag_test(BMEdge *e, const char hflag); +int BM_face_is_any_vert_flag_test(BMFace *f, const char hflag); +int BM_face_is_any_edge_flag_test(BMFace *f, const char hflag); + #endif /* __BMESH_QUERIES_H__ */ diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 92ad0742ec9..2acbbb6e006 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -1881,50 +1881,45 @@ void EDBM_selectmode_convert(BMEditMesh *em, const short selectmode_old, const s BMFace *efa; BMIter iter; + /* first tag-to-select, then select --- this avoids a feedback loop */ + /* have to find out what the selectionmode was previously */ if (selectmode_old == SCE_SELECT_VERTEX) { if (selectmode_new == SCE_SELECT_EDGE) { - /* select all edges associated with every selected vertex */ - eed = BM_iter_new(&iter, em->bm, BM_EDGES_OF_MESH, NULL); - for (; eed; eed = BM_iter_step(&iter)) { - if ((BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) || - BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))) - { + /* select all edges associated with every selected vert */ + BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { + BM_elem_flag_set(eed, BM_ELEM_TAG, BM_edge_is_any_vert_flag_test(eed, BM_ELEM_SELECT)); + } + + BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(eed, BM_ELEM_TAG)) { BM_edge_select_set(em->bm, eed, TRUE); } } } else if (selectmode_new == SCE_SELECT_FACE) { - BMIter liter; - BMLoop *l; - - /* select all faces associated with every selected vertex */ - efa = BM_iter_new(&iter, em->bm, BM_FACES_OF_MESH, NULL); - for (; efa; efa = BM_iter_step(&iter)) { - l = BM_iter_new(&liter, em->bm, BM_LOOPS_OF_FACE, efa); - for (; l; l = BM_iter_step(&liter)) { - if (BM_elem_flag_test(l->v, BM_ELEM_SELECT)) { - BM_face_select_set(em->bm, efa, TRUE); - break; - } + /* select all faces associated with every selected vert */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_elem_flag_set(efa, BM_ELEM_TAG, BM_face_is_any_vert_flag_test(efa, BM_ELEM_SELECT)); + } + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { + BM_face_select_set(em->bm, efa, TRUE); } } } } else if (selectmode_old == SCE_SELECT_EDGE) { if (selectmode_new == SCE_SELECT_FACE) { - BMIter liter; - BMLoop *l; - - /* select all faces associated with every selected vertex */ - efa = BM_iter_new(&iter, em->bm, BM_FACES_OF_MESH, NULL); - for (; efa; efa = BM_iter_step(&iter)) { - l = BM_iter_new(&liter, em->bm, BM_LOOPS_OF_FACE, efa); - for (; l; l = BM_iter_step(&liter)) { - if (BM_elem_flag_test(l->v, BM_ELEM_SELECT)) { - BM_face_select_set(em->bm, efa, TRUE); - break; - } + /* select all faces associated with every selected edge */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_elem_flag_set(efa, BM_ELEM_TAG, BM_face_is_any_edge_flag_test(efa, BM_ELEM_SELECT)); + } + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { + BM_face_select_set(em->bm, efa, TRUE); } } } diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index d8fcc7e12e7..7acb371041c 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -319,7 +319,7 @@ static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event) View3D *v3d = sa->spacedata.first; Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = NULL; - int ctrl = win->eventstate->ctrl, shift = win->eventstate->shift; + const int ctrl = win->eventstate->ctrl, shift = win->eventstate->shift; PointerRNA props_ptr; if (obedit && obedit->type == OB_MESH) { @@ -348,8 +348,11 @@ static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event) case B_SEL_EDGE: if (em) { if (shift == 0 || em->selectmode == 0) { - if ((em->selectmode ^ SCE_SELECT_EDGE) == SCE_SELECT_VERTEX) { - if (ctrl) EDBM_selectmode_convert(em, SCE_SELECT_VERTEX, SCE_SELECT_EDGE); + if (ctrl) { + const short selmode_max = highest_order_bit_s(ts->selectmode); + if (selmode_max == SCE_SELECT_VERTEX) { + EDBM_selectmode_convert(em, selmode_max, SCE_SELECT_EDGE); + } } em->selectmode = SCE_SELECT_EDGE; } @@ -362,11 +365,13 @@ static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event) case B_SEL_FACE: if (em) { if (shift == 0 || em->selectmode == 0) { - if (((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_VERTEX) || - ((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_EDGE)) - { - if (ctrl) EDBM_selectmode_convert(em, (ts->selectmode ^ SCE_SELECT_FACE), SCE_SELECT_FACE); + if (ctrl) { + const short selmode_max = highest_order_bit_s(ts->selectmode); + if (ELEM(selmode_max, SCE_SELECT_VERTEX, SCE_SELECT_EDGE)) { + EDBM_selectmode_convert(em, selmode_max, SCE_SELECT_FACE); + } } + em->selectmode = SCE_SELECT_FACE; } ts->selectmode = em->selectmode; @@ -430,9 +435,15 @@ void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C) row = uiLayoutRow(layout, TRUE); block = uiLayoutGetBlock(row); - uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL, 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Vertex select - Shift-Click for multiple modes"); - uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL, 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Edge select - Shift-Click for multiple modes"); - uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL, 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Face select - Shift-Click for multiple modes"); + uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL, + 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, + "Vertex select - Shift-Click for multiple modes"); + uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL, + 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, + "Edge select - Shift-Click for multiple modes, Ctrl-Click expands selection"); + uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL, + 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, + "Face select - Shift-Click for multiple modes, Ctrl-Click expands selection"); } } |