[Bf-blender-cvs] [d6e02d92e13] soc-2021-uv-editor-improvements-edge-selection: UV: Extend edge selection support
Siddhartha Jejurkar
noreply at git.blender.org
Thu Aug 5 13:08:35 CEST 2021
Commit: d6e02d92e13383b73f305cd7cd2162143f647507
Author: Siddhartha Jejurkar
Date: Mon Aug 2 09:50:50 2021 +0530
Branches: soc-2021-uv-editor-improvements-edge-selection
https://developer.blender.org/rBd6e02d92e13383b73f305cd7cd2162143f647507
UV: Extend edge selection support
- Add edge selection support for operators: mouse select, box select,
circle select, lasso select, (de)select all, invert selection and
select more/less
- Flush selections between UV verts and edges
- Fix: prevent deselection of neighbouring edges when deselecting an
edge in sticky location + edge select mode
===================================================================
M source/blender/editors/uvedit/uvedit_intern.h
M source/blender/editors/uvedit/uvedit_select.c
===================================================================
diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h
index ea72b859f7c..b0ab34b6b02 100644
--- a/source/blender/editors/uvedit/uvedit_intern.h
+++ b/source/blender/editors/uvedit/uvedit_intern.h
@@ -125,6 +125,14 @@ BMLoop *uv_find_nearest_loop_from_edge(struct Scene *scene,
struct BMEdge *e,
const float co[2]);
+/* flush uv selection */
+void uv_flush_vert_to_edge(struct Scene *scene,
+ struct Object *obedit,
+ const int cd_loop_uv_offset);
+void uv_flush_edge_to_vert(struct Scene *scene,
+ struct Object *obedit,
+ const int cd_loop_uv_offset);
+
/* utility tool functions */
void uvedit_live_unwrap_update(struct SpaceImage *sima,
diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c
index fe505f865b6..0e8022b0289 100644
--- a/source/blender/editors/uvedit/uvedit_select.c
+++ b/source/blender/editors/uvedit/uvedit_select.c
@@ -91,6 +91,18 @@ static void uv_select_tag_update_for_object(Depsgraph *depsgraph,
const ToolSettings *ts,
Object *obedit);
+static bool uvedit_vert_is_any_other_edge_selected(const Scene *scene,
+ BMLoop *l,
+ const int cd_loop_uv_offset);
+static bool uvedit_vert_is_any_other_face_selected(const Scene *scene,
+ BMLoop *l,
+ BMVert *v,
+ const int cd_loop_uv_offset);
+static bool uvedit_vert_is_any_other_not_face_selected(const Scene *scene,
+ BMLoop *l,
+ BMVert *v,
+ const int cd_loop_uv_offset);
+
/* -------------------------------------------------------------------- */
/** \name Active Selection Tracking
*
@@ -469,17 +481,37 @@ void uvedit_edge_select_set_with_sticky(const struct SpaceImage *sima,
default: {
/* SI_STICKY_LOC
* Fallback to SI_STICKY_LOC, in case sima->sticky is invalid */
- uvedit_edge_select_shared_location(
- scene, em, l, select, false, do_history, cd_loop_uv_offset);
-
- /* NOTE (Design tradeoff): This is a case where we deviate from the logic of: "EDGE
- * SELECTION MODE SHOULD IMPLY ONLY EDGES MUST BE SELECTED". The UV vertex selections done
- * below are to avoid the cases of edge selections breaking away (/become separate
- * entities) from the vertices/edges they were connected to */
- uvedit_uv_select_shared_location(scene, em, l, select, false, do_history, cd_loop_uv_offset);
- uvedit_uv_select_shared_location(
- scene, em, l->next, select, false, do_history, cd_loop_uv_offset);
+ if (select) {
+ uvedit_edge_select_shared_location(
+ scene, em, l, select, false, do_history, cd_loop_uv_offset);
+
+ /* NOTE (Design tradeoff): This is a case where we deviate from the logic of: "EDGE
+ * SELECTION MODE SHOULD IMPLY ONLY EDGES MUST BE SELECTED". The UV vertex selections done
+ * below are to avoid the cases of edge selections breaking away (/become separate
+ * entities) from the vertices/edges they were connected to */
+ uvedit_uv_select_shared_location(
+ scene, em, l, select, false, do_history, cd_loop_uv_offset);
+ uvedit_uv_select_shared_location(
+ scene, em, l->next, select, false, do_history, cd_loop_uv_offset);
+ }
+ else {
+ BMLoop *l_radial_iter = l;
+ do {
+ if (BM_loop_uv_share_edge_check(l, l_radial_iter, cd_loop_uv_offset)) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_radial_iter, cd_loop_uv_offset);
+ luv->flag &= ~MLOOPUV_EDGESEL;
+ }
+ } while ((l_radial_iter = l_radial_iter->radial_next) != l);
+ if (!uvedit_vert_is_any_other_edge_selected(scene, l, cd_loop_uv_offset)) {
+ uvedit_uv_select_shared_location(
+ scene, em, l, select, false, do_history, cd_loop_uv_offset);
+ }
+ if (!uvedit_vert_is_any_other_edge_selected(scene, l->next, cd_loop_uv_offset)) {
+ uvedit_uv_select_shared_location(
+ scene, em, l->next, select, false, do_history, cd_loop_uv_offset);
+ }
+ }
break;
}
}
@@ -1156,13 +1188,155 @@ bool ED_uvedit_nearest_uv_multi(const Scene *scene,
/** \} */
-/*
- * \brief Select Mode Flush
+/**
+ * For a specified vertex of a face, check if any edge connected to that vertex is selected or not
+ */
+static bool uvedit_vert_is_any_other_edge_selected(const Scene *scene,
+ BMLoop *l,
+ const int cd_loop_uv_offset)
+{
+ BMEdge *e_first, *e_iter;
+ e_first = e_iter = l->e;
+ do {
+ BMLoop *l_radial_iter = e_iter->l;
+ do {
+ if ((l_radial_iter->f != l->f) && uvedit_face_visible_test(scene, l_radial_iter->f)) {
+
+ if (uvedit_edge_select_test(scene, l_radial_iter, cd_loop_uv_offset)) {
+ return true;
+ }
+ }
+ } while ((l_radial_iter = l_radial_iter->radial_next) != e_iter->l);
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, l->v)) != e_first);
+
+ return false;
+}
+
+/**
+ * For a specified vertex of a face, check if any other face connected to that vertex is selected
+ * or not
+ */
+static bool uvedit_vert_is_any_other_face_selected(const Scene *scene,
+ BMLoop *l,
+ BMVert *v,
+ const int cd_loop_uv_offset)
+{
+ BMEdge *e_first, *e_iter;
+ e_first = e_iter = l->e;
+ do {
+ BMLoop *l_radial_iter = e_iter->l;
+ do {
+ if ((l_radial_iter->f != l->f) && uvedit_face_visible_test(scene, l_radial_iter->f) &&
+ (l->v == l_radial_iter->v)) {
+
+ if (BM_loop_uv_share_vert_check(l, l_radial_iter, cd_loop_uv_offset) &&
+ uvedit_face_select_test(scene, l_radial_iter->f, cd_loop_uv_offset)) {
+ return true;
+ }
+ }
+ } while ((l_radial_iter = l_radial_iter->radial_next) != e_iter->l);
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first);
+
+ return false;
+}
+
+/**
+ * For a specified vertex of a face, check if at least one face connected to that vertex is not
+ * selected
+ */
+static bool uvedit_vert_is_any_other_not_face_selected(const Scene *scene,
+ BMLoop *l,
+ BMVert *v,
+ const int cd_loop_uv_offset)
+{
+ BMEdge *e_first, *e_iter;
+ e_first = e_iter = l->e;
+ do {
+ BMLoop *l_radial_iter = e_iter->l;
+ do {
+ if ((l_radial_iter->f != l->f) && uvedit_face_visible_test(scene, l_radial_iter->f) &&
+ (l->v == l_radial_iter->v)) {
+
+ if (BM_loop_uv_share_vert_check(l, l_radial_iter, cd_loop_uv_offset) &&
+ !uvedit_face_select_test(scene, l_radial_iter->f, cd_loop_uv_offset)) {
+ return true;
+ }
+ }
+ } while ((l_radial_iter = l_radial_iter->radial_next) != e_iter->l);
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first);
+
+ return false;
+}
+
+/* -------------------------------------------------------------------- */
+/** \name UV Flush selection
*
- * TODO: Flushing selections based on current UV editor selection modes
- * Selections might need to be flushed in both directions (upwards and vice-versa - Refer invert
- * all option in UV select all operator).
+ * Utility functions to flush the uv-selection
+ * \{ */
+
+/**
+ * Flushes selection upwards (verts to edge)
*/
+void uv_flush_vert_to_edge(Scene *scene, Object *obedit, const int cd_loop_uv_offset)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ 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) {
+ MLoopUV *luv, *luv_next;
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
+
+ if ((luv->flag & MLOOPUV_VERTSEL) && (luv_next->flag & MLOOPUV_VERTSEL)) {
+ luv->flag |= MLOOPUV_EDGESEL;
+ }
+ else {
+ luv->flag &= ~MLOOPUV_EDGESEL;
+ }
+ }
+ }
+}
+
+/**
+ * Flushes selection downwards (edge to verts)
+ * Could be renamed to uv_validate_selection_state()
+ *
+ * UNUSUAL CASE : Flushing downwards
+ * Useful when edges that need to be selected are marked using MLOOPUV_EDGESEL flag
+ */
+void uv_flush_edge_to_vert(Scene *scene, Object *obedit, const int cd_loop_uv_offset)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ 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) {
+ MLoopUV *luv, *luv_next;
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
+
+ if (luv->flag & MLOOPUV_EDGESEL) {
+ luv->flag |= MLOOPUV_VERTSEL;
+ luv_next->flag |= MLOOPUV_VERTSEL;
+ }
+ }
+ }
+}
+
+/** \} */
+
+/* NOTE : UV Selection mode flushing NOT implemented for now
+ * Currently there's now way to know the instant when the user changes UV selection modes. */
/* -------------------------------------------------------------------- */
/** \name Find Nearest to Element
@@ -1581,9 +1755,9 @@ static void uv_select_linked_multi(Sc
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list