[Bf-blender-cvs] [af434fe] master: BMesh: select linked /w delimiters & wire edges

Campbell Barton noreply at git.blender.org
Fri May 29 06:41:55 CEST 2015


Commit: af434fea71c7493a4313637e4eb3f29b22c83839
Author: Campbell Barton
Date:   Fri May 29 14:27:39 2015 +1000
Branches: master
https://developer.blender.org/rBaf434fea71c7493a4313637e4eb3f29b22c83839

BMesh: select linked /w delimiters & wire edges

Add support for using edge delimiters mixed with wire edges.

Code isn't so elegant but users will expect this.

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

M	source/blender/bmesh/intern/bmesh_walkers.h
M	source/blender/bmesh/intern/bmesh_walkers_impl.c
M	source/blender/bmesh/intern/bmesh_walkers_private.h
M	source/blender/editors/mesh/editmesh_select.c

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

diff --git a/source/blender/bmesh/intern/bmesh_walkers.h b/source/blender/bmesh/intern/bmesh_walkers.h
index 1877611..f5a801a 100644
--- a/source/blender/bmesh/intern/bmesh_walkers.h
+++ b/source/blender/bmesh/intern/bmesh_walkers.h
@@ -115,6 +115,7 @@ void  BMW_reset(BMWalker *walker);
 enum {
 	BMW_VERT_SHELL,
 	BMW_LOOP_SHELL,
+	BMW_LOOP_SHELL_WIRE,
 	BMW_FACE_SHELL,
 	BMW_EDGELOOP,
 	BMW_FACELOOP,
diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c
index 1fbfbba..0fb70b2 100644
--- a/source/blender/bmesh/intern/bmesh_walkers_impl.c
+++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c
@@ -300,17 +300,14 @@ static void *bmw_LoopShellWalker_yield(BMWalker *walker)
 	return shellWalk->curloop;
 }
 
-static void *bmw_LoopShellWalker_step(BMWalker *walker)
+static void bmw_LoopShellWalker_step_impl(BMWalker *walker, BMLoop *l)
 {
-	BMwLoopShellWalker *swalk, owalk;
-	BMLoop *l;
-	int i;
 	BMEdge *e_edj_pair[2];
+	int i;
 
-	BMW_state_remove_r(walker, &owalk);
-	swalk = &owalk;
+	/* seems paranoid, but one caller also walks edges */
+	BLI_assert(l->head.htype == BM_LOOP);
 
-	l = swalk->curloop;
 	bmw_LoopShellWalker_visitLoop(walker, l->next);
 	bmw_LoopShellWalker_visitLoop(walker, l->prev);
 
@@ -332,12 +329,160 @@ static void *bmw_LoopShellWalker_step(BMWalker *walker)
 			} while ((l_iter = l_iter->radial_next) != l_first);
 		}
 	}
+}
+
+static void *bmw_LoopShellWalker_step(BMWalker *walker)
+{
+	BMwLoopShellWalker *swalk, owalk;
+	BMLoop *l;
+
+	BMW_state_remove_r(walker, &owalk);
+	swalk = &owalk;
+
+	l = swalk->curloop;
+	bmw_LoopShellWalker_step_impl(walker, l);
 
 	return l;
 }
 
 /** \} */
 
