[Bf-blender-cvs] [caf8684] master: EditMesh: Support contracting the selection as well as extending

Campbell Barton noreply at git.blender.org
Sun Mar 16 14:25:54 CET 2014


Commit: caf8684b5066720d4f4124092e23857dd462cb8b
Author: Campbell Barton
Date:   Mon Mar 17 00:23:05 2014 +1100
https://developer.blender.org/rBcaf8684b5066720d4f4124092e23857dd462cb8b

EditMesh: Support contracting the selection as well as extending

This allows for holding ctrl while switching from face->edge modes to
select an edge-ring.

===================================================================

M	source/blender/bmesh/intern/bmesh_queries.c
M	source/blender/bmesh/intern/bmesh_queries.h
M	source/blender/editors/mesh/editmesh_select.c

===================================================================

diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
index 5a0aae2..f240a10 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 d4b6cd0..36e67a7 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 37267d1..37b93c8 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;




More information about the Bf-blender-cvs mailing list