[Bf-blender-cvs] [a2bb480] soc-2016-uv_tools: Added "Scale to bounds" operator to scale selected islands to UV boundaries

Phil Gosch noreply at git.blender.org
Thu Jun 9 16:51:27 CEST 2016


Commit: a2bb48080d59879b43309ae5c27e9ffda053a4d8
Author: Phil Gosch
Date:   Thu Jun 9 16:50:49 2016 +0200
Branches: soc-2016-uv_tools
https://developer.blender.org/rBa2bb48080d59879b43309ae5c27e9ffda053a4d8

Added "Scale to bounds" operator to scale selected islands to UV boundaries

Options:
* Keep aspect ratio: If checked the aspect ratio of the selected uv islands is preserved
* Individual: If checked the individual uv islands are all scaled to fit the bounds, otherwise the selections are scaled as a whole

Note: Menu locations/shortcuts are to be discussed with users and not to be seen as final

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

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_unwrap_ops.c

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

diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 49a4d3d..aadd003 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -348,6 +348,7 @@ class IMAGE_MT_uvs(Menu):
         layout.operator("uv.mark_seam", text="Clear Seam").clear = True
         layout.operator("uv.seams_from_islands")
         layout.operator("mesh.faces_mirror_uv")
+        layout.operator("uv.scale_to_bounds")
 
         layout.separator()
 
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index f812fe5..119e23d 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -109,6 +109,9 @@ void ED_unwrap_lscm(struct Scene *scene, struct Object *obedit, const short sel)
 /* select shortest path */
 bool ED_uvedit_shortest_path_select(struct Scene *scene, struct Object *ob, struct BMesh *bm, bool topo_dist);
 
+/* scale to bounds */
+void ED_uvedit_scale_to_bounds(struct Scene *scene, struct Object *ob,struct BMesh *bm);
+
 /* uvedit_draw.c */
 void ED_image_draw_cursor(struct ARegion *ar, const float cursor[2]);
 void ED_uvedit_draw_main(struct SpaceImage *sima, struct ARegion *ar, struct Scene *scene, struct Object *obedit, struct Object *obact);
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 5caeac8..7b526e6 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -1617,6 +1617,99 @@ static void UV_OT_select_shortest_path(wmOperatorType *ot)
 	/* properties */
 	RNA_def_boolean(ot->srna, "topological_distance", 0, "Topological Distance", "Find the minimum number of steps, ignoring spatial distance");
 }
+/* ******************** scale to bounds operator **************** */
+
+static int uv_scale_to_bounds_exec(bContext *C, wmOperator *op)
+{
+	Scene *scene = CTX_data_scene(C);
+	Object *obedit = CTX_data_edit_object(C);
+	Image *ima = CTX_data_edit_image(C);
+	BMEditMesh *em = BKE_editmesh_from_object(obedit);
+	BMesh *bm = em->bm;
+
+	BMFace *efa;
+	BMLoop *l;
+	BMIter iter, liter;
+	MLoopUV *luv;
+	MTexPoly *tf;
+	float dx, dy, min[2], max[2];
+
+	const bool keep_aspect = RNA_boolean_get(op->ptr, "keep_aspect_ratio");
+	const bool individual = RNA_boolean_get(op->ptr, "individual_islands");
+
+	const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+	const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
+	
+	if (individual){
+		ED_uvedit_scale_to_bounds(scene, obedit, bm);
+
+		return OPERATOR_FINISHED;
+	}
+
+	INIT_MINMAX2(min, max);
+
+	BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
+		tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
+
+		if (!uvedit_face_visible_test(scene, ima, efa, tf) || !uvedit_face_select_test(scene, efa, cd_loop_uv_offset))
+			continue;
+
+		BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
+			MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+			minmax_v2v2_v2(min, max, luv->uv);
+		}
+	}
+
+	/* rescale UV to be in 1/1 */
+	dx = (max[0] - min[0]);
+	dy = (max[1] - min[1]);
+
+	if (dx > 0.0f)
+		dx = 1.0f / dx;
+	if (dy > 0.0f)
+		dy = 1.0f / dy;
+
+	if (keep_aspect) {
+		if (dx >= dy) dx = dy;
+		else if (dy > dx) dy = dx;
+	}
+
+	BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
+		tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
+
+		if (!uvedit_face_visible_test(scene, ima, efa, tf) || !uvedit_face_select_test(scene, efa, cd_loop_uv_offset))
+			continue;
+
+		BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
+			MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+
+			luv->uv[0] = (luv->uv[0] - min[0]) * dx;
+			luv->uv[1] = (luv->uv[1] - min[1]) * dy;
+		}
+	}
+
+	DAG_id_tag_update(obedit->data, 0);
+	WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+
+	return OPERATOR_FINISHED;
+}
+
+static void UV_OT_scale_to_bounds(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "Scale To Bounds";
+	ot->description = "Scale the selection to fit UV boundaries";
+	ot->idname = "UV_OT_scale_to_bounds";
+	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+	/* api callbacks */
+	ot->exec = uv_scale_to_bounds_exec;
+	ot->poll = ED_operator_uvedit;
+
+	/* properties */
+	RNA_def_boolean(ot->srna, "keep_aspect_ratio", 1, "Keep Aspect Ratio", "Keep the current aspect ratio of the selection");
+	RNA_def_boolean(ot->srna, "individual_islands", 0, "Individual", "Scale individual islands or the selection as a whole");
+}
 
 /* ******************** align operator **************** */
 
@@ -4397,6 +4490,7 @@ void ED_operatortypes_uvedit(void)
 	WM_operatortype_append(UV_OT_snap_cursor);
 	WM_operatortype_append(UV_OT_snap_selected);
 
+	WM_operatortype_append(UV_OT_scale_to_bounds);
 	WM_operatortype_append(UV_OT_align);
 
 	WM_operatortype_append(UV_OT_stitch);
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index df0473d..1131f7c 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; 
 }
 
+/* ******************** Scale To Bounds operator **************** */
+void ED_uvedit_scale_to_bounds(Scene *scene, Object *ob, BMesh *bm)
+{
+	ParamHandle *handle;
+	int hparams = set_handle_params(true, false, true, true, false);
+	handle = construct_param_handle(scene, ob, bm, hparams);
+	param_scale_bounds(handle);
+	param_flush(handle);
+	param_delete(handle);
+}
+
 /* ******************** Pack Islands operator **************** */
 
 void ED_uvedit_pack_islands(Scene *scene, Object *ob, BMesh *bm, bool selected, bool correct_aspect, bool do_rotate)




More information about the Bf-blender-cvs mailing list