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. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs