[Bf-blender-cvs] [c1f7f18a8e6] blender-v2.93-release: Fix T81247: Constrain selected UVs to correct UDIM

Siddhartha Jejurkar noreply at git.blender.org
Wed May 12 16:14:02 CEST 2021


Commit: c1f7f18a8e6c82fddaa6ec06b7b78e3d2c64a1c8
Author: Siddhartha Jejurkar
Date:   Thu May 13 00:08:16 2021 +1000
Branches: blender-v2.93-release
https://developer.blender.org/rBc1f7f18a8e6c82fddaa6ec06b7b78e3d2c64a1c8

Fix T81247: Constrain selected UVs to correct UDIM

With Constrain to Image Bounds selected, UVs will be constrained to the
correct/closest UDIM if the image is tiled.
UVs will be constrained to the 0-1 UV space if the image is not tiled.
This will override the present behavior of always constraining selected
UVs to the 0-1 UV space (UDIM 1001).

Reviewed By: campbellbarton

Ref D11202

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

M	source/blender/blenkernel/BKE_image.h
M	source/blender/blenkernel/intern/image.c
M	source/blender/editors/transform/transform_convert.c

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

diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index c51a5f7e5e1..d298e5dcf6d 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -325,6 +325,7 @@ int BKE_image_get_tile_from_pos(struct Image *ima,
                                 const float uv[2],
                                 float r_uv[2],
                                 float r_ofs[2]);
+int BKE_image_find_nearest_tile(const struct Image *image, const float co[2]);
 
 void BKE_image_get_size(struct Image *image, struct ImageUser *iuser, int *r_width, int *r_height);
 void BKE_image_get_size_fl(struct Image *image, struct ImageUser *iuser, float r_size[2]);
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 368b1c2e66b..2f7e2b41a73 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -735,6 +735,37 @@ int BKE_image_get_tile_from_pos(struct Image *ima,
   return tile_number;
 }
 
