diff options
Diffstat (limited to 'source/blender/editors/uvedit')
-rw-r--r-- | source/blender/editors/uvedit/uvedit_draw.c | 58 | ||||
-rw-r--r-- | source/blender/editors/uvedit/uvedit_intern.h | 3 | ||||
-rw-r--r-- | source/blender/editors/uvedit/uvedit_select.c | 379 | ||||
-rw-r--r-- | source/blender/editors/uvedit/uvedit_smart_stitch.c | 4 |
4 files changed, 257 insertions, 187 deletions
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index df8d3cfb8db..044fca2310c 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -237,10 +237,10 @@ static void draw_uvs_shadow(SpaceImage *sima, if (edges) { if (sima->flag & SI_SMOOTH_UV) { GPU_line_smooth(true); - GPU_blend(true); + GPU_blend(GPU_BLEND_ALPHA); } else if (overlay_alpha < 1.0f) { - GPU_blend(true); + GPU_blend(GPU_BLEND_ALPHA); } col[3] = overlay_alpha; @@ -250,10 +250,10 @@ static void draw_uvs_shadow(SpaceImage *sima, if (sima->flag & SI_SMOOTH_UV) { GPU_line_smooth(false); - GPU_blend(false); + GPU_blend(GPU_BLEND_NONE); } else if (overlay_alpha < 1.0f) { - GPU_blend(false); + GPU_blend(GPU_BLEND_NONE); } } } @@ -288,10 +288,6 @@ static void draw_uvs_texpaint(const Scene *scene, Object *ob, Depsgraph *depsgra uint idx = 0; bool prev_ma_match = (mpoly->mat_nr == (ob_eval->actcol - 1)); - GPU_matrix_bind(geom->interface); - GPU_shader_set_srgb_uniform(geom->interface); - GPU_batch_bind(geom); - /* TODO(fclem): If drawcall count becomes a problem in the future * we can use multi draw indirect drawcalls for this. * (not implemented in GPU module at the time of writing). */ @@ -299,7 +295,7 @@ static void draw_uvs_texpaint(const Scene *scene, Object *ob, Depsgraph *depsgra bool ma_match = (mpoly->mat_nr == (ob_eval->actcol - 1)); if (ma_match != prev_ma_match) { if (ma_match == false) { - GPU_batch_draw_advanced(geom, draw_start, idx - draw_start, 0, 0); + GPU_batch_draw_range(geom, draw_start, idx - draw_start); } else { draw_start = idx; @@ -309,10 +305,8 @@ static void draw_uvs_texpaint(const Scene *scene, Object *ob, Depsgraph *depsgra prev_ma_match = ma_match; } if (prev_ma_match == true) { - GPU_batch_draw_advanced(geom, draw_start, idx - draw_start, 0, 0); + GPU_batch_draw_range(geom, draw_start, idx - draw_start); } - - GPU_batch_program_use_end(geom); } else { GPU_batch_draw(geom); @@ -355,8 +349,7 @@ static void draw_uvs(SpaceImage *sima, interpedges = (ts->uv_selectmode == UV_SELECT_VERTEX); } - GPU_blend_set_func_separate( - GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); + GPU_blend(GPU_BLEND_ALPHA); if (batch->faces) { GPU_batch_program_set_builtin(batch->faces, @@ -366,7 +359,7 @@ static void draw_uvs(SpaceImage *sima, GPU_SHADER_2D_UV_FACES); if (!draw_stretch) { - GPU_blend(true); + GPU_blend(GPU_BLEND_ALPHA); UI_GetThemeColor4fv(TH_FACE, col1); UI_GetThemeColor4fv(TH_FACE_SELECT, col2); @@ -393,16 +386,16 @@ static void draw_uvs(SpaceImage *sima, GPU_batch_draw(batch->faces); if (!draw_stretch) { - GPU_blend(false); + GPU_blend(GPU_BLEND_NONE); } } if (batch->edges) { if (sima->flag & SI_SMOOTH_UV) { GPU_line_smooth(true); - GPU_blend(true); + GPU_blend(GPU_BLEND_ALPHA); } else if (overlay_alpha < 1.0f) { - GPU_blend(true); + GPU_blend(GPU_BLEND_ALPHA); } { @@ -455,24 +448,26 @@ static void draw_uvs(SpaceImage *sima, } col1[3] = overlay_alpha; + GPU_batch_program_set_builtin(batch->edges, shader); + /* Inner Line. Use depth test to insure selection is drawn on top. */ - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); GPU_line_width(1.0f); GPU_batch_uniform_4fv(batch->edges, "edgeColor", col1); GPU_batch_uniform_4fv(batch->edges, "selectColor", col2); GPU_batch_uniform_1f(batch->edges, "dashWidth", dash_width); GPU_batch_draw(batch->edges); - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); GPU_provoking_vertex(GPU_VERTEX_LAST); } if (sima->flag & SI_SMOOTH_UV) { GPU_line_smooth(false); - GPU_blend(false); + GPU_blend(GPU_BLEND_NONE); } else if (overlay_alpha < 1.0f) { - GPU_blend(false); + GPU_blend(GPU_BLEND_NONE); } } @@ -482,7 +477,7 @@ static void draw_uvs(SpaceImage *sima, const float point_size = UI_GetThemeValuef(TH_VERTEX_SIZE); const float pinned_col[4] = {1.0f, 0.0f, 0.0f, 1.0f}; /* TODO Theme? */ UI_GetThemeColor4fv(TH_VERTEX, col1); - GPU_blend(true); + GPU_blend(GPU_BLEND_ALPHA); GPU_program_point_size(true); GPU_batch_program_set_builtin(batch->verts, GPU_SHADER_2D_UV_VERTS); @@ -491,7 +486,12 @@ static void draw_uvs(SpaceImage *sima, GPU_batch_uniform_4fv(batch->verts, "pinnedColor", pinned_col); GPU_batch_uniform_1f(batch->verts, "pointSize", (point_size + 1.5f) * M_SQRT2); GPU_batch_uniform_1f(batch->verts, "outlineWidth", 0.75f); - GPU_batch_draw(batch->verts); + + /* #GPU_batch_draw_advanced is needed as unbinding the shader and redrawing + * causes the vertices not to draw at the right size. */ + GPU_shader_bind(batch->verts->shader); + + GPU_batch_draw_advanced(batch->verts, 0, 0, 0, 0); /* We have problem in this mode when face order make some verts * appear unselected because an adjacent face is not selected and @@ -500,9 +500,13 @@ static void draw_uvs(SpaceImage *sima, * on top. A bit overkill but it's simple. */ GPU_batch_uniform_4fv(batch->verts, "vertColor", transparent); GPU_batch_uniform_4fv(batch->verts, "selectColor", col2); - GPU_batch_draw(batch->verts); - GPU_blend(false); + GPU_batch_draw_advanced(batch->verts, 0, 0, 0, 0); + + GPU_shader_unbind(); + /* Finish #GPU_batch_draw_advanced drawing. */ + + GPU_blend(GPU_BLEND_NONE); GPU_program_point_size(false); } if (batch->facedots) { @@ -557,8 +561,8 @@ void ED_uvedit_draw_main(SpaceImage *sima, Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( view_layer, ((View3D *)NULL), &objects_len); if (objects_len > 0) { + GPU_depth_mask(true); GPU_clear_depth(1.0f); - GPU_clear(GPU_DEPTH_BIT); } /* go over all objects and create the batches + add their areas to the total */ diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h index 5a510aaf945..306f8a2c561 100644 --- a/source/blender/editors/uvedit/uvedit_intern.h +++ b/source/blender/editors/uvedit/uvedit_intern.h @@ -42,9 +42,6 @@ typedef struct UvNearestHit { /** Always set if we have a hit. */ struct BMFace *efa; struct BMLoop *l; - struct MLoopUV *luv, *luv_next; - /** Index of loop within face. */ - int lindex; /** Needs to be set before calling nearest functions. */ float dist_sq; } UvNearestHit; diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c index 149c5cf1f96..2ea78ca5377 100644 --- a/source/blender/editors/uvedit/uvedit_select.c +++ b/source/blender/editors/uvedit/uvedit_select.c @@ -71,10 +71,14 @@ #include "uvedit_intern.h" static void uv_select_all_perform(Scene *scene, Object *obedit, int action); + +static void uv_select_all_perform_multi_ex( + Scene *scene, Object **objects, const uint objects_len, int action, const Object *ob_exclude); static void uv_select_all_perform_multi(Scene *scene, Object **objects, const uint objects_len, int action); + static void uv_select_flush_from_tag_face(SpaceImage *sima, Scene *scene, Object *obedit, @@ -612,7 +616,7 @@ void uvedit_uv_select_disable(const Scene *scene, } } -static BMLoop *uvedit_loop_find_other_radial_loop_with_visible_face(Scene *scene, +static BMLoop *uvedit_loop_find_other_radial_loop_with_visible_face(const Scene *scene, BMLoop *l_src, const int cd_loop_uv_offset) { @@ -637,6 +641,37 @@ static BMLoop *uvedit_loop_find_other_radial_loop_with_visible_face(Scene *scene return l_other; } +static BMLoop *uvedit_loop_find_other_boundary_loop_with_visible_face(const Scene *scene, + BMLoop *l_edge, + BMVert *v_pivot, + const int cd_loop_uv_offset) +{ + BLI_assert(uvedit_loop_find_other_radial_loop_with_visible_face( + scene, l_edge, cd_loop_uv_offset) == NULL); + + BMLoop *l_step = l_edge; + l_step = (l_step->v == v_pivot) ? l_step->prev : l_step->next; + BMLoop *l_step_last = NULL; + do { + BLI_assert(BM_vert_in_edge(l_step->e, v_pivot)); + l_step_last = l_step; + l_step = uvedit_loop_find_other_radial_loop_with_visible_face( + scene, l_step, cd_loop_uv_offset); + if (l_step) { + l_step = (l_step->v == v_pivot) ? l_step->prev : l_step->next; + } + } while (l_step != NULL); + + BM_elem_flag_set(l_step_last->e, BM_ELEM_SMOOTH, false); + + if (l_step_last != NULL) { + BLI_assert(uvedit_loop_find_other_radial_loop_with_visible_face( + scene, l_step_last, cd_loop_uv_offset) == NULL); + } + + return l_step_last; +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -671,9 +706,6 @@ bool uv_find_nearest_edge(Scene *scene, Object *obedit, const float co[2], UvNea hit->efa = efa; hit->l = l; - hit->luv = luv; - hit->luv_next = luv_next; - hit->lindex = i; hit->dist_sq = dist_test_sq; found = true; @@ -713,7 +745,6 @@ bool uv_find_nearest_face(Scene *scene, Object *obedit, const float co[2], UvNea if (uv_find_nearest_edge(scene, obedit, co, &hit)) { hit.dist_sq = dist_sq_init; hit.l = NULL; - hit.luv = hit.luv_next = NULL; BMIter iter; BMFace *efa; @@ -783,7 +814,6 @@ bool uv_find_nearest_vert(Scene *scene, hit.dist_sq = dist_sq_init; hit.l = NULL; - hit.luv = hit.luv_next = NULL; BMEditMesh *em = BKE_editmesh_from_object(obedit); BMFace *efa; @@ -822,10 +852,7 @@ bool uv_find_nearest_vert(Scene *scene, hit.dist_sq = dist_test_sq; hit.l = l; - hit.luv = luv; - hit.luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); hit.efa = efa; - hit.lindex = i; found = true; } } @@ -979,200 +1006,235 @@ BMLoop *uv_find_nearest_loop_from_edge(struct Scene *scene, /** \name Edge Loop Select * \{ */ -static void uv_select_edgeloop_vertex_loop_flag(UvMapVert *first) -{ - UvMapVert *iterv; - int count = 0; +/** Mode for selecting edge loops at boundaries. */ +enum eUVEdgeLoopBoundaryMode { + /** Delimit at face corners (don't walk over multiple edges in the same face). */ + UV_EDGE_LOOP_BOUNDARY_LOOP = 1, + /** Don't delimit, walk over the all connected boundary loops. */ + UV_EDGE_LOOP_BOUNDARY_ALL = 2, +}; - for (iterv = first; iterv; iterv = iterv->next) { - if (iterv->separate && iterv != first) { - break; +static BMLoop *bm_select_edgeloop_double_side_next(const Scene *scene, + BMLoop *l_step, + BMVert *v_from, + const int cd_loop_uv_offset) +{ + if (l_step->f->len == 4) { + BMVert *v_from_next = BM_edge_other_vert(l_step->e, v_from); + BMLoop *l_step_over = (v_from == l_step->v) ? l_step->next : l_step->prev; + l_step_over = uvedit_loop_find_other_radial_loop_with_visible_face( + scene, l_step_over, cd_loop_uv_offset); + if (l_step_over) { + return (l_step_over->v == v_from_next) ? l_step_over->prev : l_step_over->next; } - - count++; - } - - if (count < 5) { - first->flag = 1; } + return NULL; } -static UvMapVert *uv_select_edgeloop_vertex_map_get(UvVertMap *vmap, BMFace *efa, BMLoop *l) +static BMLoop *bm_select_edgeloop_single_side_next(const Scene *scene, + BMLoop *l_step, + BMVert *v_from, + const int cd_loop_uv_offset) { - UvMapVert *iterv, *first; - first = BM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v)); + BMVert *v_from_next = BM_edge_other_vert(l_step->e, v_from); + return uvedit_loop_find_other_boundary_loop_with_visible_face( + scene, l_step, v_from_next, cd_loop_uv_offset); +} - for (iterv = first; iterv; iterv = iterv->next) { - if (iterv->separate) { - first = iterv; - } - if (iterv->poly_index == BM_elem_index_get(efa)) { - return first; +/* TODO(campbell): support this in the BMesh API, as we have for clearing other types. */ +static void bm_loop_tags_clear(BMesh *bm) +{ + BMIter iter; + BMFace *f; + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + BMIter liter; + BMLoop *l_iter; + BM_ITER_ELEM (l_iter, &liter, f, BM_LOOPS_OF_FACE) { + BM_elem_flag_disable(l_iter, BM_ELEM_TAG); } } - - return NULL; } -static bool uv_select_edgeloop_edge_tag_faces(BMEditMesh *em, - UvMapVert *first1, - UvMapVert *first2, - int *totface) +/** + * Tag all loops which should be selected, the caller must select. + */ +static void uv_select_edgeloop_double_side_tag(const Scene *scene, + BMEditMesh *em, + BMLoop *l_init_pair[2], + const int cd_loop_uv_offset) { - UvMapVert *iterv1, *iterv2; - BMFace *efa; - int tot = 0; - - /* count number of faces this edge has */ - for (iterv1 = first1; iterv1; iterv1 = iterv1->next) { - if (iterv1->separate && iterv1 != first1) { - break; - } + bm_loop_tags_clear(em->bm); - for (iterv2 = first2; iterv2; iterv2 = iterv2->next) { - if (iterv2->separate && iterv2 != first2) { + for (int side = 0; side < 2; side++) { + BMLoop *l_step_pair[2] = {l_init_pair[0], l_init_pair[1]}; + BMVert *v_from = side ? l_step_pair[0]->e->v1 : l_step_pair[0]->e->v2; + /* Disable since we start from the same edge. */ + BM_elem_flag_disable(l_step_pair[0], BM_ELEM_TAG); + BM_elem_flag_disable(l_step_pair[1], BM_ELEM_TAG); + while ((l_step_pair[0] != NULL) && (l_step_pair[1] != NULL)) { + if (!uvedit_face_visible_test(scene, l_step_pair[0]->f) || + !uvedit_face_visible_test(scene, l_step_pair[1]->f) || + /* Check loops have not diverged. */ + (uvedit_loop_find_other_radial_loop_with_visible_face( + scene, l_step_pair[0], cd_loop_uv_offset) != l_step_pair[1])) { break; } - if (iterv1->poly_index == iterv2->poly_index) { - /* if face already tagged, don't do this edge */ - efa = BM_face_at_index(em->bm, iterv1->poly_index); - if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { - return false; - } + BLI_assert(l_step_pair[0]->e == l_step_pair[1]->e); + + BM_elem_flag_enable(l_step_pair[0], BM_ELEM_TAG); + BM_elem_flag_enable(l_step_pair[1], BM_ELEM_TAG); + + BMVert *v_from_next = BM_edge_other_vert(l_step_pair[0]->e, v_from); + /* Walk over both sides, ensure they keep on the same edge. */ + for (int i = 0; i < ARRAY_SIZE(l_step_pair); i++) { + l_step_pair[i] = bm_select_edgeloop_double_side_next( + scene, l_step_pair[i], v_from, cd_loop_uv_offset); + } - tot++; + if ((l_step_pair[0] && BM_elem_flag_test(l_step_pair[0], BM_ELEM_TAG)) || + (l_step_pair[1] && BM_elem_flag_test(l_step_pair[1], BM_ELEM_TAG))) { break; } + v_from = v_from_next; } } +} - if (*totface == 0) { /* start edge */ - *totface = tot; - } - else if (tot != *totface) { /* check for same number of faces as start edge */ - return false; +/** + * Tag all loops which should be selected, the caller must select. + * + * \param r_count_by_select: Count the number of unselected and selected loops, + * this is needed to implement cycling between #eUVEdgeLoopBoundaryMode. + */ +static void uv_select_edgeloop_single_side_tag(const Scene *scene, + BMEditMesh *em, + BMLoop *l_init, + const int cd_loop_uv_offset, + enum eUVEdgeLoopBoundaryMode boundary_mode, + int r_count_by_select[2]) +{ + if (r_count_by_select) { + r_count_by_select[0] = r_count_by_select[1] = 0; } - /* tag the faces */ - for (iterv1 = first1; iterv1; iterv1 = iterv1->next) { - if (iterv1->separate && iterv1 != first1) { - break; - } + bm_loop_tags_clear(em->bm); - for (iterv2 = first2; iterv2; iterv2 = iterv2->next) { - if (iterv2->separate && iterv2 != first2) { + for (int side = 0; side < 2; side++) { + BMLoop *l_step = l_init; + BMVert *v_from = side ? l_step->e->v1 : l_step->e->v2; + /* Disable since we start from the same edge. */ + BM_elem_flag_disable(l_step, BM_ELEM_TAG); + while (l_step != NULL) { + + if (!uvedit_face_visible_test(scene, l_step->f) || + /* Check the boundary is still a boundary. */ + (uvedit_loop_find_other_radial_loop_with_visible_face( + scene, l_step, cd_loop_uv_offset) != NULL)) { break; } - if (iterv1->poly_index == iterv2->poly_index) { - efa = BM_face_at_index(em->bm, iterv1->poly_index); - BM_elem_flag_enable(efa, BM_ELEM_TAG); + if (r_count_by_select != NULL) { + r_count_by_select[uvedit_edge_select_test(scene, l_step, cd_loop_uv_offset)] += 1; + /* Early exit when mixed could be optional if needed. */ + if (r_count_by_select[0] && r_count_by_select[1]) { + r_count_by_select[0] = r_count_by_select[1] = -1; + break; + } + } + + BM_elem_flag_enable(l_step, BM_ELEM_TAG); + + BMVert *v_from_next = BM_edge_other_vert(l_step->e, v_from); + BMFace *f_step_prev = l_step->f; + + l_step = bm_select_edgeloop_single_side_next(scene, l_step, v_from, cd_loop_uv_offset); + + if (l_step && BM_elem_flag_test(l_step, BM_ELEM_TAG)) { break; } + if (boundary_mode == UV_EDGE_LOOP_BOUNDARY_LOOP) { + /* Don't allow walking over the the face. */ + if (f_step_prev == l_step->f) { + break; + } + } + v_from = v_from_next; } } - - return true; } -static int uv_select_edgeloop(Scene *scene, Object *obedit, UvNearestHit *hit, const bool extend) +static int uv_select_edgeloop( + SpaceImage *sima, Scene *scene, Object *obedit, UvNearestHit *hit, const bool extend) { BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMFace *efa; - BMIter iter, liter; - BMLoop *l; - UvVertMap *vmap; - UvMapVert *iterv_curr; - UvMapVert *iterv_next; - int starttotf; - bool looking, select; + bool select; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - /* setup */ - BM_mesh_elem_table_ensure(em->bm, BM_FACE); - vmap = BM_uv_vert_map_create(em->bm, false, false); - - BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE); - - if (!extend) { - uv_select_all_perform(scene, obedit, SEL_DESELECT); + if (extend) { + select = !(uvedit_uv_select_test(scene, hit->l, cd_loop_uv_offset)); + } + else { + select = true; } - BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false); - - /* set flags for first face and verts */ - iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l); - iterv_next = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l->next); - uv_select_edgeloop_vertex_loop_flag(iterv_curr); - uv_select_edgeloop_vertex_loop_flag(iterv_next); - - starttotf = 0; - uv_select_edgeloop_edge_tag_faces(em, iterv_curr, iterv_next, &starttotf); - - /* sorry, first edge isn't even ok */ - looking = !(iterv_curr->flag == 0 && iterv_next->flag == 0); - - /* iterate */ - while (looking) { - looking = false; - - /* find correct valence edges which are not tagged yet, but connect to tagged one */ + BMLoop *l_init_pair[2] = { + hit->l, + uvedit_loop_find_other_radial_loop_with_visible_face(scene, hit->l, cd_loop_uv_offset), + }; - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!BM_elem_flag_test(efa, BM_ELEM_TAG) && uvedit_face_visible_test(scene, efa)) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - /* check face not hidden and not tagged */ - if (!(iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, efa, l))) { - continue; - } - if (!(iterv_next = uv_select_edgeloop_vertex_map_get(vmap, efa, l->next))) { - continue; - } + /* When selecting boundaries, support cycling between selection modes. */ + enum eUVEdgeLoopBoundaryMode boundary_mode = UV_EDGE_LOOP_BOUNDARY_LOOP; - /* check if vertex is tagged and has right valence */ - if (iterv_curr->flag || iterv_next->flag) { - if (uv_select_edgeloop_edge_tag_faces(em, iterv_curr, iterv_next, &starttotf)) { - looking = true; - BM_elem_flag_enable(efa, BM_ELEM_TAG); + /* Tag all loops that are part of the edge loop (select after). + * This is done so we can */ + if (l_init_pair[1] == NULL) { + int count_by_select[2]; + /* If the loops selected toggle the boundaries. */ + uv_select_edgeloop_single_side_tag( + scene, em, l_init_pair[0], cd_loop_uv_offset, boundary_mode, count_by_select); + if (count_by_select[!select] == 0) { + boundary_mode = UV_EDGE_LOOP_BOUNDARY_ALL; - uv_select_edgeloop_vertex_loop_flag(iterv_curr); - uv_select_edgeloop_vertex_loop_flag(iterv_next); - break; - } - } - } + /* If the boundary is selected, toggle back to the loop. */ + uv_select_edgeloop_single_side_tag( + scene, em, l_init_pair[0], cd_loop_uv_offset, boundary_mode, count_by_select); + if (count_by_select[!select] == 0) { + boundary_mode = UV_EDGE_LOOP_BOUNDARY_LOOP; } } } - /* do the actual select/deselect */ - iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l); - iterv_next = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l->next); - iterv_curr->flag = 1; - iterv_next->flag = 1; - - if (extend) { - select = !(uvedit_uv_select_test(scene, hit->l, cd_loop_uv_offset)); + if (l_init_pair[1] == NULL) { + uv_select_edgeloop_single_side_tag( + scene, em, l_init_pair[0], cd_loop_uv_offset, boundary_mode, NULL); } else { - select = true; + uv_select_edgeloop_double_side_tag(scene, em, l_init_pair, cd_loop_uv_offset); } - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, efa, l); + /* Apply the selection. */ + if (!extend) { + uv_select_all_perform(scene, obedit, SEL_DESELECT); + } - if (iterv_curr->flag) { - uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset); + /* Select all tagged loops. */ + { + BMIter iter; + BMFace *f; + BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) { + BMIter liter; + BMLoop *l_iter; + BM_ITER_ELEM (l_iter, &liter, f, BM_LOOPS_OF_FACE) { + if (BM_elem_flag_test(l_iter, BM_ELEM_TAG)) { + uvedit_edge_select_set_with_sticky( + sima, scene, em, l_iter, select, false, cd_loop_uv_offset); + } } } } - /* cleanup */ - BM_uv_vert_map_free(vmap); - return (select) ? 1 : -1; } @@ -1770,10 +1832,8 @@ static void uv_select_all_perform(Scene *scene, Object *obedit, int action) } } -static void uv_select_all_perform_multi(Scene *scene, - Object **objects, - const uint objects_len, - int action) +static void uv_select_all_perform_multi_ex( + Scene *scene, Object **objects, const uint objects_len, int action, const Object *ob_exclude) { if (action == SEL_TOGGLE) { action = uvedit_select_is_any_selected_multi(scene, objects, objects_len) ? SEL_DESELECT : @@ -1782,10 +1842,21 @@ static void uv_select_all_perform_multi(Scene *scene, for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; + if (ob_exclude && (obedit == ob_exclude)) { + continue; + } uv_select_all_perform(scene, obedit, action); } } +static void uv_select_all_perform_multi(Scene *scene, + Object **objects, + const uint objects_len, + int action) +{ + uv_select_all_perform_multi_ex(scene, objects, objects_len, action, NULL); +} + static int uv_select_all_exec(bContext *C, wmOperator *op) { Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); @@ -1931,8 +2002,7 @@ static int uv_mouse_select_multi(bContext *C, /* do selection */ if (selectmode == UV_SELECT_ISLAND) { if (!extend) { - /* TODO(MULTI_EDIT): We only need to de-select non-active */ - uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT); + uv_select_all_perform_multi_ex(scene, objects, objects_len, SEL_DESELECT, obedit); } /* Current behavior of 'extend' * is actually toggling, so pass extend flag as 'toggle' here */ @@ -2122,12 +2192,11 @@ static int uv_mouse_select_loop_generic_multi(bContext *C, /* Do selection. */ if (!extend) { - /* TODO(MULTI_EDIT): We only need to de-select non-active */ - uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT); + uv_select_all_perform_multi_ex(scene, objects, objects_len, SEL_DESELECT, obedit); } if (loop_type == UV_LOOP_SELECT) { - flush = uv_select_edgeloop(scene, obedit, &hit, extend); + flush = uv_select_edgeloop(sima, scene, obedit, &hit, extend); } else if (loop_type == UV_RING_SELECT) { flush = uv_select_edgering(sima, scene, obedit, &hit, extend); diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c index 6332a6ab48f..6dac31794b4 100644 --- a/source/blender/editors/uvedit/uvedit_smart_stitch.c +++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c @@ -1765,7 +1765,7 @@ static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), void pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); } - GPU_blend(true); + GPU_blend(GPU_BLEND_ALPHA); /* Static Tris */ if (stitch_preview->static_tris) { @@ -1829,7 +1829,7 @@ static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), void stitch_draw_vbo(vbo_line, GPU_PRIM_LINES, col); } - GPU_blend(false); + GPU_blend(GPU_BLEND_NONE); /* draw stitch vert/lines preview */ if (ssc->mode == STITCH_VERT) { |