+/** \name LoopShell & 'Wire' Walker
+ * \{
+ *
+ * Piggyback ontop of #BMwLoopShellWalker, but also walk over wire edges
+ * This isn't elegant but users expect it when selecting linked,
+ * so we can support delimiters _and_ walking over wire edges.
+ *
+ * Details:
+ * - can yield edges (as well as loops)
+ * - only step over wire edges.
+ * - verts and edges are stored in `visit_set_alt`.
+ */
+
+static void bmw_LoopShellWalker_visitEdgeWire(BMWalker *walker, BMEdge *e)
+{
+	BMwLoopShellWireWalker *shellWalk = NULL;
+
+	BLI_assert(BM_edge_is_wire(e));
+
+	if (BLI_gset_haskey(walker->visit_set_alt, e)) {
+		return;
+	}
+
+	shellWalk = BMW_state_add(walker);
+	shellWalk->curelem = (BMElem *)e;
+	BLI_gset_insert(walker->visit_set_alt, e);
+}
+
+static void bmw_LoopShellWireWalker_visitVert(BMWalker *walker, BMVert *v, const BMEdge *e_from)
+{
+	BMEdge *e;
+
+	BLI_assert(v->head.htype == BM_VERT);
+
+	if (BLI_gset_haskey(walker->visit_set_alt, v)) {
+		return;
+	}
+
+	e = v->e;
+	do {
+		if (BM_edge_is_wire(e) && (e != e_from)) {
+			BMVert *v_other;
+			BMIter iter;
+			BMLoop *l;
+
+			bmw_LoopShellWalker_visitEdgeWire(walker, e);
+
+			/* check if we step onto a non-wire vertex */
+			v_other = BM_edge_other_vert(e, v);
+			BM_ITER_ELEM (l, &iter, v_other, BM_LOOPS_OF_VERT) {
+				bmw_LoopShellWalker_visitLoop(walker, l);
+			}
+		}
+	} while ((e = BM_DISK_EDGE_NEXT(e, v)) != v->e);
+
+	BLI_gset_insert(walker->visit_set_alt, v);
+}
+
+static void bmw_LoopShellWireWalker_begin(BMWalker *walker, void *data)
+{
+	BMHeader *h = data;
+
+	if (UNLIKELY(h == NULL)) {
+		return;
+	}
+
+	bmw_LoopShellWalker_begin(walker, data);
+
+	switch (h->htype) {
+		case BM_LOOP:
+		{
+			BMLoop *l = (BMLoop *)h;
+			bmw_LoopShellWireWalker_visitVert(walker, l->v, NULL);
+			break;
+		}
+
+		case BM_VERT:
+		{
+			BMVert *v = (BMVert *)h;
+			bmw_LoopShellWireWalker_visitVert(walker, v, NULL);
+			break;
+		}
+		case BM_EDGE:
+		{
+			BMEdge *e = (BMEdge *)h;
+			if (BM_edge_is_wire(e)) {
+				bmw_LoopShellWalker_visitEdgeWire(walker, e);
+			}
+			break;
+		}
+		case BM_FACE:
+		{
+			/* wire verts will be walked over */
+			break;
+		}
+		default:
+			BLI_assert(0);
+	}
+}
+
+static void *bmw_LoopShellWireWalker_yield(BMWalker *walker)
+{
+	BMwLoopShellWireWalker *shellWalk = BMW_current_state(walker);
+	return shellWalk->curelem;
+}
+
+static void *bmw_LoopShellWireWalker_step(BMWalker *walker)
+{
+	BMwLoopShellWireWalker *swalk, owalk;
+
+	BMW_state_remove_r(walker, &owalk);
+	swalk = &owalk;
+
+	if (swalk->curelem->head.htype == BM_LOOP) {
+		BMLoop *l = (BMLoop *)swalk->curelem;
+
+		bmw_LoopShellWalker_step_impl(walker, l);
+
+		bmw_LoopShellWireWalker_visitVert(walker, l->v, NULL);
+
+		return l;
+	}
+	else {
+		BMEdge *e = (BMEdge *)swalk->curelem;
+
+		BLI_assert(e->head.htype == BM_EDGE);
+
+		bmw_LoopShellWireWalker_visitVert(walker, e->v1, e);
+		bmw_LoopShellWireWalker_visitVert(walker, e->v2, e);
+
+		return e;
+	}
+}
+
+/** \} */
+
 
 /** \name FaceShell Walker
  * \{
@@ -1364,7 +1509,7 @@ static BMWalker bmw_VertShellWalker_Type = {
 };
 
 static BMWalker bmw_LoopShellWalker_Type = {
-	BM_LOOP | BM_VERT | BM_EDGE,
+	BM_FACE | BM_LOOP | BM_EDGE | BM_VERT,
 	bmw_LoopShellWalker_begin,
 	bmw_LoopShellWalker_step,
 	bmw_LoopShellWalker_yield,
@@ -1373,6 +1518,16 @@ static BMWalker bmw_LoopShellWalker_Type = {
 	BM_EDGE, /* valid restrict masks */
 };
 
