[Bf-blender-cvs] [d3f8940] soc-2016-uv_tools: Select overlapping UVs operator

Phil Gosch noreply at git.blender.org
Mon Jul 4 14:56:29 CEST 2016


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)
 {




More information about the Bf-blender-cvs mailing list