From bb89cc51eca305195e530f6bc91433aea21e235e Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Sat, 14 Mar 2020 08:16:08 +0100 Subject: Fix T67446: UV Editor: support island select mode for box/circle/lasso selections Previously this was only supported in single click selections, doing an island selection with box/circle/lasso would just select individual vertices instead. Now selects islands properly. This also unifys some logic between box/circle/lasso: - use early selection test from lasso [makes things faster] in box/ circle - circle wasnt checking visible face --- source/blender/editors/uvedit/uvedit_ops.c | 106 +++++++++++++++++++++-------- 1 file changed, 76 insertions(+), 30 deletions(-) diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 41bb51340fc..fccbdb63393 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -3485,6 +3485,10 @@ static void uv_select_flush_from_tag_loop(SpaceImage *sima, /** \} */ +#define UV_SELECT_ISLAND_LIMIT \ + float limit[2]; \ + uvedit_pixel_to_float(sima, limit, 0.05f) + /* -------------------------------------------------------------------- */ /** \name Box Select Operator * \{ */ @@ -3518,6 +3522,8 @@ static int uv_box_select_exec(bContext *C, wmOperator *op) pinned = RNA_boolean_get(op->ptr, "pinned"); + UV_SELECT_ISLAND_LIMIT; + bool changed_multi = false; uint objects_len = 0; @@ -3569,24 +3575,34 @@ static int uv_box_select_exec(bContext *C, wmOperator *op) if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { continue; } + bool has_selected = false; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - - if (!pinned || (ts->uv_flag & UV_SYNC_SELECTION)) { - - /* UV_SYNC_SELECTION - can't do pinned selection */ - if (BLI_rctf_isect_pt_v(&rectf, luv->uv)) { - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - BM_elem_flag_enable(l->v, BM_ELEM_TAG); + if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) { + if (!pinned || (ts->uv_flag & UV_SYNC_SELECTION)) { + /* UV_SYNC_SELECTION - can't do pinned selection */ + if (BLI_rctf_isect_pt_v(&rectf, luv->uv)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + has_selected = true; + } } - } - else if (pinned) { - if ((luv->flag & MLOOPUV_PINNED) && BLI_rctf_isect_pt_v(&rectf, luv->uv)) { - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - BM_elem_flag_enable(l->v, BM_ELEM_TAG); + else if (pinned) { + if ((luv->flag & MLOOPUV_PINNED) && BLI_rctf_isect_pt_v(&rectf, luv->uv)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + } } } } + if (has_selected && ts->uv_selectmode == UV_SELECT_ISLAND) { + UvNearestHit hit = { + .ob = obedit, + .efa = efa, + }; + uv_select_linked_multi( + scene, ima, objects, objects_len, limit, &hit, true, !select, false, false); + } } if (sima->sticky == SI_STICKY_VERTEX) { @@ -3681,6 +3697,8 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) UI_view2d_region_to_view(®ion->v2d, x, y, &offset[0], &offset[1]); + UV_SELECT_ISLAND_LIMIT; + bool changed_multi = false; uint objects_len = 0; @@ -3728,14 +3746,29 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) 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; + } + bool has_selected = false; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - if (uv_inside_circle(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); + 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)) { + changed = true; + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + has_selected = true; + } } } + if (has_selected && ts->uv_selectmode == UV_SELECT_ISLAND) { + UvNearestHit hit = { + .ob = obedit, + .efa = efa, + }; + uv_select_linked_multi( + scene, ima, objects, objects_len, limit, &hit, true, !select, false, false); + } } if (sima->sticky == SI_STICKY_VERTEX) { @@ -3809,6 +3842,8 @@ static bool do_lasso_select_mesh_uv(bContext *C, bool changed_multi = false; rcti rect; + UV_SELECT_ISLAND_LIMIT; + BLI_lasso_boundbox(&rect, mcords, moves); uint objects_len = 0; @@ -3857,22 +3892,33 @@ static bool do_lasso_select_mesh_uv(bContext *C, 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)) { - 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)) { - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - changed = true; - BM_elem_flag_enable(l->v, BM_ELEM_TAG); - } + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + bool has_selected = false; + 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)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + changed = true; + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + has_selected = true; } } } + if (has_selected && ts->uv_selectmode == UV_SELECT_ISLAND) { + UvNearestHit hit = { + .ob = obedit, + .efa = efa, + }; + uv_select_linked_multi( + scene, ima, objects, objects_len, limit, &hit, true, !select, false, false); + } } if (sima->sticky == SI_STICKY_VERTEX) { -- cgit v1.2.3