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)

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

Reply via email to