+/**
+ * Return the tile_number for the closest UDIM tile.
+ */
+int BKE_image_find_nearest_tile(const Image *image, const float co[2])
+{
+  const float co_floor[2] = {floorf(co[0]), floorf(co[1])};
+  /* Distance to the closest UDIM tile. */
+  float dist_best_sq = FLT_MAX;
+  int tile_number_best = -1;
+
+  LISTBASE_FOREACH (const ImageTile *, tile, &image->tiles) {
+    const int tile_index = tile->tile_number - 1001;
+    /* Coordinates of the current tile. */
+    const float tile_index_co[2] = {tile_index % 10, tile_index / 10};
+
+    if (equals_v2v2(co_floor, tile_index_co)) {
+      return tile->tile_number;
+    }
+
+    /* Distance between co[2] and UDIM tile. */
+    const float dist_sq = len_squared_v2v2(tile_index_co, co);
+
+    if (dist_sq < dist_best_sq) {
+      dist_best_sq = dist_sq;
+      tile_number_best = tile->tile_number;
+    }
+  }
+
+  return tile_number_best;
+}
+
 static void image_init_color_management(Image *ima)
 {
   ImBuf *ibuf;
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index c021c084a23..7239bed1eeb 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -37,6 +37,7 @@
 #include "BKE_context.h"
 #include "BKE_fcurve.h"
 #include "BKE_global.h"
+#include "BKE_image.h"
 #include "BKE_layer.h"
 #include "BKE_lib_id.h"
 #include "BKE_main.h"
@@ -505,9 +506,27 @@ bool clipUVTransform(TransInfo *t, float vec[2], const bool resize)
   bool clipx = true, clipy = true;
   float min[2], max[2];
 
-  min[0] = min[1] = 0.0f;
-  max[0] = t->aspect[0];
-  max[1] = t->aspect[1];
+  /* Check if the current image in UV editor is a tiled image or not. */
+  const SpaceImage *sima = t->area->spacedata.first;
+  const Image *image = sima->image;
+  const bool is_tiled_image = image && (image->source == IMA_SRC_TILED);
+  /* Stores the coordinates of the closest UDIM tile.
+   * Also acts as an offset to the tile from the origin of UV space. */
+  float base_offset[2] = {0.0f, 0.0f};
+
+  /* If tiled image then constrain to correct/closest UDIM tile, else 0-1 UV space. */
+  if (is_tiled_image) {
+    int nearest_tile_index = BKE_image_find_nearest_tile(image, t->center_global);
+    if (nearest_tile_index != -1) {
+      nearest_tile_index -= 1001;
+      /* Getting coordinates of nearest tile from the tile index. */
+      base_offset[0] = nearest_tile_index % 10;
+      base_offset[1] = nearest_tile_index / 10;
+    }
+  }
+
+  min[0] = min[1] = FLT_MAX;
+  max[0] = max[1] = FLT_MIN;
 
   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
 
@@ -520,42 +539,48 @@ bool clipUVTransform(TransInfo *t, float vec[2], const bool resize)
   }
 
   if (resize) {
-    if (min[0] < 0.0f && t->center_global[0] > 0.0f && t->center_global[0] < t->aspect[0] * 0.5f) {
-      vec[0] *= t->center_global[0] / (t->center_global[0] - min[0]);
+    if (min[0] < base_offset[0] && t->center_global[0] > base_offset[0] &&
+        t->center_global[0] < base_offset[0] + (t->aspect[0] * 0.5f)) {
+      vec[0] *= (t->center_global[0] - base_offset[0]) / (t->center_global[0] - min[0]);
     }
-    else if (max[0] > t->aspect[0] && t->center_global[0] < t->aspect[0]) {
-      vec[0] *= (t->center_global[0] - t->aspect[0]) / (t->center_global[0] - max[0]);
+    else if (max[0] > (base_offset[0] + t->aspect[0]) &&
+             t->center_global[0] < (base_offset[0] + t->aspect[0])) {
+      vec[0] *= (t->center_global[0] - (base_offset[0] + t->aspect[0])) /
+                (t->center_global[0] - max[0]);
     }
     else {
       clipx = 0;
     }
 
-    if (min[1] < 0.0f && t->center_global[1] > 0.0f && t->center_global[1] < t->aspect[1] * 0.5f) {
-      vec[1] *= t->center_global[1] / (t->center_global[1] - min[1]);
+    if (min[1] < base_offset[1] && t->center_global[1] > base_offset[1] &&
+        t->center_global[1] < base_offset[1] + (t->aspect[1] * 0.5f)) {
+      vec[1] *= (t->center_global[1] - base_offset[1]) / (t->center_global[1] - min[1]);
     }
-    else if (max[1] > t->aspect[1] && t->center_global[1] < t->aspect[1]) {
-      vec[1] *= (t->center_global[1] - t->aspect[1]) / (t->center_global[1] - max[1]);
+    else if (max[1] > (base_offset[1] + t->aspect[1]) &&
+             t->center_global[1] < (base_offset[1] + t->aspect[1])) {
+      vec[1] *= (t->center_global[1] - (base_offset[1] + t->aspect[1])) /
+                (t->center_global[1] - max[1]);
     }
     else {
       clipy = 0;
     }
   }
   else {
-    if (min[0] < 0.0f) {
-      vec[0] -= min[0];
+    if (min[0] < base_offset[0]) {
+      vec[0] += base_offset[0] - min[0];
     }
-    else if (max[0] > t->aspect[0]) {
-      vec[0] -= max[0] - t->aspect[0];
+    else if (max[0] > base_offset[0] + t->aspect[0]) {
+      vec[0] -= max[0] - base_offset[0] - t->aspect[0];
     }
     else {
       clipx = 0;
     }
 
-    if (min[1] < 0.0f) {
-      vec[1] -= min[1];
+    if (min[1] < base_offset[1]) {
+      vec[1] += base_offset[1] - min[1];
     }
-    else if (max[1] > t->aspect[1]) {
-      vec[1] -= max[1] - t->aspect[1];
+    else if (max[1] > base_offset[1] + t->aspect[1]) {
+      vec[1] -= max[1] - base_offset[1] - t->aspect[1];
     }
     else {
       clipy = 0;



More information about the Bf-blender-cvs mailing list