+static BMWalker bmw_LoopShellWireWalker_Type = {
+	BM_FACE | BM_LOOP | BM_EDGE | BM_VERT,
+	bmw_LoopShellWireWalker_begin,
+	bmw_LoopShellWireWalker_step,
+	bmw_LoopShellWireWalker_yield,
+	sizeof(BMwLoopShellWireWalker),
+	BMW_BREADTH_FIRST,
+	BM_EDGE, /* valid restrict masks */
+};
+
 static BMWalker bmw_FaceShellWalker_Type = {
 	BM_EDGE,
 	bmw_FaceShellWalker_begin,
@@ -1466,6 +1621,7 @@ static BMWalker bmw_ConnectedVertexWalker_Type = {
 BMWalker *bm_walker_types[] = {
 	&bmw_VertShellWalker_Type,          /* BMW_VERT_SHELL */
 	&bmw_LoopShellWalker_Type,          /* BMW_LOOP_SHELL */
+    &bmw_LoopShellWireWalker_Type,      /* BMW_LOOP_SHELL_WIRE */
 	&bmw_FaceShellWalker_Type,          /* BMW_FACE_SHELL */
 	&bmw_EdgeLoopWalker_Type,           /* BMW_EDGELOOP */
 	&bmw_FaceLoopWalker_Type,           /* BMW_FACELOOP */
diff --git a/source/blender/bmesh/intern/bmesh_walkers_private.h b/source/blender/bmesh/intern/bmesh_walkers_private.h
index 826d2ee..66d812b 100644
--- a/source/blender/bmesh/intern/bmesh_walkers_private.h
+++ b/source/blender/bmesh/intern/bmesh_walkers_private.h
@@ -50,6 +50,11 @@ typedef struct BMwLoopShellWalker {
 	BMLoop *curloop;
 } BMwLoopShellWalker;
 
+typedef struct BMwLoopShellWireWalker {
+	BMwGenericWalker header;
+	BMElem *curelem;
+} BMwLoopShellWireWalker;
+
 typedef struct BMwIslandboundWalker {
 	BMwGenericWalker header;
 	BMLoop *base;
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 30b3d46..81f7830 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -2451,7 +2451,7 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op)
 			BM_elem_flag_set(v, BM_ELEM_TAG, BM_elem_flag_test(v, BM_ELEM_SELECT));
 		}
 
-		BMW_init(&walker, em->bm, delimit ? BMW_LOOP_SHELL : BMW_VERT_SHELL,
+		BMW_init(&walker, em->bm, delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
 		         BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
 		         BMW_FLAG_TEST_HIDDEN,
 		         BMW_NIL_LAY);
@@ -2459,10 +2459,20 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op)
 		if (delimit) {
 			BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
 				if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
-					BMLoop *l_walk;
-					BMW_ITER (l_walk, &walker, v) {
-						BM_vert_select_set(em->bm, l_walk->v, true);
-						BM_elem_flag_disable(l_walk->v, BM_ELEM_TAG);
+					BMElem *ele_walk;
+					BMW_ITER (ele_walk, &walker, v) {
+						if (ele_walk->head.htype == BM_LOOP) {
+							BMVert *v_step = ((BMLoop *)ele_walk)->v;
+							BM_vert_select_set(em->bm, v_step, true);
+							BM_elem_flag_disable(v_step, BM_ELEM_TAG);
+						}
+						else {
+							BMEdge *e_step = (BMEdge *)ele_walk;
+							BLI_assert(ele_walk->head.htype == BM_EDGE);
+							BM_edge_select_set(em->bm, e_step, true);
+							BM_elem_flag_disable(e_step->v1, BM_ELEM_TAG);
+							BM_elem_flag_disable(e_step->v2, BM_ELEM_TAG);
+						}
 					}
 				}
 			}
@@ -2490,7 +2500,7 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op)
 			BM_elem_flag_set(e, BM_ELEM_TAG, BM_elem_flag_test(e, BM_ELEM_SELECT));
 		}
 
-		BMW_init(&walker, em->bm, delimit ? BMW_LOOP_SHELL : BMW_VERT_SHELL,
+		BMW_init(&walker, em->bm, delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
 		         BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
 		         BMW_FLAG_TEST_HIDDEN,
 		         BMW_NIL_LAY);
@@ -2498,11 +2508,20 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op)
 		if (delimit) {
 			BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
 				if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
-					BMLoop *l_walk;
-					BMW_ITER (l_walk, &walker, e) {
-						BM_edge_select_set(em->bm, l_walk->e, true);
-						BM_edge_select_set(em->bm, l_walk->prev->e, true);
-						BM_elem_flag_disable(l_walk->e, BM_ELEM_TAG);
+					BMElem *ele_walk;
+					BMW_ITER (ele_walk, &walker, e) {
+						if (ele_walk->head.htype == BM_LOOP) {
+							BMLoop *l_step = (BMLoop *)ele_walk;
+							BM_edge_select_set(em->bm, l_step->e, true);
+							BM_edge_select_set(em->bm, l_step->prev->e, true);
+							BM_elem_flag_disable(l_step->e, BM_ELEM_TAG);
+						}
+						else {
+							BMEdge *e_step = (BMEdge *)ele_walk;
+							BLI_assert(ele_walk->head.htype == BM_EDGE);
+							BM_edge_select_set(em->bm, e_step, true);
+							BM_elem_flag_disable(e_step, BM_ELEM_TAG);
+						}
 					}
 				}
 			}
@@ -2593,15 +2612,23 @@ static void edbm_select_linked_pick_ex(
 
 	if ((em->selectmode & SCE_SELECT_VERTEX) && eve) {
 
-		BMW_init(&walker, bm, delimit ? BMW_LOOP_SHELL : BMW_VERT_SHELL,
+		BMW_init(&walker, bm, delimit ? BMW_LOOP_SHELL_WIRE : BMW_VERT_SHELL,
 		         BMW_MASK_NOP, delimit ? BMO_ELE_TAG : BMW_MASK_NOP, BMW_MASK_NOP,
 		         BMW_FLAG_TEST_HIDDEN,
 		         BMW_NIL_LAY);
 
 		if (delimit) {
-			BMLoop *l_walk;
-			BMW_ITER (l_walk, &walker, eve) {
-				BM_vert_select_set(bm, l_walk->v, sel);
+			BMElem *ele_walk;
+			BMW_ITER (ele_walk, &walker, eve) {
+				if (ele_walk->head.htype == BM_LOOP) {
+					B

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list