Commit: d615f4d65e44109d1843441e9b3c5f145901c3c7
Author: Siddhartha Jejurkar
Date: Sat Jul 3 14:29:56 2021 +0530
Branches: soc-2021-uv-editor-improvements
https://developer.blender.org/rBd615f4d65e44109d1843441e9b3c5f145901c3c7
Fix: Pack islands to area operator
* Correct packing area coordinates for cases when user sets the maximum
coordinates to be lower than the minimum coordinates
* Cancel operator when scale option is disabled and packing area is not
big enough for selected islands. Also display warning message in UI
when this happens
===================================================================
M source/blender/blenlib/BLI_boxpack_2d.h
M source/blender/blenlib/intern/boxpack_2d.c
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
===================================================================
diff --git a/source/blender/blenlib/BLI_boxpack_2d.h
b/source/blender/blenlib/BLI_boxpack_2d.h
index 5b70cd3f410..89339b66021 100644
--- a/source/blender/blenlib/BLI_boxpack_2d.h
+++ b/source/blender/blenlib/BLI_boxpack_2d.h
@@ -64,7 +64,7 @@ void BLI_box_pack_2d_fixedarea(struct ListBase *boxes,
int height,
struct ListBase *packed);
-void BLI_rect_pack_2d(BoxPack *boxarray,
+bool BLI_rect_pack_2d(BoxPack *boxarray,
const uint len,
const float rect_width,
const float rect_height);
diff --git a/source/blender/blenlib/intern/boxpack_2d.c
b/source/blender/blenlib/intern/boxpack_2d.c
index 1679da7fc13..bddb9878a36 100644
--- a/source/blender/blenlib/intern/boxpack_2d.c
+++ b/source/blender/blenlib/intern/boxpack_2d.c
@@ -786,14 +786,8 @@ void BLI_box_pack_2d_fixedarea(ListBase *boxes, int width,
int height, ListBase
}
/* Similar implementation of BLI_box_pack_2d_fixedarea() that works with
BoxPack array and float
- * variables.
- * A current problem with the algorithm is that boxes that do not fit are not
packed (skipped), so
- * that finally causes those boxes to be placed at the bottom left position
overlapping with other
- * boxes.
- * TODO : Fix this issue by setting a callback that cancels the operator (and
possibly prints an
- * error message saying the area is too small for packing islands without
scaling) when a
- * particular box does not fit any empty space */
-void BLI_rect_pack_2d(BoxPack *boxarray,
+ * variables */
+bool BLI_rect_pack_2d(BoxPack *boxarray,
const uint len,
const float rect_width,
const float rect_height)
@@ -802,11 +796,19 @@ void BLI_rect_pack_2d(BoxPack *boxarray,
RectSizeBoxPack *full_rect = MEM_callocN(sizeof(RectSizeBoxPack), __func__);
full_rect->w = rect_width;
full_rect->h = rect_height;
+ bool is_box_packed;
BLI_addhead(&spaces, full_rect);
+ /* CHECK : Sorting is probably used incorrectly here */
qsort(boxarray, (size_t)len, sizeof(BoxPack), box_areasort);
+ /* Rotating islands in uvedits_islands.c doesn't work well with this
algorithm
+ * TODO : Implement heuristic for rotating islands - Rotate islands if they
don't fit in any
+ * empty space, but can fit if they are rotated. A boolean might be needed
per island to check if
+ * islands need to be rotated when they are translated in uvedit_islands.c */
+
for (uint i = 0; i < len; i++) {
+ is_box_packed = false;
LISTBASE_FOREACH (RectSizeBoxPack *, space, &spaces) {
/* Skip this space if it's too small. */
if (boxarray[i].w > space->w || boxarray[i].h > space->h) {
@@ -816,6 +818,7 @@ void BLI_rect_pack_2d(BoxPack *boxarray,
/* Pack this box into this space. */
boxarray[i].x = space->x;
boxarray[i].y = space->y;
+ is_box_packed = true;
if (boxarray[i].w == space->w && boxarray[i].h == space->h) {
/* Box exactly fills space, so just remove the space. */
@@ -867,7 +870,14 @@ void BLI_rect_pack_2d(BoxPack *boxarray,
break;
}
+ /* Packing area not big enough to pack all boxes */
+ if (!is_box_packed) {
+ BLI_freelistN(&spaces);
+ return false;
+ }
}
+ /* All boxes packed successfully */
BLI_freelistN(&spaces);
+ return true;
}
\ No newline at end of file
diff --git a/source/blender/editors/include/ED_uvedit.h
b/source/blender/editors/include/ED_uvedit.h
index 2dc9635a494..269590197ee 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -253,7 +253,7 @@ void ED_uvedit_pack_islands_multi(const struct Scene *scene,
bool use_target,
const struct UVPackIsland_Params *params);
-void ED_uvedit_pack_islands_to_area_multi(const struct Scene *scene,
+bool ED_uvedit_pack_islands_to_area_multi(const struct Scene *scene,
Object **objects,
const uint objects_len,
const float min_co[2],
diff --git a/source/blender/editors/uvedit/uvedit_islands.c
b/source/blender/editors/uvedit/uvedit_islands.c
index 07c8263d618..9181699a283 100644
--- a/source/blender/editors/uvedit/uvedit_islands.c
+++ b/source/blender/editors/uvedit/uvedit_islands.c
@@ -593,7 +593,7 @@ void ED_uvedit_pack_islands_multi(const Scene *scene,
/* Almost similar to ED_uvedit_pack_islands_multi().
* TODO : Break some of the code into smaller functions since same operations
are being done in
* both ED_uvedit_pack_islands_to_area_multi() and
ED_uvedit_pack_islands_multi() */
-void ED_uvedit_pack_islands_to_area_multi(const Scene *scene,
+bool ED_uvedit_pack_islands_to_area_multi(const Scene *scene,
Object **objects,
const uint objects_len,
const float min_co[2],
@@ -628,7 +628,7 @@ void ED_uvedit_pack_islands_to_area_multi(const Scene
*scene,
/* This check could probably be removed */
if (island_list_len == 0) {
- return;
+ return true;
}
float margin = scene->toolsettings->uvcalc_margin;
@@ -641,7 +641,7 @@ void ED_uvedit_pack_islands_to_area_multi(const Scene
*scene,
int index;
LISTBASE_FOREACH_INDEX (struct FaceIsland *, island, &island_list, index) {
/* For now using the same conditions for rotating islands when scaling is
enabled and disabled.
- * TODO : New heuristic for rotating islands when scaling is disabled
(using the
+ * TODO : Use new heuristic for rotating islands when scaling is disabled
(using the
* RectPack2D algorithm) */
if (params->rotate) {
if (island->aspect_y != 1.0f) {
@@ -714,7 +714,17 @@ void ED_uvedit_pack_islands_to_area_multi(const Scene
*scene,
scale[1] = 1.0f / boxarray_size[1];
}
else {
- BLI_rect_pack_2d(boxarray, island_list_len, (max_co[0] - min_co[0]),
(max_co[1] - min_co[1]));
+ if (!BLI_rect_pack_2d(
+ boxarray, island_list_len, (max_co[0] - min_co[0]), (max_co[1] -
min_co[1]))) {
+ /* Cancel operator : Packing area not big enough for selected islands */
+ for (int i = 0; i < island_list_len; i++) {
+ MEM_freeN(island_array[i]->faces);
+ MEM_freeN(island_array[i]);
+ }
+ MEM_freeN(island_array);
+ MEM_freeN(boxarray);
+ return false;
+ }
}
for (int i = 0; i < island_list_len; i++) {
@@ -758,4 +768,7 @@ void ED_uvedit_pack_islands_to_area_multi(const Scene
*scene,
MEM_freeN(island_array);
MEM_freeN(boxarray);
+
+ /* All islands packed successfully */
+ return true;
}
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 745a242050f..c780e7134f6 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -1185,38 +1185,65 @@ static int pack_islands_to_area_exec(bContext *C,
wmOperator *op)
view_layer, CTX_wm_view3d(C), &objects_len);
/* Packing area coordinates */
- float min_co[2] = {0.0f, 0.0f};
- float max_co[2] = {1.0f, 1.0f};
-
- /* Fixes the issue of modified packing coordinates when user reuses the
operator from the
- * properties panel after zooming in/out in the UV editor */
- if (RNA_struct_property_is_set(op->ptr, "box_min_co") ||
- RNA_struct_property_is_set(op->ptr, "box_max_co") ||
- RNA_struct_property_is_set(op->ptr, "rotate") ||
- RNA_struct_property_is_set(op->ptr, "scale") ||
- RNA_struct_property_is_set(op->ptr, "margin")) {
- RNA_float_get_array(op->ptr, "box_min_co", min_co);
- RNA_float_get_array(op->ptr, "box_max_co", max_co);
- }
- /* MISSING : Implement a way to clamp box coordinates properly so that
invalid cases such as
- * (max_co < min_co) are handled */
+ float box_min_co[2] = {0.0f, 0.0f};
+ float box_max_co[2] = {1.0f, 1.0f};
+ /* Store coordinates for operator rerun */
+ float pack_area[4] = {0.0f, 0.0f, 1.0f, 1.0f};
+
+ rctf bounds;
+ WM_operator_properties_border_to_rctf(op, &bounds);
+ UI_view2d_region_to_view_rctf(®ion->v2d, &bounds, &bounds);
+ /* Bounding coordinates for the user-defined area */
+ box_min_co[0] = bounds.xmin;
+ box_min_co[1] = bounds.ymin;
+ box_max_co[0] = bounds.xmax;
+ box_max_co[1] = bounds.ymax;
+
+ RNA_float_get_array(op->ptr, "pack_area", pack_area);
+
+ /* Running operator through modal callback */
+ if (!RNA_struct_property_is_set(op->ptr, "pack_area")) {
+ RNA_float_set_array(op->ptr, "box_min_co", box_min_co);
+ RNA_float_set_array(op->ptr, "box_max_co", box_max_co);
+
+ pack_area[0] = box_min_co[0];
+ pack_area[1] = box_min_co[1];
+ pack_area[2] = box_max_co[0];
+ pack_area[3] = box_max_co[1];
+
+ RNA_float_set_array(op->ptr, "pack_area", pack_area);
+ /* Scale always true when box select used to define area */
+ RNA_boolean_set(op->ptr, "scale", true);
+ }
+ /* Re-running operator theough properties panel */
else {
- rctf bounds;
- WM_operator_properties_border_to_rctf(op, &bounds);
- UI_view2d_region_to_view_rctf(®ion->v2d, &bounds, &bounds);
- /* Bounding coordinates for the user-defined area */
- min_co[0] = bounds.xmin;
- min_co[1] = bounds.ymin;
- max_co[0] = bounds.xmax;
- max_co[1] = bounds.ymax;
- RNA_float_set_array(op->ptr, "box_min_co", min_co);
- RNA_float_set_array(op->ptr, "box_max_co", max_co);
+ RNA_float_get_array(op->ptr, "box_min_co", box_min_co);
+ RNA_float_get_array(op->ptr, "box_max_co", box_max_co);
+ if ((box_max_co[0] - box_min_co[0]) <= 0.001f || (box_max_co[1] -
box_min_co[1]) <= 0.001f) {
+ box_min_co[0] = pack_area[0];
+ box_min_co[1] = pack_area[1];
+ box_max_co[0] = pack_area[2];
+ box_max_co[1] = pack_area[3];
+ RNA_float_set_array(op->ptr, "box_min_co", box_min_co);
+ RNA_float_set_array(op->ptr, "box_max_co", box_max_co);
+ RNA_float_set_array(op->ptr, "pack_area", pack_area);
+ /* CANCEL OPERATOR SINCE
@@ Diff output truncated at 10240 characters. @@
_______________________________________________
Bf-blender-cvs mailing list
[email protected]
List details, subscription details or unsubscribe:
https://lists.blender.org/mailman/listinfo/bf-blender-cvs