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:
authorCampbell Barton <ideasman42@gmail.com>2015-05-29 07:27:39 +0300
committerCampbell Barton <ideasman42@gmail.com>2015-05-29 07:41:39 +0300
commitaf434fea71c7493a4313637e4eb3f29b22c83839 (patch)
tree86ca8f7898b7e83f8a6b27adc45281c41432135e /source/blender/bmesh/intern/bmesh_walkers_impl.c
parent3511e2d6aeb4d8d4986be699f3104b4258c354e2 (diff)
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.
Diffstat (limited to 'source/blender/bmesh/intern/bmesh_walkers_impl.c')
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers_impl.c172
1 files changed, 164 insertions, 8 deletions
diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c
index 1fbfbba5c5e..0fb70b2b733 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 */