UV: support select linked with sync-select in vert/edge modes

master
Campbell Barton 4 years ago
parent 732434cb1f
commit 72b422c1e1

@ -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 (luv->flag & MLOOPUV_VERTSEL) {
stack[stacksize] = a;
stacksize++;
flag[a] = 1;
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;
}
}
}
}
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");

Loading…
Cancel
Save