diff options
author | Campbell Barton <ideasman42@gmail.com> | 2012-04-20 01:47:32 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2012-04-20 01:47:32 +0400 |
commit | 741a177a74057b9baaae17640205017ca393ed89 (patch) | |
tree | 33cf96b86350248bcbd54df29d57f64510f12c52 /source/blender/editors/mesh/editmesh_rip.c | |
parent | ebbfcd71e5ea35a64759ecbf9bc0f34d582a6bde (diff) |
bmesh: improve rip tool
- When the rip extends into a fan, pick the opposite edge in the fan (rather then 2 along)
- When stepping over the fan to find the rip edge, walk in the direction closest to the mouse (generally works nicer)
Diffstat (limited to 'source/blender/editors/mesh/editmesh_rip.c')
-rw-r--r-- | source/blender/editors/mesh/editmesh_rip.c | 65 |
1 files changed, 50 insertions, 15 deletions
diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index 34666c2cb7a..3d310e5ea90 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -66,7 +66,7 @@ static float edbm_rip_rip_edgedist(ARegion *ar, float mat[][4], float *co1, floa return dist_to_line_segment_v2(mvalf, vec1, vec2); } -static float edbm_rip_edge_side_measure(BMEdge *e, +static float edbm_rip_edge_side_measure(BMEdge *e, BMLoop *e_l, ARegion *ar, float projectMat[4][4], const float fmval[2]) { @@ -80,6 +80,8 @@ static float edbm_rip_edge_side_measure(BMEdge *e, BMVert *v1_other; BMVert *v2_other; + BLI_assert(BM_vert_in_edge(e, e_l->v)); + /* method for calculating distance: * * for each edge: calculate face center, then made a vector @@ -88,8 +90,8 @@ static float edbm_rip_edge_side_measure(BMEdge *e, /* rather then the face center, get the middle of * both edge verts connected to this one */ - v1_other = BM_face_other_vert_loop(e->l->f, e->v2, e->v1)->v; - v2_other = BM_face_other_vert_loop(e->l->f, e->v1, e->v2)->v; + v1_other = BM_face_other_vert_loop(e_l->f, e->v2, e->v1)->v; + v2_other = BM_face_other_vert_loop(e_l->f, e->v1, e->v2)->v; mid_v3_v3v3(cent, v1_other->co, v2_other->co); mid_v3_v3v3(mid, e->v1->co, e->v2->co); @@ -323,12 +325,12 @@ static void edbm_ripsel_deselect_helper(BMesh *bm, EdgeLoopPair *eloop_pairs, e = lp->l_a->e; v_prev = edbm_ripsel_edloop_pair_start_vert(e); for (; e; e = edbm_ripsel_edge_uid_step(e, &v_prev)) { - score_a += edbm_rip_edge_side_measure(e, ar, projectMat, fmval); + score_a += edbm_rip_edge_side_measure(e, e->l, ar, projectMat, fmval); } e = lp->l_b->e; v_prev = edbm_ripsel_edloop_pair_start_vert(e); for (; e; e = edbm_ripsel_edge_uid_step(e, &v_prev)) { - score_b += edbm_rip_edge_side_measure(e, ar, projectMat, fmval); + score_b += edbm_rip_edge_side_measure(e, e->l, ar, projectMat, fmval); } e = (score_a > score_b) ? lp->l_a->e : lp->l_b->e; @@ -538,26 +540,59 @@ static int edbm_rip_invoke(bContext *C, wmOperator *op, wmEvent *event) dist = FLT_MAX; } else { + int totedge; + int all_minifold; /* expand edge selection */ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { e2 = NULL; i = 0; + totedge = 0; + all_minifold = TRUE; BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { - /* important to check selection rather then tag here - * else we get feedback loop */ - if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { - e2 = e; - i++; + + if (!BM_edge_is_wire(e) && + !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) + { + /* important to check selection rather then tag here + * else we get feedback loop */ + if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { + e2 = e; + i++; + } + totedge++; + } + + /** #BM_vert_other_disk_edge has no hidden checks so don't check hidden here */ + if ((all_minifold == TRUE) && (BM_edge_is_manifold(e) == FALSE)) { + all_minifold = FALSE; } } + /* single edge, extend */ if (i == 1 && e2->l) { - l = BM_face_other_edge_loop(e2->l->f, e2, v); - l = l->radial_next; - l = BM_face_other_edge_loop(l->f, l->e, v); + if ((totedge == 4) || (all_minifold == FALSE)) { + BMLoop *l_a = e2->l; + BMLoop *l_b = l_a->radial_next; + + /* find the best face to follow, this wat the edge won't point away from + * the mouse when there are more then 4 (takes the shortest face fan around) */ + l = (edbm_rip_edge_side_measure(e2, l_a, ar, projectMat, fmval) < + edbm_rip_edge_side_measure(e2, l_b, ar, projectMat, fmval)) ? l_a : l_b; - if (l) { - BM_elem_flag_enable(l->e, BM_ELEM_TAG); + l = BM_face_other_edge_loop(l->f, e2, v); + l = l->radial_next; + l = BM_face_other_edge_loop(l->f, l->e, v); + + if (l) { + BM_elem_flag_enable(l->e, BM_ELEM_TAG); + } + } + else { + e = BM_vert_other_disk_edge(v, e2); + + if (e) { + BM_elem_flag_enable(e, BM_ELEM_TAG); + } } } } |