diff options
author | Campbell Barton <ideasman42@gmail.com> | 2020-05-04 12:01:00 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2020-05-04 12:20:08 +0300 |
commit | 411c5238a2fefe54100453e8536c2c80fae1e9a0 (patch) | |
tree | 6b901c508d3b2dc2abc5d01984ae0802509d6d3d /source/blender/editors/uvedit/uvedit_select.c | |
parent | 88b9505b8419f4a363e52bb1930cb1946bf327fe (diff) |
UV: support edge-selection for box/circle/lasso select
Diffstat (limited to 'source/blender/editors/uvedit/uvedit_select.c')
-rw-r--r-- | source/blender/editors/uvedit/uvedit_select.c | 180 |
1 files changed, 161 insertions, 19 deletions
diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c index fbbafde04d3..e9be10318b0 100644 --- a/source/blender/editors/uvedit/uvedit_select.c +++ b/source/blender/editors/uvedit/uvedit_select.c @@ -2495,6 +2495,9 @@ static int uv_box_select_exec(bContext *C, wmOperator *op) const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ? (ts->selectmode == SCE_SELECT_FACE) : (ts->uv_selectmode == UV_SELECT_FACE)); + const bool use_edge = ((ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_EDGE) : + (ts->uv_selectmode == UV_SELECT_EDGE)); /* get rectangle from operator */ WM_operator_properties_border_to_rctf(op, &rectf); @@ -2550,6 +2553,41 @@ static int uv_box_select_exec(bContext *C, wmOperator *op) uv_select_flush_from_tag_face(sima, scene, obedit, select); } } + else if (use_edge && !pinned) { + changed = true; + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + + BMLoop *l_prev = BM_FACE_FIRST_LOOP(efa)->prev; + MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l_prev, cd_loop_uv_offset); + bool luv_select_prev = uvedit_uv_select_test(scene, l_prev, cd_loop_uv_offset); + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + const bool luv_select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset); + if ((select != luv_select) || (select != luv_select_prev)) { + if (BLI_rctf_isect_pt_v(&rectf, luv->uv) && + BLI_rctf_isect_pt_v(&rectf, luv_prev->uv)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + uvedit_uv_select_set(em, scene, l_prev, select, false, cd_loop_uv_offset); + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + BM_elem_flag_enable(l_prev->v, BM_ELEM_TAG); + } + } + l_prev = l; + luv_prev = luv; + luv_select_prev = luv_select; + } + } + + if (sima->sticky == SI_STICKY_VERTEX) { + uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset); + } + } else { /* other selection modes */ changed = true; @@ -2637,13 +2675,33 @@ void UV_OT_select_box(wmOperatorType *ot) /** \name Circle Select Operator * \{ */ -static int uv_inside_circle(const float uv[2], const float offset[2], const float ellipse[2]) +static int uv_circle_select_is_point_inside(const float uv[2], + const float offset[2], + const float ellipse[2]) +{ + /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */ + const float co[2] = { + (uv[0] - offset[0]) * ellipse[0], + (uv[1] - offset[1]) * ellipse[1], + }; + return len_squared_v2(co) < 1.0f; +} + +static int uv_circle_select_is_edge_inside(const float uv_a[2], + const float uv_b[2], + const float offset[2], + const float ellipse[2]) { /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */ - float x, y; - x = (uv[0] - offset[0]) * ellipse[0]; - y = (uv[1] - offset[1]) * ellipse[1]; - return ((x * x + y * y) < 1.0f); + const float co_a[2] = { + (uv_a[0] - offset[0]) * ellipse[0], + (uv_a[1] - offset[1]) * ellipse[1], + }; + const float co_b[2] = { + (uv_b[0] - offset[0]) * ellipse[0], + (uv_b[1] - offset[1]) * ellipse[1], + }; + return dist_squared_to_line_segment_v2((const float[2]){0.0f, 0.0f}, co_a, co_b) < 1.0f; } static int uv_circle_select_exec(bContext *C, wmOperator *op) @@ -2666,6 +2724,9 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ? (ts->selectmode == SCE_SELECT_FACE) : (ts->uv_selectmode == UV_SELECT_FACE)); + const bool use_edge = ((ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_EDGE) : + (ts->uv_selectmode == UV_SELECT_EDGE)); /* get operator properties */ x = RNA_int_get(op->ptr, "x"); @@ -2715,7 +2776,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) if (select != uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { float cent[2]; uv_poly_center(efa, cent, cd_loop_uv_offset); - if (uv_inside_circle(cent, offset, ellipse)) { + if (uv_circle_select_is_point_inside(cent, offset, ellipse)) { BM_elem_flag_enable(efa, BM_ELEM_TAG); changed = true; } @@ -2727,6 +2788,40 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) uv_select_flush_from_tag_face(sima, scene, obedit, select); } } + else if (use_edge) { + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + + BMLoop *l_prev = BM_FACE_FIRST_LOOP(efa)->prev; + MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l_prev, cd_loop_uv_offset); + bool luv_select_prev = uvedit_uv_select_test(scene, l_prev, cd_loop_uv_offset); + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + const bool luv_select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset); + if ((select != luv_select) || (select != luv_select_prev)) { + if (uv_circle_select_is_edge_inside(luv->uv, luv_prev->uv, offset, ellipse)) { + changed = true; + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + uvedit_uv_select_set(em, scene, l_prev, select, false, cd_loop_uv_offset); + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + BM_elem_flag_enable(l_prev->v, BM_ELEM_TAG); + } + } + l_prev = l; + luv_prev = luv; + luv_select_prev = luv_select; + } + } + + if (sima->sticky == SI_STICKY_VERTEX) { + uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset); + } + } else { BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); @@ -2738,7 +2833,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - if (uv_inside_circle(luv->uv, offset, ellipse)) { + if (uv_circle_select_is_point_inside(luv->uv, offset, ellipse)) { changed = true; uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); BM_elem_flag_enable(l->v, BM_ELEM_TAG); @@ -2801,6 +2896,23 @@ void UV_OT_select_circle(wmOperatorType *ot) /** \name Lasso Select Operator * \{ */ +static bool do_lasso_select_mesh_uv_is_point_inside(ARegion *region, + const rcti *clip_rect, + const int mcoords[][2], + const int mcoords_len, + const float co_test[2]) +{ + int co_screen[2]; + if (UI_view2d_view_to_region_clip( + ®ion->v2d, co_test[0], co_test[1], &co_screen[0], &co_screen[1]) && + BLI_rcti_isect_pt_v(clip_rect, co_screen) && + BLI_lasso_is_point_inside( + mcoords, mcoords_len, co_screen[0], co_screen[1], V2D_IS_CLIPPED)) { + return true; + } + return false; +} + static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short moves, @@ -2816,6 +2928,10 @@ static bool do_lasso_select_mesh_uv(bContext *C, const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ? (ts->selectmode == SCE_SELECT_FACE) : (ts->uv_selectmode == UV_SELECT_FACE)); + const bool use_edge = ((ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_EDGE) : + (ts->uv_selectmode == UV_SELECT_EDGE)); + const bool select = (sel_op != SEL_OP_SUB); const bool use_pre_deselect = SEL_OP_USE_PRE_DESELECT(sel_op); @@ -2823,7 +2939,6 @@ static bool do_lasso_select_mesh_uv(bContext *C, BMFace *efa; BMLoop *l; - int screen_uv[2]; float limit[2]; bool changed_multi = false; rcti rect; @@ -2857,12 +2972,7 @@ static bool do_lasso_select_mesh_uv(bContext *C, if (select != uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { float cent[2]; uv_poly_center(efa, cent, cd_loop_uv_offset); - - if (UI_view2d_view_to_region_clip( - ®ion->v2d, cent[0], cent[1], &screen_uv[0], &screen_uv[1]) && - BLI_rcti_isect_pt_v(&rect, screen_uv) && - BLI_lasso_is_point_inside( - mcords, moves, screen_uv[0], screen_uv[1], V2D_IS_CLIPPED)) { + if (do_lasso_select_mesh_uv_is_point_inside(region, &rect, mcords, moves, cent)) { BM_elem_flag_enable(efa, BM_ELEM_TAG); changed = true; } @@ -2874,6 +2984,42 @@ static bool do_lasso_select_mesh_uv(bContext *C, uv_select_flush_from_tag_face(sima, scene, obedit, select); } } + else if (use_edge) { + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + + BMLoop *l_prev = BM_FACE_FIRST_LOOP(efa)->prev; + MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l_prev, cd_loop_uv_offset); + bool luv_select_prev = uvedit_uv_select_test(scene, l_prev, cd_loop_uv_offset); + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + const bool luv_select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset); + if ((select != luv_select) || (select != luv_select_prev)) { + if (do_lasso_select_mesh_uv_is_point_inside(region, &rect, mcords, moves, luv->uv) && + do_lasso_select_mesh_uv_is_point_inside( + region, &rect, mcords, moves, luv_prev->uv)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + uvedit_uv_select_set(em, scene, l_prev, select, false, cd_loop_uv_offset); + changed = true; + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + BM_elem_flag_enable(l_prev->v, BM_ELEM_TAG); + } + } + l_prev = l; + luv_prev = luv; + luv_select_prev = luv_select; + } + } + + if (sima->sticky == SI_STICKY_VERTEX) { + uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset); + } + } else { /* Vert Sel */ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); @@ -2885,11 +3031,7 @@ static bool do_lasso_select_mesh_uv(bContext *C, BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) { MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - if (UI_view2d_view_to_region_clip( - ®ion->v2d, luv->uv[0], luv->uv[1], &screen_uv[0], &screen_uv[1]) && - BLI_rcti_isect_pt_v(&rect, screen_uv) && - BLI_lasso_is_point_inside( - mcords, moves, screen_uv[0], screen_uv[1], V2D_IS_CLIPPED)) { + if (do_lasso_select_mesh_uv_is_point_inside(region, &rect, mcords, moves, luv->uv)) { uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); changed = true; BM_elem_flag_enable(l->v, BM_ELEM_TAG); |