[Bf-blender-cvs] [1a890011516] soc-2021-uv-editor-improvements: UV : Pack islands to correct/specified UDIM

Siddhartha Jejurkar noreply at git.blender.org
Fri Jun 11 16:30:07 CEST 2021


Commit: 1a890011516e14e57c4d1dd1b845158211a97e1a
Author: Siddhartha Jejurkar
Date:   Fri Jun 11 19:36:24 2021 +0530
Branches: soc-2021-uv-editor-improvements
https://developer.blender.org/rB1a890011516e14e57c4d1dd1b845158211a97e1a

UV : Pack islands to correct/specified UDIM

Adds 2 features to the pack islands operator

 * Packing selected UVs to the closest UDIM
 * Packing selected UVs to user specified UDIM

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

M	source/blender/editors/include/ED_uvedit.h
M	source/blender/editors/uvedit/uvedit_islands.c
M	source/blender/editors/uvedit/uvedit_unwrap_ops.c
M	source/blender/makesdna/DNA_scene_defaults.h
M	source/blender/makesdna/DNA_scene_types.h

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

diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index ea3d921f2c5..dd61768a312 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -249,6 +249,8 @@ struct UVPackIsland_Params {
 void ED_uvedit_pack_islands_multi(const struct Scene *scene,
                                   Object **objects,
                                   const uint objects_len,
+                                  const struct SpaceImage *sima,
+                                  bool use_target,
                                   const struct UVPackIsland_Params *params);
 
 #ifdef __cplusplus
diff --git a/source/blender/editors/uvedit/uvedit_islands.c b/source/blender/editors/uvedit/uvedit_islands.c
index 93948b5ae1b..a03b6670dae 100644
--- a/source/blender/editors/uvedit/uvedit_islands.c
+++ b/source/blender/editors/uvedit/uvedit_islands.c
@@ -29,6 +29,7 @@
 
 #include "DNA_meshdata_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_space_types.h"
 
 #include "BLI_boxpack_2d.h"
 #include "BLI_convexhull_2d.h"
@@ -37,6 +38,7 @@
 #include "BLI_rect.h"
 
 #include "BKE_editmesh.h"
+#include "BKE_image.h"
 
 #include "DEG_depsgraph.h"
 
@@ -358,6 +360,8 @@ static int bm_mesh_calc_uv_islands(const Scene *scene,
 void ED_uvedit_pack_islands_multi(const Scene *scene,
                                   Object **objects,
                                   const uint objects_len,
+                                  const SpaceImage *sima,
+                                  bool use_target,
                                   const struct UVPackIsland_Params *params)
 {
   /* Align to the Y axis, could make this configurable. */
@@ -365,6 +369,18 @@ void ED_uvedit_pack_islands_multi(const Scene *scene,
   ListBase island_list = {NULL};
   int island_list_len = 0;
 
+  const Image *image;
+  bool is_tiled_image = false;
+  int udim_grid[2] = {1, 1};
+
+  /* To handle cases where sima=NULL - Smart UV project */
+  if (sima) {
+    image = sima->image;
+    is_tiled_image = image && (image->source == IMA_SRC_TILED);
+    udim_grid[0] = sima->tile_grid_shape[0];
+    udim_grid[1] = sima->tile_grid_shape[1];
+  }
+
   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
     Object *obedit = objects[ob_index];
     BMEditMesh *em = BKE_editmesh_from_object(obedit);
@@ -406,8 +422,26 @@ void ED_uvedit_pack_islands_multi(const Scene *scene,
   BoxPack *boxarray = MEM_mallocN(sizeof(*boxarray) * island_list_len, __func__);
 
   int index;
+  /* Coordinates for the center of the all the selected islands */
+  float selection_center[2] = {0.0f, 0.0f};
+  float selection_min[2], selection_max[2];
+  INIT_MINMAX2(selection_min, selection_max);
+
   LISTBASE_FOREACH_INDEX (struct FaceIsland *, island, &island_list, index) {
 
+    /* Calculate bounding box of all selected islands */
+    float bounds_min[2], bounds_max[2];
+    INIT_MINMAX2(bounds_min, bounds_max);
+    for (int i = 0; i < island->faces_len; i++) {
+      BMFace *f = island->faces[i];
+      BM_face_uv_minmax(f, bounds_min, bounds_max, island->cd_loop_uv_offset);
+    }
+
+    selection_min[0] = MIN2(bounds_min[0], selection_min[0]);
+    selection_min[1] = MIN2(bounds_min[1], selection_min[1]);
+    selection_max[0] = MAX2(bounds_max[0], selection_max[0]);
+    selection_max[1] = MAX2(bounds_max[1], selection_max[1]);
+
     if (params->rotate) {
       if (island->aspect_y != 1.0f) {
         bm_face_array_uv_scale_y(
@@ -440,6 +474,10 @@ void ED_uvedit_pack_islands_multi(const Scene *scene,
     }
   }
 
+  /* Calculate the center of the bounding box */
+  selection_center[0] = (selection_min[0] + selection_max[0]) / 2.0f;
+  selection_center[1] = (selection_min[1] + selection_max[1]) / 2.0f;
+
   if (margin > 0.0f) {
     /* Logic matches behavior from #param_pack,
      * use area so multiply the margin by the area to give
@@ -463,6 +501,61 @@ void ED_uvedit_pack_islands_multi(const Scene *scene,
 
   const float scale[2] = {1.0f / boxarray_size[0], 1.0f / boxarray_size[1]};
 
+  /* Tile offset */
+  float base_offset[2] = {0.0f, 0.0f};
+
+  /* (sima = NULL) or (use_target = false) would skip the calculation of base_offset - Smart UV
+   * project */
+  if (use_target) {
+    const int specified_tile_index = scene->toolsettings->target_udim - 1001;
+    /* Calculate offset based on specified_tile_index */
+    base_offset[0] = specified_tile_index % 10;
+    base_offset[1] = specified_tile_index / 10;
+  }
+
+  /* If tiled image then constrain to correct/closest UDIM tile */
+  else if (sima && is_tiled_image && !use_target) {
+    int nearest_tile_index = BKE_image_find_nearest_tile(image, selection_center);
+    if (nearest_tile_index != -1) {
+      nearest_tile_index -= 1001;
+      /* Calculate offset based on nearest_tile_index */
+      base_offset[0] = nearest_tile_index % 10;
+      base_offset[1] = nearest_tile_index / 10;
+    }
+  }
+
+  /* If no image present then constrain to correct/closest tile on UDIM grid*/
+  else if (sima && !image && !use_target) {
+    const float co_floor[2] = {floorf(selection_center[0]), floorf(selection_center[1])};
+    if (selection_center[0] < udim_grid[0] && selection_center[0] > 0 &&
+        selection_center[1] < udim_grid[1] && selection_center[1] > 0) {
+      base_offset[0] = co_floor[0];
+      base_offset[1] = co_floor[1];
+    }
+    /* If Selected UVs lie outside the UDIM grid, constrain to closest tile on UDIM grid */
+    else {
+      if (selection_center[0] > udim_grid[0]) {
+        base_offset[0] = udim_grid[0] - 1;
+      }
+      else if (selection_center[0] < 0) {
+        base_offset[0] = 0;
+      }
+      else {
+        base_offset[0] = co_floor[0];
+      }
+
+      if (selection_center[1] > udim_grid[1]) {
+        base_offset[1] = udim_grid[1] - 1;
+      }
+      else if (selection_center[1] < 0) {
+        base_offset[1] = 0;
+      }
+      else {
+        base_offset[1] = co_floor[1];
+      }
+    }
+  }
+
   for (int i = 0; i < island_list_len; i++) {
     struct FaceIsland *island = island_array[boxarray[i].index];
     const float pivot[2] = {
@@ -470,8 +563,8 @@ void ED_uvedit_pack_islands_multi(const Scene *scene,
         island->bounds_rect.ymin,
     };
     const float offset[2] = {
-        (boxarray[i].x * scale[0]) - island->bounds_rect.xmin,
-        (boxarray[i].y * scale[1]) - island->bounds_rect.ymin,
+        (boxarray[i].x * scale[0]) - island->bounds_rect.xmin + base_offset[0],
+        (boxarray[i].y * scale[1]) - island->bounds_rect.ymin + base_offset[1],
     };
     for (int j = 0; j < island->faces_len; j++) {
       BMFace *efa = island->faces[j];
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 87ae112a237..792d56274e1 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -37,6 +37,7 @@
 #include "BLI_alloca.h"
 #include "BLI_array.h"
 #include "BLI_linklist.h"
+#include "BLI_listbase.h"
 #include "BLI_math.h"
 #include "BLI_memarena.h"
 #include "BLI_string.h"
@@ -1009,6 +1010,11 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
 {
   ViewLayer *view_layer = CTX_data_view_layer(C);
   const Scene *scene = CTX_data_scene(C);
+  const SpaceImage *sima = CTX_wm_space_image(C);
+
+  const Image *image = sima->image;
+  const bool is_tiled_image = image && (image->source == IMA_SRC_TILED);
+  bool use_target = false;
 
   const UnwrapOptions options = {
       .topology_from_uvs = true,
@@ -1020,6 +1026,57 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
 
   bool rotate = RNA_boolean_get(op->ptr, "rotate");
 
+  /* Check if specified UDIM is valid - specified tile exists in the udim grid or tiled image */
+  if (RNA_enum_get(op->ptr, "packTo") == 1) {
+    if (RNA_struct_property_is_set(op->ptr, "target_udim")) {
+      int target_udim = RNA_int_get(op->ptr, "target_udim");
+
+      /* If no image in the UV editor then check if target_UDIM lies within the UDIM grid*/
+      if (!image) {
+        target_udim -= 1001;
+        const int target_x = (target_udim % 10) + 1;
+        const int target_y = (target_udim / 10) + 1;
+
+        if (target_x <= sima->tile_grid_shape[0] && target_y <= sima->tile_grid_shape[1]) {
+          scene->toolsettings->target_udim = RNA_int_get(op->ptr, "target_udim");
+        }
+        else {
+          RNA_int_set(op->ptr, "target_udim", scene->toolsettings->target_udim);
+        }
+      }
+
+      /* If tiled image present then check if target_udim is valid */
+      else if (image && is_tiled_image) {
+        RNA_int_set(op->ptr, "target_udim", scene->toolsettings->target_udim);
+
+        LISTBASE_FOREACH (const ImageTile *, tile, &image->tiles) {
+
+          if (target_udim == tile->tile_number) {
+            scene->toolsettings->target_udim = target_udim;
+            RNA_int_set(op->ptr, "target_udim", target_udim);
+            break;
+          }
+        }
+      }
+
+      /* If non-tiled image present then always pack to UDIM 1001 */
+      else if (image && !is_tiled_image) {
+        scene->toolsettings->target_udim = 1001;
+        RNA_int_set(op->ptr, "target_udim", 1001);
+      }
+    }
+
+    /*  */
+    else {
+      scene->toolsettings->target_udim = RNA_int_get(op->ptr, "target_udim");
+    }
+    use_target = true;
+  }
+
+  else {
+    use_target = false;
+  }
+
   uint objects_len = 0;
   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
       view_layer, CTX_wm_view3d(C), &objects_len);
@@ -1039,6 +1096,8 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
   ED_uvedit_pack_islands_multi(scene,
                                objects,
                                objects_len,
+                               sima,
+                               use_target,
                                &(struct UVPackIsland_Params){
                                    .rotate = rotate,
                                    .rotate_align_axis = -1,
@@ -1052,8 +1111,32 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
   return OPERATOR_FINISHED;


@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list