diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h index 516239a7176..f3aba12a924 100644 --- a/source/blender/editors/include/ED_uvedit.h +++ b/source/blender/editors/include/ED_uvedit.h @@ -237,6 +237,18 @@ void ED_image_draw_cursor(struct ARegion *region, const float cursor[2]); void ED_uvedit_buttons_register(struct ARegionType *art); /* uvedit_islands.c */ + +struct UVMapUDIM_Params { + const struct Image *image; + /** Copied from #SpaceImage.tile_grid_shape */ + int grid_shape[2]; + bool use_target_udim; + int target_udim; +}; +bool ED_uvedit_udim_params_from_image_space(const struct SpaceImage *sima, + bool use_active, + struct UVMapUDIM_Params *udim_params); + struct UVPackIsland_Params { uint rotate : 1; /** -1 not to align to axis, otherwise 0,1 for X,Y. */ @@ -247,13 +259,13 @@ struct UVPackIsland_Params { uint correct_aspect : 1; }; -bool uv_coords_isect_udim(const struct Image *image, const int udim_grid[2], float coords[2]); +bool uv_coords_isect_udim(const struct Image *image, + const int udim_grid[2], + const float coords[2]); void ED_uvedit_pack_islands_multi(const struct Scene *scene, - const struct SpaceImage *sima, Object **objects, const uint objects_len, - const bool use_target_udim, - int target_udim, + const struct UVMapUDIM_Params *udim_params, 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 62173f4eaff..6159758dbcd 100644 --- a/source/blender/editors/uvedit/uvedit_islands.c +++ b/source/blender/editors/uvedit/uvedit_islands.c @@ -237,8 +237,10 @@ static void bm_face_array_uv_scale_y(BMFace **faces, /** \name UDIM packing helper functions * \{ */ -/* Returns true if UV coordinates lie on a valid tile in UDIM grid or tiled image. */ -bool uv_coords_isect_udim(const Image *image, const int udim_grid[2], float coords[2]) +/** + * Returns true if UV coordinates lie on a valid tile in UDIM grid or tiled image. + */ +bool uv_coords_isect_udim(const Image *image, const int udim_grid[2], const float coords[2]) { const float coords_floor[2] = {floorf(coords[0]), floorf(coords[1])}; const bool is_tiled_image = image && (image->source == IMA_SRC_TILED); @@ -452,11 +454,9 @@ static int bm_mesh_calc_uv_islands(const Scene *scene, * \{ */ void ED_uvedit_pack_islands_multi(const Scene *scene, - const SpaceImage *sima, Object **objects, const uint objects_len, - const bool use_target_udim, - int target_udim, + const struct UVMapUDIM_Params *udim_params, const struct UVPackIsland_Params *params) { /* Align to the Y axis, could make this configurable. */ @@ -512,7 +512,7 @@ void ED_uvedit_pack_islands_multi(const Scene *scene, LISTBASE_FOREACH_INDEX (struct FaceIsland *, island, &island_list, index) { /* Skip calculation if using specified UDIM option. */ - if (!use_target_udim) { + if (udim_params && (udim_params->use_target_udim == false)) { float bounds_min[2], bounds_max[2]; INIT_MINMAX2(bounds_min, bounds_max); for (int i = 0; i < island->faces_len; i++) { @@ -525,6 +525,7 @@ void ED_uvedit_pack_islands_multi(const Scene *scene, selection_max_co[0] = MAX2(bounds_max[0], selection_max_co[0]); selection_max_co[1] = MAX2(bounds_max[1], selection_max_co[1]); } + if (params->rotate) { if (island->aspect_y != 1.0f) { bm_face_array_uv_scale_y( @@ -559,7 +560,7 @@ void ED_uvedit_pack_islands_multi(const Scene *scene, /* Center of bounding box containing all selected UVs. */ float selection_center[2]; - if (!use_target_udim) { + if (udim_params && (udim_params->use_target_udim == false)) { selection_center[0] = (selection_min_co[0] + selection_max_co[0]) / 2.0f; selection_center[1] = (selection_min_co[1] + selection_max_co[1]) / 2.0f; } @@ -590,24 +591,22 @@ void ED_uvedit_pack_islands_multi(const Scene *scene, /* Tile offset. */ float base_offset[2] = {0.0f, 0.0f}; + /* CASE: ignore UDIM. */ + if (udim_params == NULL) { + /* pass */ + } /* CASE: Active/specified(smart uv project) UDIM. */ - if (use_target_udim) { + else if (udim_params->use_target_udim) { + /* Calculate offset based on specified_tile_index. */ - base_offset[0] = (target_udim - 1001) % 10; - base_offset[1] = (target_udim - 1001) / 10; + base_offset[0] = (udim_params->target_udim - 1001) % 10; + base_offset[1] = (udim_params->target_udim - 1001) / 10; } /* CASE: Closest UDIM. */ else { - const Image *image; - int udim_grid[2] = {1, 1}; - /* To handle cases where `sima == NULL` - Smart UV project in 3D viewport. */ - if (sima != NULL) { - image = sima->image; - udim_grid[0] = sima->tile_grid_shape[0]; - udim_grid[1] = sima->tile_grid_shape[1]; - } - + const Image *image = udim_params->image; + const int *udim_grid = udim_params->grid_shape; /* Check if selection lies on a valid UDIM grid tile. */ bool is_valid_udim = uv_coords_isect_udim(image, udim_grid, selection_center); if (is_valid_udim) { @@ -643,8 +642,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 + base_offset[0], - (boxarray[i].y * scale[1]) - island->bounds_rect.ymin + base_offset[1], + ((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 4e183732db9..38233b55d15 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -144,6 +144,61 @@ static bool ED_uvedit_ensure_uvs(Object *obedit) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name UDIM Access + * \{ */ + +bool ED_uvedit_udim_params_from_image_space(const SpaceImage *sima, + bool use_active, + struct UVMapUDIM_Params *udim_params) +{ + memset(udim_params, 0, sizeof(*udim_params)); + + udim_params->grid_shape[0] = 1; + udim_params->grid_shape[1] = 1; + udim_params->target_udim = 0; + udim_params->use_target_udim = false; + + if (sima == NULL) { + return false; + } + + udim_params->image = sima->image; + udim_params->grid_shape[0] = sima->tile_grid_shape[0]; + udim_params->grid_shape[1] = sima->tile_grid_shape[1]; + + if (use_active) { + int active_udim = 1001; + /* NOTE: Presently, when UDIM grid and tiled image are present together, only active tile for + * the tiled image is considered. */ + Image *image = sima->image; + if (image && image->source == IMA_SRC_TILED) { + ImageTile *active_tile = BLI_findlink(&image->tiles, image->active_tile_index); + if (active_tile) { + active_udim = active_tile->tile_number; + } + } + else { + /* TODO: Support storing an active UDIM when there are no tiles present. + * Until then, use 2D cursor to find the active tile index for the UDIM grid. */ + const float cursor_loc[2] = {sima->cursor[0], sima->cursor[1]}; + if (uv_coords_isect_udim(sima->image, sima->tile_grid_shape, cursor_loc)) { + int tile_number = 1001; + tile_number += floorf(cursor_loc[1]) * 10; + tile_number += floorf(cursor_loc[0]); + active_udim = tile_number; + } + } + + udim_params->target_udim = active_udim; + udim_params->use_target_udim = true; + } + + return true; +} + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Parametrizer Conversion * \{ */ @@ -1040,7 +1095,6 @@ static int pack_islands_exec(bContext *C, wmOperator *op) /* RNA props */ const bool rotate = RNA_boolean_get(op->ptr, "rotate"); const int udim_source = RNA_enum_get(op->ptr, "udim_source"); - bool use_target_udim = false; if (RNA_struct_property_is_set(op->ptr, "margin")) { scene->toolsettings->uvcalc_margin = RNA_float_get(op->ptr, "margin"); } @@ -1048,46 +1102,15 @@ static int pack_islands_exec(bContext *C, wmOperator *op) RNA_float_set(op->ptr, "margin", scene->toolsettings->uvcalc_margin); } - int target_udim = 1001; - if (udim_source == PACK_UDIM_SRC_CLOSEST) { - /* pass */ - } - else if (udim_source == PACK_UDIM_SRC_ACTIVE) { - int active_udim = 1001; - /* NOTE: Presently, when UDIM grid and tiled image are present together, only active tile for - * the tiled imgae is considered. */ - if (sima && sima->image) { - Image *image = sima->image; - ImageTile *active_tile = BLI_findlink(&image->tiles, image->active_tile_index); - if (active_tile) { - active_udim = active_tile->tile_number; - } - } - else if (sima && !sima->image) { - /* Use 2D cursor to find the active tile index for the UDIM grid. */ - float cursor_loc[2] = {sima->cursor[0], sima->cursor[1]}; - if (uv_coords_isect_udim(sima->image, sima->tile_grid_shape, cursor_loc)) { - int tile_number = 1001; - tile_number += floorf(cursor_loc[1]) * 10; - tile_number += floorf(cursor_loc[0]); - active_udim = tile_number; - } - /* TODO: Support storing an active UDIM when there are no tiles present. */ - } - - target_udim = active_udim; - use_target_udim = true; - } - else { - BLI_assert_unreachable(); - } + struct UVMapUDIM_Params udim_params; + const bool use_active = (udim_source == PACK_UDIM_SRC_ACTIVE); + const bool use_udim_params = ED_uvedit_udim_params_from_image_space( + sima, use_active, &udim_params); ED_uvedit_pack_islands_multi(scene, - sima, objects, objects_len, - use_target_udim, - target_udim, + use_udim_params ? &udim_params : NULL, &(struct UVPackIsland_Params){ .rotate = rotate, .rotate_align_axis = -1, @@ -2114,7 +2137,6 @@ static int smart_project_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - const SpaceImage *sima = CTX_wm_space_image(C); /* May be NULL. */ View3D *v3d = CTX_wm_view3d(C); @@ -2125,7 +2147,6 @@ static int smart_project_exec(bContext *C, wmOperator *op) const float project_angle_limit_cos = cosf(project_angle_limit); const float project_angle_limit_half_cos = cosf(project_angle_limit / 2); - const int target_udim = 1001; /* 0-1 UV space. */ /* Memory arena for list links (cleared for each object). */ MemArena *arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); @@ -2265,11 +2286,9 @@ static int smart_project_exec(bContext *C, wmOperator *op) /* Depsgraph refresh functions are called here. */ const bool correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect"); ED_uvedit_pack_islands_multi(scene, - sima, objects_changed, object_changed_len, - true, - target_udim, + NULL, &(struct UVPackIsland_Params){ .rotate = true, /* We could make this optional. */