Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c54
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.h4
-rw-r--r--source/blender/editors/mesh/editmesh_select.c101
3 files changed, 133 insertions, 26 deletions
diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
index 5a0aae28175..f240a10efc8 100644
--- a/source/blender/bmesh/intern/bmesh_queries.c
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -1799,6 +1799,60 @@ bool BM_face_exists_overlap_subset(BMVert **varr, const int len)
return is_overlap;
}
+bool BM_vert_is_all_edge_flag_test(const BMVert *v, const char hflag, const bool respect_hide)
+{
+ if (v->e) {
+ BMEdge *e_other;
+ BMIter eiter;
+
+ BM_ITER_ELEM (e_other, &eiter, (BMVert *)v, BM_EDGES_OF_VERT) {
+ if (!respect_hide || !BM_elem_flag_test(e_other, BM_ELEM_HIDDEN)) {
+ if (!BM_elem_flag_test(e_other, hflag)) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+bool BM_vert_is_all_face_flag_test(const BMVert *v, const char hflag, const bool respect_hide)
+{
+ if (v->e) {
+ BMEdge *f_other;
+ BMIter fiter;
+
+ BM_ITER_ELEM (f_other, &fiter, (BMVert *)v, BM_FACES_OF_VERT) {
+ if (!respect_hide || !BM_elem_flag_test(f_other, BM_ELEM_HIDDEN)) {
+ if (!BM_elem_flag_test(f_other, hflag)) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+
+bool BM_edge_is_all_face_flag_test(const BMEdge *e, const char hflag, const bool respect_hide)
+{
+ if (e->l) {
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = e->l;
+ do {
+ if (!respect_hide || !BM_elem_flag_test(l_iter->f, BM_ELEM_HIDDEN)) {
+ if (!BM_elem_flag_test(l_iter->f, hflag)) {
+ return false;
+ }
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+
+ return true;
+}
/* convenience functions for checking flags */
bool BM_edge_is_any_vert_flag_test(const BMEdge *e, const char hflag)
diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h
index d4b6cd0e061..36e67a73f1f 100644
--- a/source/blender/bmesh/intern/bmesh_queries.h
+++ b/source/blender/bmesh/intern/bmesh_queries.h
@@ -119,6 +119,10 @@ void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2);
void BM_edge_ordered_verts_ex(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2,
const BMLoop *edge_loop);
+bool BM_vert_is_all_edge_flag_test(const BMVert *v, const char hflag, const bool respect_hide);
+bool BM_vert_is_all_face_flag_test(const BMVert *v, const char hflag, const bool respect_hide);
+bool BM_edge_is_all_face_flag_test(const BMEdge *e, const char hflag, const bool respect_hide);
+
bool BM_edge_is_any_vert_flag_test(const BMEdge *e, const char hflag);
bool BM_face_is_any_vert_flag_test(const BMFace *f, const char hflag);
bool BM_face_is_any_edge_flag_test(const BMFace *f, const char hflag);
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 37267d1e54b..37b93c8c282 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -1647,12 +1647,24 @@ void EDBM_selectmode_set(BMEditMesh *em)
}
/**
+ * Expand & Contract the Selection
+ * (used when chaning modes and Ctrl key held)
+ *
* Flush the selection up:
* - vert -> edge
+ * - vert -> face
* - edge -> face
+ *
+ * Flush the selection down:
+ * - face -> edge
+ * - face -> vert
+ * - edge -> vert
*/
void EDBM_selectmode_convert(BMEditMesh *em, const short selectmode_old, const short selectmode_new)
{
+ BMesh *bm = em->bm;
+
+ BMVert *eve;
BMEdge *eed;
BMFace *efa;
BMIter iter;
@@ -1661,54 +1673,96 @@ void EDBM_selectmode_convert(BMEditMesh *em, const short selectmode_old, const s
/* have to find out what the selectionmode was previously */
if (selectmode_old == SCE_SELECT_VERTEX) {
- if (em->bm->totvertsel == 0) {
+ if (bm->totvertsel == 0) {
/* pass */
}
else if (selectmode_new == SCE_SELECT_EDGE) {
+ /* flush up (vert -> edge) */
+
/* select all edges associated with every selected vert */
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ BM_ITER_MESH (eed, &iter, 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) {
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(eed, BM_ELEM_TAG)) {
- BM_edge_select_set(em->bm, eed, true);
+ BM_edge_select_set(bm, eed, true);
}
}
}
else if (selectmode_new == SCE_SELECT_FACE) {
+ /* flush up (vert -> face) */
+
/* select all faces associated with every selected vert */
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BM_ITER_MESH (efa, &iter, 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) {
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
- BM_face_select_set(em->bm, efa, true);
+ BM_face_select_set(bm, efa, true);
}
}
}
}
else if (selectmode_old == SCE_SELECT_EDGE) {
- if (em->bm->totedgesel == 0) {
+ if (bm->totedgesel == 0) {
/* pass */
}
else if (selectmode_new == SCE_SELECT_FACE) {
+ /* flush up (edge -> face) */
+
/* select all faces associated with every selected edge */
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BM_ITER_MESH (efa, &iter, 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) {
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
- BM_face_select_set(em->bm, efa, true);
+ BM_face_select_set(bm, efa, true);
+ }
+ }
+ }
+ else if (selectmode_new == SCE_SELECT_VERTEX) {
+ /* flush down (edge -> vert) */
+
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_vert_is_all_edge_flag_test(eve, BM_ELEM_SELECT, true)) {
+ BM_vert_select_set(bm, eve, false);
}
}
+ /* deselect edges without both verts selected */
+ BM_mesh_deselect_flush(bm);
+ }
+ }
+ else if (selectmode_old == SCE_SELECT_FACE) {
+ if (bm->totfacesel == 0) {
+ /* pass */
+ }
+ else if (selectmode_new == SCE_SELECT_EDGE) {
+ /* flush down (face -> edge) */
+
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ if (!BM_edge_is_all_face_flag_test(eed, BM_ELEM_SELECT, true)) {
+ BM_edge_select_set(bm, eed, false);
+ }
+ }
+ }
+ else if (selectmode_new == SCE_SELECT_VERTEX) {
+ /* flush down (face -> vert) */
+
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_vert_is_all_face_flag_test(eve, BM_ELEM_SELECT, true)) {
+ BM_vert_select_set(bm, eve, false);
+ }
+ }
+ /* deselect faces without verts selected */
+ BM_mesh_deselect_flush(bm);
}
}
}
-/* user facing function, does notification and undo push */
+/* user facing function, does notification */
bool EDBM_selectmode_toggle(bContext *C, const short selectmode_new,
const int action, const bool use_extend, const bool use_expand)
{
@@ -1755,22 +1809,24 @@ bool EDBM_selectmode_toggle(bContext *C, const short selectmode_new,
break;
}
+ if (use_extend == 0 || em->selectmode == 0) {
+ if (use_expand) {
+ const short selmode_max = highest_order_bit_s(ts->selectmode);
+ EDBM_selectmode_convert(em, selmode_max, selectmode_new);
+ }
+ }
+
switch (selectmode_new) {
case SCE_SELECT_VERTEX:
- if (use_extend == 0 || em->selectmode == 0)
+ if (use_extend == 0 || em->selectmode == 0) {
em->selectmode = SCE_SELECT_VERTEX;
+ }
ts->selectmode = em->selectmode;
EDBM_selectmode_set(em);
ret = true;
break;
case SCE_SELECT_EDGE:
if (use_extend == 0 || em->selectmode == 0) {
- if (use_expand) {
- 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;
}
ts->selectmode = em->selectmode;
@@ -1779,13 +1835,6 @@ bool EDBM_selectmode_toggle(bContext *C, const short selectmode_new,
break;
case SCE_SELECT_FACE:
if (use_extend == 0 || em->selectmode == 0) {
- if (use_expand) {
- 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;