Cleanup: simplify sticky UV selection

Use BMesh connectivity information instead of looping over all
geometry to flush the sticky selection.
This commit is contained in:
Campbell Barton 2020-07-21 14:51:59 +10:00
parent b88dd3b8e7
commit 2bc1fd7e91
1 changed files with 14 additions and 116 deletions

View File

@ -1640,31 +1640,6 @@ void UV_OT_select_all(wmOperatorType *ot)
/** \name Mouse Select Operator
* \{ */
static bool uv_sticky_select(
const int hitv[], int v, float *hituv[], const float uv[2], int sticky, int hitlen)
{
/* This function test if some vertex needs to selected
* in addition to the existing ones due to sticky select */
if (sticky == SI_STICKY_DISABLE) {
return false;
}
for (int i = 0; i < hitlen; i++) {
if (hitv[i] == v) {
if (sticky == SI_STICKY_LOC) {
if (equals_v2v2(hituv[i], uv)) {
return true;
}
}
else if (sticky == SI_STICKY_VERTEX) {
return true;
}
}
}
return false;
}
static int uv_mouse_select_multi(bContext *C,
Object **objects,
uint objects_len,
@ -1676,18 +1651,11 @@ static int uv_mouse_select_multi(bContext *C,
SpaceImage *sima = CTX_wm_space_image(C);
Scene *scene = CTX_data_scene(C);
const ToolSettings *ts = scene->toolsettings;
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
MLoopUV *luv;
UvNearestHit hit = UV_NEAREST_HIT_INIT;
int i, selectmode, sticky, *hitv = NULL;
bool select = true;
int selectmode, sticky;
bool found_item = false;
/* 0 == don't flush, 1 == sel, -1 == desel; only use when selection sync is enabled */
int flush = 0;
int hitlen = 0;
float **hituv = NULL;
const float penalty_dist = uv_select_penalty_default(sima);
@ -1717,16 +1685,6 @@ static int uv_mouse_select_multi(bContext *C,
found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
if (found_item) {
/* mark 1 vertex as being hit */
hitv = BLI_array_alloca(hitv, hit.efa->len);
hituv = BLI_array_alloca(hituv, hit.efa->len);
copy_vn_i(hitv, hit.efa->len, 0xFFFFFFFF);
hitv[hit.lindex] = BM_elem_index_get(hit.l->v);
hituv[hit.lindex] = hit.luv->uv;
hitlen = hit.efa->len;
if ((ts->uv_flag & UV_SYNC_SELECTION) == 0) {
BMesh *bm = BKE_editmesh_from_object(hit.ob)->bm;
ED_uvedit_active_vert_loop_set(bm, hit.l);
@ -1739,18 +1697,6 @@ static int uv_mouse_select_multi(bContext *C,
found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
if (found_item) {
/* mark 2 edge vertices as being hit */
hitv = BLI_array_alloca(hitv, hit.efa->len);
hituv = BLI_array_alloca(hituv, hit.efa->len);
copy_vn_i(hitv, hit.efa->len, 0xFFFFFFFF);
hitv[hit.lindex] = BM_elem_index_get(hit.l->v);
hitv[(hit.lindex + 1) % hit.efa->len] = BM_elem_index_get(hit.l->next->v);
hituv[hit.lindex] = hit.luv->uv;
hituv[(hit.lindex + 1) % hit.efa->len] = hit.luv_next->uv;
hitlen = hit.efa->len;
if ((ts->uv_flag & UV_SYNC_SELECTION) == 0) {
BMesh *bm = BKE_editmesh_from_object(hit.ob)->bm;
ED_uvedit_active_edge_loop_set(bm, hit.l);
@ -1763,23 +1709,8 @@ static int uv_mouse_select_multi(bContext *C,
found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
if (found_item) {
BMEditMesh *em = BKE_editmesh_from_object(hit.ob);
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
/* make active */
BM_mesh_active_face_set(em->bm, hit.efa);
/* mark all face vertices as being hit */
hitv = BLI_array_alloca(hitv, hit.efa->len);
hituv = BLI_array_alloca(hituv, hit.efa->len);
BM_ITER_ELEM_INDEX (l, &liter, hit.efa, BM_LOOPS_OF_FACE, i) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
hituv[i] = luv->uv;
hitv[i] = BM_elem_index_get(l->v);
}
hitlen = hit.efa->len;
BMesh *bm = BKE_editmesh_from_object(hit.ob)->bm;
BM_mesh_active_face_set(bm, hit.efa);
}
}
else if (selectmode == UV_SELECT_ISLAND) {
@ -1816,22 +1747,24 @@ static int uv_mouse_select_multi(bContext *C,
uv_select_linked_multi(scene, objects, objects_len, &hit, false, false, extend, false);
}
else if (extend) {
bool select = true;
if (selectmode == UV_SELECT_VERTEX) {
/* (de)select uv vertex */
select = !uvedit_uv_select_test(scene, hit.l, cd_loop_uv_offset);
uvedit_uv_select_set(scene, em, hit.l, select, true, cd_loop_uv_offset);
uvedit_uv_select_set_with_sticky(sima, scene, em, hit.l, select, true, cd_loop_uv_offset);
flush = 1;
}
else if (selectmode == UV_SELECT_EDGE) {
/* (de)select edge */
select = !(uvedit_edge_select_test(scene, hit.l, cd_loop_uv_offset));
uvedit_edge_select_set(scene, em, hit.l, select, true, cd_loop_uv_offset);
uvedit_edge_select_set_with_sticky(sima, scene, em, hit.l, select, true, cd_loop_uv_offset);
flush = 1;
}
else if (selectmode == UV_SELECT_FACE) {
/* (de)select face */
select = !(uvedit_face_select_test(scene, hit.efa, cd_loop_uv_offset));
uvedit_face_select_set(scene, em, hit.efa, select, true, cd_loop_uv_offset);
uvedit_face_select_set_with_sticky(
sima, scene, em, hit.efa, select, true, cd_loop_uv_offset);
flush = -1;
}
@ -1844,64 +1777,29 @@ static int uv_mouse_select_multi(bContext *C,
/* (de)select sticky uv nodes */
if (sticky != SI_STICKY_DISABLE) {
BM_mesh_elem_index_ensure(em->bm, BM_VERT);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (uv_sticky_select(hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen)) {
uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset);
}
}
}
flush = select ? 1 : -1;
}
}
else {
const bool select = true;
/* deselect all */
uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT);
if (selectmode == UV_SELECT_VERTEX) {
/* select vertex */
uvedit_uv_select_enable(scene, em, hit.l, true, cd_loop_uv_offset);
uvedit_uv_select_set_with_sticky(sima, scene, em, hit.l, select, true, cd_loop_uv_offset);
flush = 1;
}
else if (selectmode == UV_SELECT_EDGE) {
/* select edge */
uvedit_edge_select_enable(scene, em, hit.l, true, cd_loop_uv_offset);
uvedit_edge_select_set_with_sticky(sima, scene, em, hit.l, select, true, cd_loop_uv_offset);
flush = 1;
}
else if (selectmode == UV_SELECT_FACE) {
/* select face */
uvedit_face_select_enable(scene, em, hit.efa, true, cd_loop_uv_offset);
}
/* select sticky uvs */
if (sticky != SI_STICKY_DISABLE) {
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (sticky == SI_STICKY_DISABLE) {
continue;
}
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (uv_sticky_select(hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen)) {
uvedit_uv_select_enable(scene, em, l, false, cd_loop_uv_offset);
}
flush = 1;
}
}
uvedit_face_select_set_with_sticky(
sima, scene, em, hit.efa, select, true, cd_loop_uv_offset);
flush = 1;
}
}