Commit: 035fa7985d270fae197dfd155c7937b24e16e244 Author: Siddhartha Jejurkar Date: Mon Jul 26 09:22:32 2021 +0530 Branches: soc-2021-uv-editor-improvements-edge-selection https://developer.blender.org/rB035fa7985d270fae197dfd155c7937b24e16e244
UV: Edge selection support - Initial * Add UV edge selection flag - MLOOPUV_EDGESEL * Refactor existing UV element selection functions to use the edge selection flag wherever required * Refactor existing UV element check functions to ensure proper selection states using the edge selection flag * Refactor UV select all operator to use edge selection flag * New functions for selecting vertices or edges that share the same location, either on 3D mesh or in UV space. * Add small penalty for finding the nearest UV edge. Ensures that UV edge selection will select other edges sharing the same location in successive selection attempts. * Expose UV edge selection flag as boolean in Python Differential Revision: https://developer.blender.org/D12028 =================================================================== M source/blender/editors/include/ED_uvedit.h M source/blender/editors/uvedit/uvedit_intern.h M source/blender/editors/uvedit/uvedit_path.c M source/blender/editors/uvedit/uvedit_select.c M source/blender/editors/uvedit/uvedit_smart_stitch.c M source/blender/makesdna/DNA_meshdata_types.h M source/blender/makesrna/intern/rna_mesh.c M source/blender/python/bmesh/bmesh_py_types_meshdata.c =================================================================== diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h index ea3d921f2c5..157fc450e70 100644 --- a/source/blender/editors/include/ED_uvedit.h +++ b/source/blender/editors/include/ED_uvedit.h @@ -145,6 +145,13 @@ void uvedit_edge_select_set_with_sticky(const struct SpaceImage *sima, const bool select, const bool do_history, const uint cd_loop_uv_offset); +void uvedit_edge_select_shared_location(const struct Scene *scene, + struct BMEditMesh *em, + struct BMLoop *l, + const bool select, + const bool use_mesh_location, + const bool do_history, + const uint cd_loop_uv_offset); void uvedit_edge_select_set(const struct Scene *scene, struct BMEditMesh *em, struct BMLoop *l, @@ -168,6 +175,13 @@ void uvedit_uv_select_set_with_sticky(const struct SpaceImage *sima, const bool select, const bool do_history, const uint cd_loop_uv_offset); +void uvedit_uv_select_shared_location(const struct Scene *scene, + struct BMEditMesh *em, + struct BMLoop *l, + const bool select, + const bool use_mesh_location, + const bool do_history, + const uint cd_loop_uv_offset); void uvedit_uv_select_set(const struct Scene *scene, struct BMEditMesh *em, struct BMLoop *l, diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h index cd8fbd00316..ea72b859f7c 100644 --- a/source/blender/editors/uvedit/uvedit_intern.h +++ b/source/blender/editors/uvedit/uvedit_intern.h @@ -86,11 +86,13 @@ bool uv_find_nearest_vert_multi(struct Scene *scene, bool uv_find_nearest_edge(struct Scene *scene, struct Object *obedit, const float co[2], + const float penalty, struct UvNearestHit *hit); bool uv_find_nearest_edge_multi(struct Scene *scene, struct Object **objects, const uint objects_len, const float co[2], + const float penalty, struct UvNearestHit *hit); bool uv_find_nearest_face_ex(struct Scene *scene, diff --git a/source/blender/editors/uvedit/uvedit_path.c b/source/blender/editors/uvedit/uvedit_path.c index 2613c5b23a0..1f3ba206103 100644 --- a/source/blender/editors/uvedit/uvedit_path.c +++ b/source/blender/editors/uvedit/uvedit_path.c @@ -627,7 +627,7 @@ static int uv_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEve else if (uv_selectmode & UV_SELECT_EDGE) { UvNearestHit hit = UV_NEAREST_HIT_INIT_MAX(®ion->v2d); - if (!uv_find_nearest_edge(scene, obedit, co, &hit)) { + if (!uv_find_nearest_edge(scene, obedit, co, 0.0f, &hit)) { return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c index 4c597d80534..aac9b8a419d 100644 --- a/source/blender/editors/uvedit/uvedit_select.c +++ b/source/blender/editors/uvedit/uvedit_select.c @@ -246,6 +246,9 @@ bool uvedit_face_select_test_ex(const ToolSettings *ts, BMFace *efa, const int c if (!(luv->flag & MLOOPUV_VERTSEL)) { return false; } + if (!(luv->flag & MLOOPUV_EDGESEL)) { + return false; + } } return true; } @@ -268,12 +271,33 @@ void uvedit_face_select_set_with_sticky(const SpaceImage *sima, return; } - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(efa); - do { - uvedit_uv_select_set_with_sticky( - sima, scene, em, l_iter, select, do_history, cd_loop_uv_offset); - } while ((l_iter = l_iter->next) != l_first); + const int sticky = sima->sticky; + switch (sticky) { + case SI_STICKY_DISABLE: { + if (uvedit_face_visible_test(scene, efa)) { + uvedit_face_select_set(scene, em, efa, select, do_history, cd_loop_uv_offset); + } + break; + } + case SI_STICKY_LOC: + case SI_STICKY_VERTEX: + default: { + /* Sticky location and vertex modes. */ + /* Fallback, in case sima->sticky is invalid */ + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(efa); + do { + uvedit_edge_select_shared_location( + scene, em, l_iter, select, false, do_history, cd_loop_uv_offset); + + uvedit_uv_select_shared_location( + scene, em, l_iter, select, false, do_history, cd_loop_uv_offset); + uvedit_uv_select_shared_location( + scene, em, l_iter->next, select, false, do_history, cd_loop_uv_offset); + } while ((l_iter = l_iter->next) != l_first); + break; + } + } } void uvedit_face_select_set(const struct Scene *scene, @@ -313,6 +337,7 @@ void uvedit_face_select_enable(const Scene *scene, BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag |= MLOOPUV_VERTSEL; + luv->flag |= MLOOPUV_EDGESEL; } } } @@ -335,6 +360,7 @@ void uvedit_face_select_disable(const Scene *scene, BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag &= ~MLOOPUV_VERTSEL; + luv->flag &= ~MLOOPUV_EDGESEL; } } } @@ -357,7 +383,12 @@ bool uvedit_edge_select_test_ex(const ToolSettings *ts, BMLoop *l, const int cd_ luv1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv2 = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); - return (luv1->flag & MLOOPUV_VERTSEL) && (luv2->flag & MLOOPUV_VERTSEL); + /* UV edge is selected only if : + * - first UV vertex in luv1 is selected + * - second UV vertex in luv2 is selected + * - MLOOPUV_EDGESEL flag is set for luv1 */ + return (luv1->flag & MLOOPUV_VERTSEL) && (luv2->flag & MLOOPUV_VERTSEL) && + (luv1->flag & MLOOPUV_EDGESEL); } bool uvedit_edge_select_test(const Scene *scene, BMLoop *l, const int cd_loop_uv_offset) { @@ -378,9 +409,86 @@ void uvedit_edge_select_set_with_sticky(const struct SpaceImage *sima, return; } - uvedit_uv_select_set_with_sticky(sima, scene, em, l, select, do_history, cd_loop_uv_offset); - uvedit_uv_select_set_with_sticky( - sima, scene, em, l->next, select, do_history, cd_loop_uv_offset); + const int sticky = sima->sticky; + switch (sticky) { + case SI_STICKY_DISABLE: { + if (uvedit_face_visible_test(scene, l->f)) { + uvedit_edge_select_set(scene, em, l, select, do_history, cd_loop_uv_offset); + } + break; + } + case SI_STICKY_VERTEX: { + BMLoop *l_radial_iter = l; + do { + if (uvedit_face_visible_test(scene, l_radial_iter->f)) { + uvedit_edge_select_set(scene, em, l_radial_iter, select, do_history, cd_loop_uv_offset); + + uvedit_uv_select_shared_location( + scene, em, l_radial_iter, select, false, do_history, cd_loop_uv_offset); + uvedit_uv_select_shared_location( + scene, em, l_radial_iter->next, select, false, do_history, cd_loop_uv_offset); + } + + } while ((l_radial_iter = l_radial_iter->radial_next) != l); + break; + } + 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: 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); + + break; + } + } +} + +/* Selects UV edges sharing the same location as l->e + * + * If use_mesh_location is : + * - true :- selects all UV edges sharing the same location on the 3D mesh + * - false :- selects all UV edges sharing the same location in UV space */ +void uvedit_edge_select_shared_location(const Scene *scene, + BMEditMesh *em, + BMLoop *l, + const bool select, + const bool use_mesh_location, + const bool do_history, + const uint cd_loop_uv_offset) +{ + const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + BMLoop *l_radial_iter = l; + do { + if (uvedit_face_visible_test(scene, l_radial_iter->f)) { + + if (use_mesh_location) { + uvedit_edge_select_set(scene, em, l_radial_iter, select, do_history, cd_loop_uv_offset); + } + else { + const MLoopUV *luv_other, *luv_next, *luv_other_next; + luv_other = BM_ELEM_CD_GET_VOID_P(l_radial_iter, cd_loop_uv_offset); + luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); + luv_other_next = BM_ELEM_CD_GET_VOID_P(l_radial_iter->next, cd_loop_uv_offset); + /* Check the current and next loop to account for the possibilty of opposite directions + * of a loop in a particular edge's radial cycle */ + if (equals_v2v2(luv->uv, luv_oth @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list [email protected] List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs
