Commit: d3f89408c7c47b3ddd264ed1b4161da7fb6e2d3c
Author: Phil Gosch
Date:   Mon Jul 4 14:54:52 2016 +0200
Branches: soc-2016-uv_tools
https://developer.blender.org/rBd3f89408c7c47b3ddd264ed1b4161da7fb6e2d3c

Select overlapping UVs operator

Found via Select->Select all by trait->Overlapping UVs menu entry, selects all 
UV charts which overlap/intersect
Operator has an "Extend" option to extend the current selection.

I also turned rectangle/bounds intersection test into a seperate function which 
can be reused

===================================================================

M       release/scripts/startup/bl_ui/space_image.py
M       source/blender/editors/include/ED_uvedit.h
M       source/blender/editors/uvedit/uvedit_ops.c
M       source/blender/editors/uvedit/uvedit_parametrizer.c
M       source/blender/editors/uvedit/uvedit_parametrizer.h
M       source/blender/editors/uvedit/uvedit_unwrap_ops.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/space_image.py 
b/release/scripts/startup/bl_ui/space_image.py
index 4811bd4..0d60b02 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -126,6 +126,12 @@ class IMAGE_MT_view(Menu):
         layout.operator("screen.screen_full_area")
         layout.operator("screen.screen_full_area", text="Toggle Fullscreen 
Area").use_hide_panels = True
 
+class IMAGE_MT_uvs_select_by_trait(Menu):
+    bl_label = "Select All by Trait"
+    
+    def draw(self, context):
+        layout = self.layout
+        layout.operator("uv.select_overlapping")
 
 class IMAGE_MT_select(Menu):
     bl_label = "Select"
@@ -149,6 +155,8 @@ class IMAGE_MT_select(Menu):
         layout.operator("uv.select_shortest_path")
 
         layout.separator()
+        layout.menu("IMAGE_MT_uvs_select_by_trait")
+        layout.separator()
 
         layout.operator("uv.select_less", text="Less")
         layout.operator("uv.select_more", text="More")
diff --git a/source/blender/editors/include/ED_uvedit.h 
b/source/blender/editors/include/ED_uvedit.h
index c5a1e66..4e5ef0d 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -108,6 +108,9 @@ void ED_uvedit_unwrap_cube_project(struct Object *ob, 
struct BMesh *bm, float cu
 /* single call up unwrap using scene settings, used for edge tag unwrapping */
 void ED_unwrap_lscm(struct Scene *scene, struct Object *obedit, const short 
sel);
 
+/* select by trait */
+void ED_uvedit_overlapping_select(struct Scene *scene, struct OBject *ob, 
struct BMesh *bm, const bool extend);
+
 /* select shortest path */
 bool ED_uvedit_shortest_path_select(struct Scene *scene, struct Object *ob, 
struct BMesh *bm, bool topo_dist);
 
diff --git a/source/blender/editors/uvedit/uvedit_ops.c 
b/source/blender/editors/uvedit/uvedit_ops.c
index 20bcfc5..b499f70 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -4288,6 +4288,38 @@ static void UV_OT_select_mesh(wmOperatorType *ot)
        ot->poll = ED_operator_uvedit;
 }
 
+/******************** select overlapping operator ********************/
+
+static int UV_OT_select_overlapping_exec(bContext *C, wmOperator *op)
+{
+       Object *obedit = CTX_data_edit_object(C);
+       Scene *scene = CTX_data_scene(C);
+       BMEditMesh *em = BKE_editmesh_from_object(obedit);
+       BMesh *bm = em->bm;
+
+       const bool extend = RNA_boolean_get(op->ptr, "extend");
+
+       ED_uvedit_overlapping_select(scene, obedit, bm, extend);
+
+       WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+       return OPERATOR_FINISHED;
+}
+static void UV_OT_select_overlapping(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Select Overlapping UVs";
+       ot->description = "Select all overlapping UV islands";
+       ot->idname = "UV_OT_select_overlapping";
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+       /* api callbacks */
+       ot->exec = UV_OT_select_overlapping_exec;
+       ot->poll = ED_operator_uvedit;
+
+       RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend current 
selection");
+}
+
 /******************** set 3d cursor operator ********************/
 
 static int uv_set_2d_cursor_poll(bContext *C)
@@ -4645,6 +4677,7 @@ void ED_operatortypes_uvedit(void)
        WM_operatortype_append(UV_OT_select_more);
        WM_operatortype_append(UV_OT_select_less);
        WM_operatortype_append(UV_OT_select_shortest_path);
+       WM_operatortype_append(UV_OT_select_overlapping);
 
        WM_operatortype_append(UV_OT_snap_cursor);
        WM_operatortype_append(UV_OT_snap_selected);
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c 
b/source/blender/editors/uvedit/uvedit_parametrizer.c
index 5ac81d2..7835bb6 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -621,6 +621,18 @@ static PBool p_intersect_line_segments_2d(float *a, float 
*b, float *c, float *d
        return P_FALSE;
 }
 
+bool p_rect_intersect(float min1[2], float max1[2], float min2[2], float 
max2[2])
+{
+       if (min1[0] > max2[0] ||
+               max1[0] < min2[0] ||
+               min1[1] > max2[1] ||
+               max1[1] < min2[1]) {
+               return false;
+       }
+
+       return true;
+}
+
 /* Topological Utilities */
 
 static PEdge *p_wheel_edge_next(PEdge *e)
@@ -761,6 +773,12 @@ static void p_flush_uvs(PHandle *handle, PChart *chart)
                        sel_flag |= MLOOPVERT_SELECTED; /* MLOOPUV_VERTSEL*/
                        *(e->orig_flag) = sel_flag; 
                }
