[Bf-blender-cvs] [6a10e69d270] master: UV: match 3D mesh editing behavior for edge-loop select
Campbell Barton
noreply at git.blender.org
Wed Aug 26 10:42:48 CEST 2020
Commit: 6a10e69d270bc6866dd0000ffc0b81f6205ba2e9
Author: Campbell Barton
Date: Wed Aug 26 13:13:06 2020 +1000
Branches: master
https://developer.blender.org/rB6a10e69d270bc6866dd0000ffc0b81f6205ba2e9
UV: match 3D mesh editing behavior for edge-loop select
- Cycling between part of the boundary & the entire UV boundary.
- Include pole vertices in the selection.
Edge loop selection was rewritten to use BMesh connectivity data.
===================================================================
M source/blender/editors/uvedit/uvedit_select.c
===================================================================
diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c
index cb3b32bcfee..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;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -971,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
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list