diff options
Diffstat (limited to 'source/blender/editors/uvedit')
-rw-r--r-- | source/blender/editors/uvedit/uvedit_islands.cc | 290 | ||||
-rw-r--r-- | source/blender/editors/uvedit/uvedit_ops.c | 4 | ||||
-rw-r--r-- | source/blender/editors/uvedit/uvedit_unwrap_ops.c | 158 |
3 files changed, 326 insertions, 126 deletions
diff --git a/source/blender/editors/uvedit/uvedit_islands.cc b/source/blender/editors/uvedit/uvedit_islands.cc index 2648ec5e2f6..92745667505 100644 --- a/source/blender/editors/uvedit/uvedit_islands.cc +++ b/source/blender/editors/uvedit/uvedit_islands.cc @@ -403,6 +403,219 @@ int bm_mesh_calc_uv_islands(const Scene *scene, /** \} */ +static float pack_islands_scale_margin(const blender::Vector<FaceIsland *> &island_vector, + BoxPack *box_array, + const float scale, + const float margin) +{ + for (const int index : island_vector.index_range()) { + FaceIsland *island = island_vector[index]; + BoxPack *box = &box_array[index]; + box->index = index; + box->w = BLI_rctf_size_x(&island->bounds_rect) * scale + 2 * margin; + box->h = BLI_rctf_size_y(&island->bounds_rect) * scale + 2 * margin; + } + float max_u, max_v; + BLI_box_pack_2d(box_array, island_vector.size(), &max_u, &max_v); + return max_ff(max_u, max_v); +} + +static float pack_islands_margin_fraction(const blender::Vector<FaceIsland *> &island_vector, + BoxPack *box_array, + const float margin_fraction) +{ + /* + * Root finding using a combined search / modified-secant method. + * First, use a robust search procedure to bracket the root within a factor of 10. + * Then, use a modified-secant method to converge. + * + * This is a specialized solver using domain knowledge to accelerate convergence. + */ + + float scale_low = 0.0f; + float value_low = 0.0f; + float scale_high = 0.0f; + float value_high = 0.0f; + float scale_last = 0.0f; + + /* Scaling smaller than `min_scale_roundoff` is unlikely to fit and + * will destroy information in existing UVs. */ + float min_scale_roundoff = 1e-5f; + + /* Certain inputs might have poor convergence properties. + * Use `max_iteration` to prevent an infinite loop. */ + int max_iteration = 25; + for (int iteration = 0; iteration < max_iteration; iteration++) { + float scale = 1.0f; + + if (iteration == 0) { + BLI_assert(iteration == 0); + BLI_assert(scale == 1.0f); + BLI_assert(scale_low == 0.0f); + BLI_assert(scale_high == 0.0f); + } + else if (scale_low == 0.0f) { + BLI_assert(scale_high > 0.0f); + /* Search mode, shrink layout until we can find a scale that fits. */ + scale = scale_high * 0.1f; + } + else if (scale_high == 0.0f) { + BLI_assert(scale_low > 0.0f); + /* Search mode, grow layout until we can find a scale that doesn't fit. */ + scale = scale_low * 10.0f; + } + else { + /* Bracket mode, use modified secant method to find root. */ + BLI_assert(scale_low > 0.0f); + BLI_assert(scale_high > 0.0f); + BLI_assert(value_low <= 0.0f); + BLI_assert(value_high >= 0.0f); + if (scale_high < scale_low * 1.0001f) { + /* Convergence. */ + break; + } + + /* Secant method for area. */ + scale = (sqrtf(scale_low) * value_high - sqrtf(scale_high) * value_low) / + (value_high - value_low); + scale = scale * scale; + + if (iteration & 1) { + /* Modified binary-search to improve robustness. */ + scale = sqrtf(scale * sqrtf(scale_low * scale_high)); + } + } + + scale = max_ff(scale, min_scale_roundoff); + + /* Evaluate our `f`. */ + scale_last = scale; + float max_uv = pack_islands_scale_margin( + island_vector, box_array, scale_last, margin_fraction); + float value = sqrtf(max_uv) - 1.0f; + + if (value <= 0.0f) { + scale_low = scale; + value_low = value; + } + else { + scale_high = scale; + value_high = value; + if (scale == min_scale_roundoff) { + /* Unable to pack without damaging UVs. */ + scale_low = scale; + break; + } + } + } + + const bool flush = true; + if (flush) { + /* Write back best pack as a side-effect. First get best pack. */ + if (scale_last != scale_low) { + scale_last = scale_low; + float max_uv = pack_islands_scale_margin( + island_vector, box_array, scale_last, margin_fraction); + UNUSED_VARS(max_uv); + /* TODO (?): `if (max_uv < 1.0f) { scale_last /= max_uv; }` */ + } + + /* Then expand FaceIslands by the correct amount. */ + for (const int index : island_vector.index_range()) { + BoxPack *box = &box_array[index]; + box->x /= scale_last; + box->y /= scale_last; + FaceIsland *island = island_vector[index]; + BLI_rctf_pad( + &island->bounds_rect, margin_fraction / scale_last, margin_fraction / scale_last); + } + } + return scale_last; +} + +static float calc_margin_from_aabb_length_sum(const blender::Vector<FaceIsland *> &island_vector, + const struct UVPackIsland_Params ¶ms) +{ + /* Logic matches behavior from #GEO_uv_parametrizer_pack. + * Attempt to give predictable results + * not dependent on current UV scale by using + * `aabb_length_sum` (was "`area`") to multiply + * the margin by the length (was "area"). + */ + double aabb_length_sum = 0.0f; + for (FaceIsland *island : island_vector) { + float w = BLI_rctf_size_x(&island->bounds_rect); + float h = BLI_rctf_size_y(&island->bounds_rect); + aabb_length_sum += sqrtf(w * h); + } + return params.margin * aabb_length_sum * 0.1f; +} + +static BoxPack *pack_islands_params(const blender::Vector<FaceIsland *> &island_vector, + const struct UVPackIsland_Params ¶ms, + float r_scale[2]) +{ + BoxPack *box_array = static_cast<BoxPack *>( + MEM_mallocN(sizeof(*box_array) * island_vector.size(), __func__)); + + if (params.margin == 0.0f) { + /* Special case for zero margin. Margin_method is ignored as all formulas give same result. */ + const float max_uv = pack_islands_scale_margin(island_vector, box_array, 1.0f, 0.0f); + r_scale[0] = 1.0f / max_uv; + r_scale[1] = r_scale[0]; + return box_array; + } + + if (params.margin_method == ED_UVPACK_MARGIN_FRACTION) { + /* Uses a line search on scale. ~10x slower than other method. */ + const float scale = pack_islands_margin_fraction(island_vector, box_array, params.margin); + r_scale[0] = scale; + r_scale[1] = scale; + /* pack_islands_margin_fraction will pad FaceIslands, return early. */ + return box_array; + } + + float margin = params.margin; + switch (params.margin_method) { + case ED_UVPACK_MARGIN_ADD: /* Default for Blender 2.8 and earlier. */ + break; /* Nothing to do. */ + case ED_UVPACK_MARGIN_SCALED: /* Default for Blender 3.3 and later. */ + margin = calc_margin_from_aabb_length_sum(island_vector, params); + break; + case ED_UVPACK_MARGIN_FRACTION: /* Added as an option in Blender 3.4. */ + BLI_assert_unreachable(); /* Handled above. */ + break; + default: + BLI_assert_unreachable(); + } + + const float max_uv = pack_islands_scale_margin(island_vector, box_array, 1.0f, margin); + r_scale[0] = 1.0f / max_uv; + r_scale[1] = r_scale[0]; + + for (int index = 0; index < island_vector.size(); index++) { + FaceIsland *island = island_vector[index]; + BLI_rctf_pad(&island->bounds_rect, margin, margin); + } + return box_array; +} + +static bool island_has_pins(FaceIsland *island) +{ + BMLoop *l; + BMIter iter; + const int cd_loop_uv_offset = island->cd_loop_uv_offset; + for (int i = 0; i < island->faces_len; i++) { + BM_ITER_ELEM (l, &iter, island->faces[i], BM_LOOPS_OF_FACE) { + MLoopUV *luv = static_cast<MLoopUV *>(BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset)); + if (luv->flag & MLOOPUV_PINNED) { + return true; + } + } + } + return false; +} + /* -------------------------------------------------------------------- */ /** \name Public UV Island Packing * @@ -412,6 +625,7 @@ int bm_mesh_calc_uv_islands(const Scene *scene, void ED_uvedit_pack_islands_multi(const Scene *scene, Object **objects, const uint objects_len, + BMesh **bmesh_override, const struct UVMapUDIM_Params *udim_params, const struct UVPackIsland_Params *params) { @@ -419,9 +633,17 @@ void ED_uvedit_pack_islands_multi(const Scene *scene, for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + BMesh *bm = nullptr; + if (bmesh_override) { + /* Note: obedit is still required for aspect ratio and ID_RECALC_GEOMETRY. */ + bm = bmesh_override[ob_index]; + } + else { + BMEditMesh *em = BKE_editmesh_from_object(obedit); + bm = em->bm; + } + BLI_assert(bm); + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); if (cd_loop_uv_offset == -1) { continue; } @@ -437,7 +659,7 @@ void ED_uvedit_pack_islands_multi(const Scene *scene, ListBase island_list = {nullptr}; bm_mesh_calc_uv_islands(scene, - em->bm, + bm, &island_list, params->only_selected_faces, params->only_selected_uvs, @@ -445,8 +667,14 @@ void ED_uvedit_pack_islands_multi(const Scene *scene, aspect_y, cd_loop_uv_offset); - int index; - LISTBASE_FOREACH_INDEX (struct FaceIsland *, island, &island_list, index) { + /* Remove from linked list and append to blender::Vector. */ + LISTBASE_FOREACH_MUTABLE (struct FaceIsland *, island, &island_list) { + BLI_remlink(&island_list, island); + if (params->ignore_pinned && island_has_pins(island)) { + MEM_freeN(island->faces); + MEM_freeN(island); + continue; + } island_vector.append(island); } } @@ -455,19 +683,12 @@ void ED_uvedit_pack_islands_multi(const Scene *scene, return; } - float margin = scene->toolsettings->uvcalc_margin; - double area = 0.0f; - - BoxPack *boxarray = static_cast<BoxPack *>( - MEM_mallocN(sizeof(*boxarray) * island_vector.size(), __func__)); - /* Coordinates of bounding box containing all selected UVs. */ float selection_min_co[2], selection_max_co[2]; INIT_MINMAX2(selection_min_co, selection_max_co); for (int index = 0; index < island_vector.size(); index++) { FaceIsland *island = island_vector[index]; - /* Skip calculation if using specified UDIM option. */ if (udim_params && (udim_params->use_target_udim == false)) { float bounds_min[2], bounds_max[2]; @@ -489,17 +710,6 @@ void ED_uvedit_pack_islands_multi(const Scene *scene, bm_face_array_calc_bounds( island->faces, island->faces_len, island->cd_loop_uv_offset, &island->bounds_rect); - - BoxPack *box = &boxarray[index]; - box->index = index; - box->x = 0.0f; - box->y = 0.0f; - box->w = BLI_rctf_size_x(&island->bounds_rect); - box->h = BLI_rctf_size_y(&island->bounds_rect); - - if (margin > 0.0f) { - area += double(sqrtf(box->w * box->h)); - } } /* Center of bounding box containing all selected UVs. */ @@ -509,28 +719,8 @@ void ED_uvedit_pack_islands_multi(const Scene *scene, selection_center[1] = (selection_min_co[1] + selection_max_co[1]) / 2.0f; } - if (margin > 0.0f) { - /* Logic matches behavior from #GEO_uv_parametrizer_pack, - * use area so multiply the margin by the area to give - * predictable results not dependent on UV scale. */ - margin = (margin * float(area)) * 0.1f; - for (int i = 0; i < island_vector.size(); i++) { - FaceIsland *island = island_vector[i]; - BoxPack *box = &boxarray[i]; - - BLI_rctf_pad(&island->bounds_rect, margin, margin); - box->w = BLI_rctf_size_x(&island->bounds_rect); - box->h = BLI_rctf_size_y(&island->bounds_rect); - } - } - - float boxarray_size[2]; - BLI_box_pack_2d(boxarray, island_vector.size(), &boxarray_size[0], &boxarray_size[1]); - - /* Don't change the aspect when scaling. */ - boxarray_size[0] = boxarray_size[1] = max_ff(boxarray_size[0], boxarray_size[1]); - - const float scale[2] = {1.0f / boxarray_size[0], 1.0f / boxarray_size[1]}; + float scale[2] = {1.0f, 1.0f}; + BoxPack *box_array = pack_islands_params(island_vector, *params, scale); /* Tile offset. */ float base_offset[2] = {0.0f, 0.0f}; @@ -580,14 +770,14 @@ void ED_uvedit_pack_islands_multi(const Scene *scene, } for (int i = 0; i < island_vector.size(); i++) { - FaceIsland *island = island_vector[boxarray[i].index]; + FaceIsland *island = island_vector[box_array[i].index]; const float pivot[2] = { island->bounds_rect.xmin, 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], + ((box_array[i].x * scale[0]) - island->bounds_rect.xmin) + base_offset[0], + ((box_array[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]; @@ -607,7 +797,7 @@ void ED_uvedit_pack_islands_multi(const Scene *scene, MEM_freeN(island); } - MEM_freeN(boxarray); + MEM_freeN(box_array); } /** \} */ diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 5e2d9097abd..b65f4889347 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -37,6 +37,7 @@ #include "BKE_node.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "ED_image.h" #include "ED_mesh.h" @@ -113,7 +114,8 @@ bool ED_object_get_active_image(Object *ob, bNode **r_node, bNodeTree **r_ntree) { - Material *ma = BKE_object_material_get(ob, mat_nr); + Material *ma = DEG_is_evaluated_object(ob) ? BKE_object_material_get_eval(ob, mat_nr) : + BKE_object_material_get(ob, mat_nr); bNodeTree *ntree = (ma && ma->use_nodes) ? ma->nodetree : NULL; bNode *node = (ntree) ? nodeGetActiveTexture(ntree) : NULL; diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index 661a2a1b05b..ecaba3234a7 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -1050,50 +1050,6 @@ void UV_OT_minimize_stretch(wmOperatorType *ot) /** \name Pack UV Islands Operator * \{ */ -static void uvedit_pack_islands(const Scene *scene, Object *ob, BMesh *bm) -{ - const UnwrapOptions options = { - .topology_from_uvs = true, - .only_selected_faces = false, - .only_selected_uvs = true, - .fill_holes = false, - .correct_aspect = false, - }; - - bool rotate = true; - bool ignore_pinned = false; - - ParamHandle *handle = construct_param_handle(scene, ob, bm, &options, NULL); - GEO_uv_parametrizer_pack(handle, scene->toolsettings->uvcalc_margin, rotate, ignore_pinned); - GEO_uv_parametrizer_flush(handle); - GEO_uv_parametrizer_delete(handle); -} - -/** - * \warning Since this uses #ParamHandle it doesn't work with non-manifold meshes (see T82637). - * Use #ED_uvedit_pack_islands_multi for a more general solution. - * - * TODO: remove this function, in favor of #ED_uvedit_pack_islands_multi. - */ -static void uvedit_pack_islands_multi(const Scene *scene, - Object **objects, - const uint objects_len, - const UnwrapOptions *options, - bool rotate, - bool ignore_pinned) -{ - ParamHandle *handle = construct_param_handle_multi(scene, objects, objects_len, options); - GEO_uv_parametrizer_pack(handle, scene->toolsettings->uvcalc_margin, rotate, ignore_pinned); - GEO_uv_parametrizer_flush(handle); - GEO_uv_parametrizer_delete(handle); - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY); - WM_main_add_notifier(NC_GEOM | ND_DATA, obedit->data); - } -} - /* Packing targets. */ enum { PACK_UDIM_SRC_CLOSEST = 0, @@ -1125,7 +1081,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"); if (RNA_struct_property_is_set(op->ptr, "margin")) { scene->toolsettings->uvcalc_margin = RNA_float_get(op->ptr, "margin"); @@ -1139,21 +1094,42 @@ static int pack_islands_exec(bContext *C, wmOperator *op) const bool use_udim_params = ED_uvedit_udim_params_from_image_space( sima, use_active, &udim_params); + const struct UVPackIsland_Params pack_island_params = { + .rotate = RNA_boolean_get(op->ptr, "rotate"), + .only_selected_uvs = options.only_selected_uvs, + .only_selected_faces = options.only_selected_faces, + .use_seams = !options.topology_from_uvs || options.topology_from_uvs_use_seams, + .correct_aspect = options.correct_aspect, + .ignore_pinned = false, + .margin_method = RNA_enum_get(op->ptr, "margin_method"), + .margin = RNA_float_get(op->ptr, "margin"), + }; ED_uvedit_pack_islands_multi(scene, objects, objects_len, + NULL, use_udim_params ? &udim_params : NULL, - &(struct UVPackIsland_Params){ - .rotate = rotate, - .only_selected_uvs = true, - .only_selected_faces = true, - .correct_aspect = true, - }); + &pack_island_params); MEM_freeN(objects); return OPERATOR_FINISHED; } +const EnumPropertyItem pack_margin_method[] = { + {ED_UVPACK_MARGIN_SCALED, + "SCALED", + 0, + "Scaled", + "Use scale of existing UVs to multiply margin"}, + {ED_UVPACK_MARGIN_ADD, "ADD", 0, "Add", "Just add the margin, ignoring any UV scale"}, + {ED_UVPACK_MARGIN_FRACTION, + "FRACTION", + 0, + "Fraction", + "Specify a precise fraction of final UV output"}, + {0, NULL, 0, NULL, NULL}, +}; + void UV_OT_pack_islands(wmOperatorType *ot) { static const EnumPropertyItem pack_target[] = { @@ -1180,6 +1156,8 @@ void UV_OT_pack_islands(wmOperatorType *ot) /* properties */ RNA_def_enum(ot->srna, "udim_source", pack_target, PACK_UDIM_SRC_CLOSEST, "Pack to", ""); RNA_def_boolean(ot->srna, "rotate", true, "Rotate", "Rotate islands for best fit"); + RNA_def_enum( + ot->srna, "margin_method", pack_margin_method, ED_UVPACK_MARGIN_SCALED, "Margin Method", ""); RNA_def_float_factor( ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f); } @@ -1892,12 +1870,19 @@ void ED_uvedit_live_unwrap(const Scene *scene, Object **objects, int objects_len .fill_holes = (scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES) != 0, .correct_aspect = (scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT) == 0, }; - - bool rotate = true; - bool ignore_pinned = true; - uvedit_unwrap_multi(scene, objects, objects_len, &options, NULL); - uvedit_pack_islands_multi(scene, objects, objects_len, &options, rotate, ignore_pinned); + + const struct UVPackIsland_Params pack_island_params = { + .rotate = true, + .only_selected_uvs = options.only_selected_uvs, + .only_selected_faces = options.only_selected_faces, + .use_seams = !options.topology_from_uvs || options.topology_from_uvs_use_seams, + .correct_aspect = options.correct_aspect, + .ignore_pinned = true, + .margin_method = ED_UVPACK_MARGIN_SCALED, + .margin = scene->toolsettings->uvcalc_margin, + }; + ED_uvedit_pack_islands_multi(scene, objects, objects_len, NULL, NULL, &pack_island_params); } } @@ -1929,8 +1914,6 @@ static int unwrap_exec(bContext *C, wmOperator *op) .correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect"), }; - bool rotate = true; - bool ignore_pinned = true; if (CTX_wm_space_image(C)) { /* Inside the UV Editor, only unwrap selected UVs. */ options.only_selected_uvs = true; @@ -2035,7 +2018,18 @@ static int unwrap_exec(bContext *C, wmOperator *op) .count_failed = 0, }; uvedit_unwrap_multi(scene, objects, objects_len, &options, &result_info); - uvedit_pack_islands_multi(scene, objects, objects_len, &options, rotate, ignore_pinned); + + const struct UVPackIsland_Params pack_island_params = { + .rotate = true, + .only_selected_uvs = options.only_selected_uvs, + .only_selected_faces = options.only_selected_faces, + .use_seams = !options.topology_from_uvs || options.topology_from_uvs_use_seams, + .correct_aspect = options.correct_aspect, + .ignore_pinned = true, + .margin_method = RNA_enum_get(op->ptr, "margin_method"), + .margin = RNA_float_get(op->ptr, "margin"), + }; + ED_uvedit_pack_islands_multi(scene, objects, objects_len, NULL, NULL, &pack_island_params); MEM_freeN(objects); @@ -2098,6 +2092,8 @@ void UV_OT_unwrap(wmOperatorType *ot) 0, "Use Subdivision Surface", "Map UVs taking vertex position after Subdivision Surface modifier has been applied"); + RNA_def_enum( + ot->srna, "margin_method", pack_margin_method, ED_UVPACK_MARGIN_SCALED, "Margin Method", ""); RNA_def_float_factor( ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f); } @@ -2118,7 +2114,6 @@ typedef struct ThickFace { static int smart_uv_project_thickface_area_cmp_fn(const void *tf_a_p, const void *tf_b_p) { - const ThickFace *tf_a = (ThickFace *)tf_a_p; const ThickFace *tf_b = (ThickFace *)tf_b_p; @@ -2412,17 +2407,17 @@ 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, - objects_changed, - object_changed_len, - NULL, - &(struct UVPackIsland_Params){ - .rotate = true, - .only_selected_uvs = only_selected_uvs, - .only_selected_faces = true, - .correct_aspect = correct_aspect, - .use_seams = true, - }); + + const struct UVPackIsland_Params params = { + .rotate = true, + .only_selected_uvs = only_selected_uvs, + .only_selected_faces = true, + .correct_aspect = correct_aspect, + .use_seams = true, + .margin_method = RNA_enum_get(op->ptr, "margin_method"), + .margin = RNA_float_get(op->ptr, "island_margin"), + }; + ED_uvedit_pack_islands_multi(scene, objects_changed, object_changed_len, NULL, NULL, ¶ms); /* #ED_uvedit_pack_islands_multi only supports `per_face_aspect = false`. */ const bool per_face_aspect = false; @@ -2464,6 +2459,8 @@ void UV_OT_smart_project(wmOperatorType *ot) DEG2RADF(89.0f)); RNA_def_property_float_default(prop, DEG2RADF(66.0f)); + RNA_def_enum( + ot->srna, "margin_method", pack_margin_method, ED_UVPACK_MARGIN_SCALED, "Margin Method", ""); RNA_def_float(ot->srna, "island_margin", 0.0f, @@ -3161,13 +3158,24 @@ void ED_uvedit_add_simple_uvs(Main *bmain, const Scene *scene, Object *ob) .calc_face_normal = true, .calc_vert_normal = true, })); - /* select all uv loops first - pack parameters needs this to make sure charts are registered */ + /* Select all UVs for cube_project. */ ED_uvedit_select_all(bm); /* A cube size of 2.0 maps [-1..1] vertex coords to [0.0..1.0] in UV coords. */ uvedit_unwrap_cube_project(scene, bm, 2.0, false, false, NULL); - /* Set the margin really quickly before the packing operation. */ - scene->toolsettings->uvcalc_margin = 0.001f; - uvedit_pack_islands(scene, ob, bm); + + /* Pack UVs. */ + const struct UVPackIsland_Params params = { + .rotate = true, + .only_selected_uvs = false, + .only_selected_faces = false, + .correct_aspect = false, + .use_seams = true, + .margin_method = ED_UVPACK_MARGIN_SCALED, + .margin = 0.001f, + }; + ED_uvedit_pack_islands_multi(scene, &ob, 1, &bm, NULL, ¶ms); + + /* Write back from BMesh to Mesh. */ BM_mesh_bm_to_me(bmain, bm, me, (&(struct BMeshToMeshParams){0})); BM_mesh_free(bm); |