From 72b422c1e101dce18ddff5a4221665a80e58d78d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 1 Aug 2020 11:34:42 +1000 Subject: [PATCH] UV: support select linked with sync-select in vert/edge modes --- source/blender/editors/uvedit/uvedit_select.c | 81 +++++++++++++------ 1 file changed, 55 insertions(+), 26 deletions(-) diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c index aff891c4023..151c881a466 100644 --- a/source/blender/editors/uvedit/uvedit_select.c +++ b/source/blender/editors/uvedit/uvedit_select.c @@ -1263,11 +1263,13 @@ static void uv_select_linked_multi(Scene *scene, Object **objects, const uint objects_len, UvNearestHit *hit_final, - bool extend, + const bool extend, bool deselect, - bool toggle, - bool select_faces) + const bool toggle, + const bool select_faces) { + const bool uv_sync_select = (scene->toolsettings->uv_flag & UV_SYNC_SELECTION); + /* loop over objects, or just use hit_final->ob */ for (uint ob_index = 0; ob_index < objects_len; ob_index++) { if (hit_final && ob_index != 0) { @@ -1278,7 +1280,6 @@ static void uv_select_linked_multi(Scene *scene, BMFace *efa; BMLoop *l; BMIter iter, liter; - MLoopUV *luv; UvVertMap *vmap; UvMapVert *vlist, *iterv, *startv; int i, stacksize = 0, *stack; @@ -1296,7 +1297,7 @@ static void uv_select_linked_multi(Scene *scene, * * Better solve this by having a delimit option for select-linked operator, * keeping island-select working as is. */ - vmap = BM_uv_vert_map_create(em->bm, !select_faces, false); + vmap = BM_uv_vert_map_create(em->bm, !uv_sync_select, false); if (vmap == NULL) { continue; @@ -1318,14 +1319,42 @@ static void uv_select_linked_multi(Scene *scene, } else { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { + bool add_to_stack = true; + if (uv_sync_select && !select_faces) { + /* Special case, vertex/edge & sync select being enabled. + * + * Without this, a second linked select will 'grow' each time as each new + * selection reaches the boundaries of islands that share vertices but not UV's. + * + * Rules applied here: + * - This loops face isn't selected. + * - The only other fully selected face is connected or, + * - There are no connected fully selected faces UV-connected to this loop. + */ + if (uvedit_face_select_test(scene, l->f, cd_loop_uv_offset)) { + /* pass */ + } + else { + BMIter liter_other; + BMLoop *l_other; + BM_ITER_ELEM (l_other, &liter_other, l->v, BM_LOOPS_OF_VERT) { + if ((l != l_other) && + !BM_loop_uv_share_vert_check(l, l_other, cd_loop_uv_offset) && + uvedit_face_select_test(scene, l_other->f, cd_loop_uv_offset)) { + add_to_stack = false; + break; + } + } + } + } - if (luv->flag & MLOOPUV_VERTSEL) { - stack[stacksize] = a; - stacksize++; - flag[a] = 1; - - break; + if (add_to_stack) { + stack[stacksize] = a; + stacksize++; + flag[a] = 1; + break; + } } } } @@ -1394,10 +1423,9 @@ static void uv_select_linked_multi(Scene *scene, } else { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - - if (luv->flag & MLOOPUV_VERTSEL) { + if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { found_selected = true; + break; } } @@ -1414,10 +1442,7 @@ static void uv_select_linked_multi(Scene *scene, BM_face_select_set(em->bm, efa, value); \ } \ else { \ - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { \ - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); \ - luv->flag = (value) ? (luv->flag | MLOOPUV_VERTSEL) : (luv->flag & ~MLOOPUV_VERTSEL); \ - } \ + uvedit_face_select_set(scene, em, efa, value, false, cd_loop_uv_offset); \ } \ (void)0 @@ -1442,6 +1467,17 @@ static void uv_select_linked_multi(Scene *scene, MEM_freeN(stack); MEM_freeN(flag); BM_uv_vert_map_free(vmap); + + if (uv_sync_select) { + if (deselect) { + EDBM_deselect_flush(em); + } + else { + if (!select_faces) { + EDBM_selectmode_flush(em); + } + } + } } } @@ -2263,13 +2299,6 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent UvNearestHit hit = UV_NEAREST_HIT_INIT; - if ((ts->uv_flag & UV_SYNC_SELECTION) && !(ts->selectmode & SCE_SELECT_FACE)) { - BKE_report(op->reports, - RPT_ERROR, - "Select linked only works in face select mode when sync selection is enabled"); - return OPERATOR_CANCELLED; - } - if (pick) { extend = RNA_boolean_get(op->ptr, "extend"); deselect = RNA_boolean_get(op->ptr, "deselect");