+               else {
+                       sel_flag = *e->orig_flag;
+                       sel_flag &= ~MLOOPEDGE_SELECTED;/* MLOOPUV_EDGESEL*/
+                       sel_flag &= ~MLOOPVERT_SELECTED; /* MLOOPUV_VERTSEL*/
+                       *(e->orig_flag) = sel_flag;
+               }
        }
 }
 
@@ -1468,6 +1486,46 @@ static void p_chart_fill_boundaries(PChart *chart, PEdge 
*outer)
        }
 }
 
+static bool p_charts_intersect(PChart* a, PChart *b)
+{
+       PEdge *e1, *e2;
+       float min1[2], min2[2], max1[2], max2[2];
+
+       /* Check for overlapping bounding rectangles */
+       p_chart_uv_bbox(a, min1, max1);
+       p_chart_uv_bbox(b, min2, max2);
+
+       if (!p_rect_intersect(min1, max1, min2, max2)) {
+               return false;
+       }
+
+       /* Check edges for intersections */
+       for (e1 = a->edges; e1; e1 = e1->nextlink) {
+               for (e2 = b->edges; e2; e2 = e2->nextlink) {
+                       if (p_intersect_line_segaments_2d(e1->vert->uv,
+                                                                               
         e1->nextlink->vert->uv,
+                                                                               
         e2->vert->uv,
+                                                                               
         e2->nextlink->vert->uv)) {
+                               return true;
+                       }
+               }
+       }
+
+       return false;
+}
+
+static void p_chart_select(PChart *chart, bool select)
+{
+       PEdge *e;
+
+       for (e = chart->edges; e; e = e->nextlink) {
+               if (select)
+                       e->flag |= PEDGE_SELECT;
+               else
+                       e->flag &= ~PEDGE_SELECT;
+       }
+}
+
 #if 0
 /* Polygon kernel for inserting uv's non overlapping */
 
@@ -4730,10 +4788,7 @@ void p_convex_hull_delete(PConvexHull *c_hull)
 bool p_convex_hull_intersect(PConvexHull *chull_a, PConvexHull *chull_b)
 {
        /* Preliminary bounds check */
-       if (chull_a->min_v[0] > chull_b->max_v[0] ||
-               chull_a->max_v[0] < chull_b->min_v[0] ||
-               chull_a->min_v[1] > chull_b->max_v[1] ||
-               chull_a->max_v[1] < chull_b->min_v[1]) {
+       if (!p_rect_intersect(chull_a->min_v, chull_a->max_v, chull_b->min_v, 
chull_b->max_v)) {
                return false;
        }
        
@@ -5336,6 +5391,36 @@ void param_shortest_path(ParamHandle *handle, bool 
*p_found, bool topological_di
        *p_found = success;
 }
 
+void param_select_overlapping(ParamHandle *handle, const bool extend)
+{
+       PHandle *phandle = (PHandle *)handle;
+       PChart *chart1, *chart2;
+       int i, j;
+       
+       /* deselect charts */
+       if (!extend)
+       {
+               for (i = 0; i < phandle->ncharts; i++) {
+                       chart1 = phandle->charts[i];
+                       p_chart_select(chart1, false);
+               }
+       }
+
+       /* Check charts for intersections/overlaps */
+       for (i = 0; i < phandle->ncharts; i++) {
+               chart1 = phandle->charts[i];
+
+               for (j = 0; j < phandle->ncharts; j++) {
+                       chart2 = phandle->charts[j];
+                       if ((i != j) && p_charts_intersect(chart1, chart2)) {
+                               /* select charts */
+                               p_chart_select(chart1, true);
+                               p_chart_select(chart2, true);
+                       }
+               }
+       }
+}
+
 void param_flush(ParamHandle *handle)
 {
        PHandle *phandle = (PHandle *)handle;
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.h 
b/source/blender/editors/uvedit/uvedit_parametrizer.h
index 5e48ff4..1460b22 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.h
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.h
@@ -124,6 +124,10 @@ void param_scale_bounds(ParamHandle *handle);
 
 void param_shortest_path(ParamHandle *handle, bool *p_found, bool 
topological_distance);
 
+/* Select Overlapping */
+
+void param_select_overlapping(ParamHandle *handle, bool extend);
+
 /* Flushing */
 
 void param_flush(ParamHandle *handle);
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c 
b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 7b03258..9f9cf7a 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -750,6 +750,17 @@ bool ED_uvedit_shortest_path_select(Scene *scene, Object 
*ob, BMesh *bm, bool to
        return path_found; 
 }
 
+/* ******************** Select Overlapping UVs operator **************** */
+void ED_uvedit_overlapping_select(Scene *scene, Object *ob, BMesh *bm, const 
bool extend)
+{
+       ParamHandle *handle;
+       int hparams = set_handle_params(true, false, false, true, true);
+       handle = construct_param_handle(scene, ob, bm, hparams);
+       param_select_overlapping(handle, extend);
+       param_flush(handle);
+       param_delete(handle);
+}
+
 /* ******************** Scale To Bounds operator **************** */
 void ED_uvedit_scale_to_bounds(Scene *scene, Object *ob, BMesh *bm)
 {

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to