diff options
author | Campbell Barton <ideasman42@gmail.com> | 2014-03-07 03:10:23 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2014-03-07 03:39:31 +0400 |
commit | 276ef3b3b5192aad5c3e5e02c69246818f89033b (patch) | |
tree | e996807504d949a58b0f4d464b8017f294d124f3 | |
parent | a7a7a032a6b6eb63a5d3798b1bd893b9cc32cb38 (diff) |
Editmesh: Toggle between all edge-loop boundaries when selecting
Now Alt+RMB,RMB will select all connected boundaries.
There are times when you just want to select an entire boundary loop
ignoring face topology, previously there was no way to do this.
-rw-r--r-- | source/blender/editors/mesh/editmesh_select.c | 110 |
1 files changed, 95 insertions, 15 deletions
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 0c7810ab52a..41546e7bf07 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -1007,6 +1007,34 @@ void MESH_OT_select_mode(wmOperatorType *ot) /* **************** LOOP SELECTS *************** */ +static void walker_select_count(BMEditMesh *em, int walkercode, void *start, const bool select, const bool select_mix, + int *r_totsel, int *r_totunsel) +{ + BMesh *bm = em->bm; + BMElem *ele; + BMWalker walker; + int tot[2] = {0, 0}; + + BMW_init(&walker, bm, walkercode, + BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP, + BMW_FLAG_TEST_HIDDEN, + BMW_NIL_LAY); + + for (ele = BMW_begin(&walker, start); ele; ele = BMW_step(&walker)) { + tot[(BM_elem_flag_test_bool(ele, BM_ELEM_SELECT) != select)] += 1; + + if (!select_mix && tot[0] && tot[1]) { + tot[0] = tot[1] = -1; + break; + } + } + + *r_totsel = tot[0]; + *r_totunsel = tot[1]; + + BMW_end(&walker); +} + static void walker_select(BMEditMesh *em, int walkercode, void *start, const bool select) { BMesh *bm = em->bm; @@ -1101,12 +1129,68 @@ void MESH_OT_loop_multi_select(wmOperatorType *ot) /* ***************** loop select (non modal) ************** */ +static void mouse_mesh_loop_face(BMEditMesh *em, BMEdge *eed, bool select, bool select_clear) +{ + if (select_clear) { + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + } + + walker_select(em, BMW_FACELOOP, eed, select); +} + +static void mouse_mesh_loop_edge_ring(BMEditMesh *em, BMEdge *eed, bool select, bool select_clear) +{ + if (select_clear) { + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + } + + walker_select(em, BMW_EDGERING, eed, select); +} + +static void mouse_mesh_loop_edge(BMEditMesh *em, BMEdge *eed, bool select, bool select_clear, bool select_cycle) +{ + bool edge_boundary = false; + + /* cycle between BMW_LOOP / BMW_EDGEBOUNDARY */ + if (select_cycle && BM_edge_is_boundary(eed)) { + int tot[2]; + + /* if the loops selected toggle the boundaries */ + walker_select_count(em, BMW_LOOP, eed, select, false, + &tot[0], &tot[1]); + if (tot[select] == 0) { + edge_boundary = true; + + /* if the boundaries selected, toggle back to the loop */ + walker_select_count(em, BMW_EDGEBOUNDARY, eed, select, false, + &tot[0], &tot[1]); + if (tot[select] == 0) { + edge_boundary = false; + } + } + } + + if (select_clear) { + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + } + + if (edge_boundary) { + walker_select(em, BMW_EDGEBOUNDARY, eed, select); + } + else { + walker_select(em, BMW_LOOP, eed, select); + } +} + + static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle, bool ring) { ViewContext vc; BMEditMesh *em; BMEdge *eed; bool select = true; + bool select_clear = false; + bool select_cycle = true; float dist = 50.0f; float mvalf[2]; @@ -1124,7 +1208,7 @@ static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool de } if (extend == false && deselect == false && toggle == false) { - EDBM_flag_disable_all(em, BM_ELEM_SELECT); + select_clear = true; } if (extend) { @@ -1133,28 +1217,24 @@ static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool de else if (deselect) { select = false; } - else if (BM_elem_flag_test(eed, BM_ELEM_SELECT) == 0) { + else if (select_clear || (BM_elem_flag_test(eed, BM_ELEM_SELECT) == 0)) { select = true; } else if (toggle) { select = false; + select_cycle = false; } if (em->selectmode & SCE_SELECT_FACE) { - walker_select(em, BMW_FACELOOP, eed, select); - } - else if (em->selectmode & SCE_SELECT_EDGE) { - if (ring) - walker_select(em, BMW_EDGERING, eed, select); - else - walker_select(em, BMW_LOOP, eed, select); + mouse_mesh_loop_face(em, eed, select, select_clear); } - else if (em->selectmode & SCE_SELECT_VERTEX) { - if (ring) - walker_select(em, BMW_EDGERING, eed, select); - - else - walker_select(em, BMW_LOOP, eed, select); + else { + if (ring) { + mouse_mesh_loop_edge_ring(em, eed, select, select_clear); + } + else { + mouse_mesh_loop_edge(em, eed, select, select_clear, select_cycle); + } } EDBM_selectmode_flush(em); |