From 0b4dfa1fcb2e4b43923c219ed59aaf31bbf0fed9 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 31 Aug 2012 12:08:04 +0000 Subject: Fix #32450: edge slide with multiple loops selected could move some loops in the wrong direction. --- source/blender/editors/transform/transform.c | 60 ++++++++++++++++++++-------- source/blender/editors/transform/transform.h | 2 + 2 files changed, 45 insertions(+), 17 deletions(-) (limited to 'source') diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index b3f012efb59..685141810fd 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -4759,7 +4759,7 @@ static int createSlideVerts(TransInfo *t) BMEditMesh *em = me->edit_btmesh; BMesh *bm = em->bm; BMIter iter, iter2; - BMEdge *e, *e1 /*, *ee, *le */ /* UNUSED */; + BMEdge *e, *e1; BMVert *v, *v2, *first; BMLoop *l, *l1, *l2; TransDataSlideVert *sv_array; @@ -4771,9 +4771,10 @@ static int createSlideVerts(TransInfo *t) ARegion *ar = t->ar; float projectMat[4][4]; float mval[2] = {(float)t->mval[0], (float)t->mval[1]}; - float start[3] = {0.0f, 0.0f, 0.0f}, dir[3], end[3] = {0.0f, 0.0f, 0.0f}; + float start[3] = {0.0f, 0.0f, 0.0f}, end[3] = {0.0f, 0.0f, 0.0f}; float vec[3], vec2[3] /*, lastvec[3], size, dis=0.0, z */ /* UNUSED */; - int numsel, i, j; + float dir[3], maxdist, (*loop_dir)[3], *loop_maxdist; + int numsel, i, j, loop_nr, l_nr; if (t->spacetype == SPACE_VIEW3D) { /* background mode support */ @@ -4848,6 +4849,7 @@ static int createSlideVerts(TransInfo *t) } sv_array = MEM_callocN(sizeof(TransDataSlideVert) * j, "sv_array"); + loop_nr = 0; j = 0; while (1) { @@ -4910,6 +4912,8 @@ static int createSlideVerts(TransInfo *t) sv->v = v; sv->origvert = *v; + sv->loop_nr = loop_nr; + copy_v3_v3(sv->upvec, vec); if (l2) copy_v3_v3(sv->downvec, vec2); @@ -4932,6 +4936,7 @@ static int createSlideVerts(TransInfo *t) sv = sv_array + j + 1; sv->v = v; sv->origvert = *v; + sv->loop_nr = loop_nr; l = BM_face_other_edge_loop(l1->f, l1->e, v); sv->up = BM_edge_other_vert(l->e, v); @@ -4958,6 +4963,8 @@ static int createSlideVerts(TransInfo *t) BM_elem_flag_disable(v, BM_ELEM_TAG); BM_elem_flag_disable(v2, BM_ELEM_TAG); } while (e != first->e && l1); + + loop_nr++; } /* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */ @@ -4965,21 +4972,24 @@ static int createSlideVerts(TransInfo *t) sld->sv = sv_array; sld->totsv = j; - /*find mouse vector*/ - /* dis = z = -1.0f; */ /* UNUSED */ - /* size = 50.0; */ /* UNUSED */ - /* zero_v3(lastvec); */ /* UNUSED */ + /* find mouse vectors, the global one, and one per loop in case we have + * multiple loops selected, in case they are oriented different */ zero_v3(dir); - /* ee = le = NULL; */ /* UNUSED */ + maxdist = -1.0f; + + loop_dir = MEM_callocN(sizeof(float)*3*loop_nr, "sv loop_dir"); + loop_maxdist = MEM_callocN(sizeof(float)*loop_nr, "sv loop_maxdist"); + for (j = 0; j < loop_nr; j++) + loop_maxdist[j] = -1.0f; + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { BMIter iter2; BMEdge *e2; - float vec1[3], dis2, mval[2] = {t->mval[0], t->mval[1]}, d; + float vec1[3], mval[2] = {t->mval[0], t->mval[1]}, d; /* search cross edges for visible edge to the mouse cursor, * then use the shared vertex to calculate screen vector*/ - dis2 = -1.0f; for (i = 0; i < 2; i++) { v = i ? e->v1 : e->v2; BM_ITER_ELEM (e2, &iter2, v, BM_EDGES_OF_VERT) { @@ -5007,17 +5017,23 @@ static int createSlideVerts(TransInfo *t) ED_view3d_project_float_v3(ar, sv_array[j].up->co, vec2, projectMat); } else { - add_v3_v3v3(vec1, v->co, sv_array[j].upvec); + add_v3_v3v3(vec2, v->co, sv_array[j].upvec); ED_view3d_project_float_v3(ar, vec2, vec2, projectMat); } - + + /* global direction */ d = dist_to_line_segment_v2(mval, vec1, vec2); - if (dis2 == -1.0f || d < dis2) { - dis2 = d; - /* ee = e2; */ /* UNUSED */ - /* size = len_v3v3(vec1, vec2); */ /* UNUSED */ + if (maxdist == -1.0f || d < maxdist) { + maxdist = d; sub_v3_v3v3(dir, vec1, vec2); } + + /* per loop direction */ + l_nr = sv_array[j].loop_nr; + if (loop_maxdist[l_nr] == -1.0f || d < loop_maxdist[l_nr]) { + loop_maxdist[l_nr] = d; + sub_v3_v3v3(loop_dir[l_nr], vec1, vec2); + } } } } @@ -5051,6 +5067,14 @@ static int createSlideVerts(TransInfo *t) } BLI_smallhash_insert(&sld->vhash, (uintptr_t)sv_array->v, sv_array); + + /* switch up/down if loop direction is different from global direction */ + l_nr = sv_array->loop_nr; + if (dot_v3v3(loop_dir[l_nr], dir) < 0.0f) { + swap_v3_v3(sv_array->upvec, sv_array->downvec); + SWAP(BMVert, sv_array->vup, sv_array->vdown); + SWAP(BMVert*, sv_array->up, sv_array->down); + } } if (rv3d) @@ -5061,7 +5085,7 @@ static int createSlideVerts(TransInfo *t) /*zero out start*/ zero_v3(start); - + /*dir holds a vector along edge loop*/ copy_v3_v3(end, dir); mul_v3_fl(end, 0.5f); @@ -5078,6 +5102,8 @@ static int createSlideVerts(TransInfo *t) BLI_smallhash_release(&table); BMBVH_FreeBVH(btree); + MEM_freeN(loop_dir); + MEM_freeN(loop_maxdist); return 1; } diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 8a7148aad95..e645cb2fed6 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -198,6 +198,8 @@ typedef struct TransDataSlideVert { float edge_len; float upvec[3], downvec[3]; + + int loop_nr; } TransDataSlideVert; typedef struct SlideData { -- cgit v1.2.3