[Bf-blender-cvs] [a7f24a8307c] soc-2021-uv-editor-improvements-edge-selection: Edge selection support for Edge ring and loop select operator
Siddhartha Jejurkar
noreply at git.blender.org
Sun Aug 8 23:34:58 CEST 2021
Commit: a7f24a8307ce2fedbca27495344a9d7623c094f1
Author: Siddhartha Jejurkar
Date: Mon Aug 9 03:00:27 2021 +0530
Branches: soc-2021-uv-editor-improvements-edge-selection
https://developer.blender.org/rBa7f24a8307ce2fedbca27495344a9d7623c094f1
Edge selection support for Edge ring and loop select operator
* Adds edge selection support for edge ring and edge loop select operator
* Selecting face loops in the UV editor is now done through the loop
select operator
===================================================================
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 2ba64bb7961..d7762775296 100644
--- a/source/blender/editors/uvedit/uvedit_select.c
+++ b/source/blender/editors/uvedit/uvedit_select.c
@@ -844,14 +844,10 @@ void uvedit_uv_select_disable(const Scene *scene,
}
}
-/* Returns a radial loop which shares the same UV edge and has a visible UV face.
- * If more than one such radial loops exist then return NULL */
static BMLoop *uvedit_loop_find_other_radial_loop_with_visible_face(const Scene *scene,
BMLoop *l_src,
const int cd_loop_uv_offset)
{
- /* This function basically tells if the UV edge associated with this loop is a boundry edge or if
- * it is shared with another UV face or not */
BMLoop *l_other = NULL;
BMLoop *l_iter = l_src->radial_next;
if (l_iter != l_src) {
@@ -873,14 +869,11 @@ static BMLoop *uvedit_loop_find_other_radial_loop_with_visible_face(const Scene
return l_other;
}
-/* Finds the loop belonging to another face that is also a boundry loop (is at the boundry of UV)
- */
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)
{
- /* This function helps find another loop whose UV edge is also a boundry edge) */
BLI_assert(uvedit_loop_find_other_radial_loop_with_visible_face(
scene, l_edge, cd_loop_uv_offset) == NULL);
@@ -1645,7 +1638,7 @@ static int uv_select_edgeloop(
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
if (extend) {
- select = !(uvedit_uv_select_test(scene, hit->l, cd_loop_uv_offset));
+ select = !(uvedit_edge_select_test(scene, hit->l, cd_loop_uv_offset));
}
else {
select = true;
@@ -1712,6 +1705,70 @@ static int uv_select_edgeloop(
/** \} */
+/* -------------------------------------------------------------------- */
+/** \name Face Loop Select
+ * \{ */
+
+static int uv_select_faceloop(
+ const SpaceImage *sima, Scene *scene, Object *obedit, UvNearestHit *hit, const bool extend)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ bool select;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ if (!extend) {
+ uv_select_all_perform(scene, NULL, obedit, SEL_DESELECT);
+ }
+
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
+
+ if (extend) {
+ select = !(uvedit_face_select_test(scene, hit->l->f, cd_loop_uv_offset));
+ }
+ else {
+ select = true;
+ }
+
+ BMLoop *l_pair[2] = {
+ hit->l,
+ uvedit_loop_find_other_radial_loop_with_visible_face(scene, hit->l, cd_loop_uv_offset),
+ };
+
+ for (int side = 0; side < 2; side++) {
+ BMLoop *l_step = l_pair[side];
+ while (l_step) {
+ if (!uvedit_face_visible_test(scene, l_step->f)) {
+ break;
+ }
+
+ uvedit_face_select_set_with_sticky(
+ sima, scene, em, l_step->f, select, false, cd_loop_uv_offset);
+
+ BM_elem_flag_enable(l_step->f, BM_ELEM_TAG);
+ if (l_step->f->len == 4) {
+ BMLoop *l_step_opposite = l_step->next->next;
+ l_step = uvedit_loop_find_other_radial_loop_with_visible_face(
+ scene, l_step_opposite, cd_loop_uv_offset);
+ }
+ else {
+ l_step = NULL;
+ }
+
+ /* Break iteration when l_step :
+ * - is the first loop where we started from
+ * - tagged using BM_ELEM_TAG(meaning this loop has been visited in this iteration) */
+ if (l_step && BM_elem_flag_test(l_step->f, BM_ELEM_TAG)) {
+ break;
+ }
+ }
+ }
+
+ return (select) ? 1 : -1;
+}
+
+/** \} */
+
/* -------------------------------------------------------------------- */
/** \name Edge Ring Select
* \{ */
@@ -1724,6 +1781,9 @@ static int uv_select_edgering(
const bool use_face_select = (ts->uv_flag & UV_SYNC_SELECTION) ?
(ts->selectmode & SCE_SELECT_FACE) :
(ts->uv_selectmode & UV_SELECT_FACE);
+ const bool use_vertex_select = (ts->uv_flag & UV_SYNC_SELECTION) ?
+ (ts->selectmode & SCE_SELECT_VERTEX) :
+ (ts->uv_selectmode & UV_SELECT_VERTEX);
bool select;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
@@ -1735,7 +1795,7 @@ static int uv_select_edgering(
BM_mesh_elem_hflag_disable_all(em->bm, BM_EDGE, BM_ELEM_TAG, false);
if (extend) {
- select = !(uvedit_uv_select_test(scene, hit->l, cd_loop_uv_offset));
+ select = !(uvedit_edge_select_test(scene, hit->l, cd_loop_uv_offset));
}
else {
select = true;
@@ -1756,10 +1816,20 @@ static int uv_select_edgering(
}
if (use_face_select) {
+ /* While selecting face loops is now done in a separate function - uv_select_faceloop()
+ * ,this check is still kept for edge ring selection to keep it consistent with how edge
+ * ring selection works in the 3D viewport */
uvedit_face_select_set_with_sticky(
sima, scene, em, l_step->f, select, false, cd_loop_uv_offset);
}
+ else if (use_vertex_select) {
+ uvedit_uv_select_set_with_sticky(
+ sima, scene, em, l_step, select, false, cd_loop_uv_offset);
+ uvedit_uv_select_set_with_sticky(
+ sima, scene, em, l_step->next, select, false, cd_loop_uv_offset);
+ }
else {
+ /* Edge select mode */
uvedit_edge_select_set_with_sticky(
sima, scene, em, l_step, select, false, cd_loop_uv_offset);
}
@@ -1778,8 +1848,19 @@ static int uv_select_edgering(
l_step = NULL;
}
+ /* Break iteration when l_step :
+ * - is the first loop where we started from
+ * - tagged using BM_ELEM_TAG (meaning this loop has been visited in this iteration)
+ * - has its corresponding UV edge selected/unselected based on select */
if (l_step && BM_elem_flag_test(l_step->e, BM_ELEM_TAG)) {
- break;
+ /* Previously this check was not done and this resulted in the final edge in the edge ring
+ * cycle to be skipped during selection (casued by old sticky selection behavior) */
+ if (select && uvedit_edge_select_test(scene, l_step, cd_loop_uv_offset)) {
+ break;
+ }
+ else if (!select && !uvedit_edge_select_test(scene, l_step, cd_loop_uv_offset)) {
+ break;
+ }
}
}
}
@@ -2752,7 +2833,12 @@ static int uv_mouse_select_loop_generic_multi(bContext *C,
}
if (loop_type == UV_LOOP_SELECT) {
- flush = uv_select_edgeloop(sima, scene, obedit, &hit, extend);
+ if (ED_uvedit_select_mode_get(scene) == UV_SELECT_FACE) {
+ flush = uv_select_faceloop(sima, scene, obedit, &hit, extend);
+ }
+ else {
+ 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);
@@ -2804,15 +2890,7 @@ static int uv_select_loop_exec(bContext *C, wmOperator *op)
RNA_float_get_array(op->ptr, "location", co);
const bool extend = RNA_boolean_get(op->ptr, "extend");
- Scene *scene = CTX_data_scene(C);
- enum eUVLoopGenericType type = UV_LOOP_SELECT;
- if (ED_uvedit_select_mode_get(scene) == UV_SELECT_FACE) {
- /* For now ring-select and face-loop is the same thing,
- * if we support real edge selection this will no longer be the case. */
- type = UV_RING_SELECT;
- }
-
- return uv_mouse_select_loop_generic(C, co, extend, type);
+ return uv_mouse_select_loop_generic(C, co, extend, UV_LOOP_SELECT);
}
static int uv_select_loop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
More information about the Bf-blender-cvs
mailing list