UV: respect uv selection for smart uv, cube, sphere and cylinder projection

Differential Revision: https://developer.blender.org/D15711
This commit is contained in:
Chris Blackbourn 2022-08-19 13:35:03 +12:00
parent aa82f91c92
commit a5c696a0c2
Notes: blender-bot 2023-02-14 11:34:30 +01:00
Referenced by issue #101414, Regression: Smart UV Project is broken on 3.4
1 changed files with 84 additions and 19 deletions

View File

@ -1714,10 +1714,12 @@ static void uv_map_clip_correct_properties(wmOperatorType *ot)
* such as "Unwrap" & "Smart UV Projections" will need to handle aspect correction themselves.
* For now keep using a single aspect for all faces in this case.
*/
static void uv_map_clip_correct_multi(Object **objects,
uint objects_len,
wmOperator *op,
bool per_face_aspect)
static void uv_map_clip_correct(const Scene *scene,
Object **objects,
uint objects_len,
wmOperator *op,
bool per_face_aspect,
bool only_selected_uvs)
{
BMFace *efa;
BMLoop *l;
@ -1754,6 +1756,10 @@ static void uv_map_clip_correct_multi(Object **objects,
continue;
}
if (only_selected_uvs && !uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) {
continue;
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
minmax_v2v2_v2(min, max, luv->uv);
@ -1767,6 +1773,10 @@ static void uv_map_clip_correct_multi(Object **objects,
continue;
}
if (only_selected_uvs && !uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) {
continue;
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
clamp_v2(luv->uv, 0.0f, 1.0f);
@ -1803,6 +1813,10 @@ static void uv_map_clip_correct_multi(Object **objects,
continue;
}
if (only_selected_uvs && !uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) {
continue;
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
@ -1814,11 +1828,6 @@ static void uv_map_clip_correct_multi(Object **objects,
}
}
static void uv_map_clip_correct(Object *ob, wmOperator *op)
{
uv_map_clip_correct_multi(&ob, 1, op, true);
}
/** \} */
/* -------------------------------------------------------------------- */
@ -2245,6 +2254,12 @@ static int smart_project_exec(bContext *C, wmOperator *op)
/* May be NULL. */
View3D *v3d = CTX_wm_view3d(C);
bool only_selected_uvs = false;
if (CTX_wm_space_image(C)) {
/* Inside the UV Editor, only project selected UVs. */
only_selected_uvs = true;
}
const float project_angle_limit = RNA_float_get(op->ptr, "angle_limit");
const float island_margin = RNA_float_get(op->ptr, "island_margin");
const float area_weight = RNA_float_get(op->ptr, "area_weight");
@ -2283,6 +2298,14 @@ static int smart_project_exec(bContext *C, wmOperator *op)
if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
continue;
}
if (only_selected_uvs) {
if (!uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) {
uvedit_face_select_disable(scene, em->bm, efa, cd_loop_uv_offset);
continue;
}
}
thick_faces[thick_faces_len].area = BM_face_calc_area(efa);
thick_faces[thick_faces_len].efa = efa;
thick_faces_len++;
@ -2397,6 +2420,7 @@ static int smart_project_exec(bContext *C, wmOperator *op)
.rotate = true,
/* We could make this optional. */
.rotate_align_axis = 1,
.only_selected_uvs = true,
.only_selected_faces = true,
.correct_aspect = correct_aspect,
.use_seams = true,
@ -2404,7 +2428,8 @@ static int smart_project_exec(bContext *C, wmOperator *op)
/* #ED_uvedit_pack_islands_multi only supports `per_face_aspect = false`. */
const bool per_face_aspect = false;
uv_map_clip_correct_multi(objects_changed, object_changed_len, op, per_face_aspect);
uv_map_clip_correct(
scene, objects_changed, object_changed_len, op, per_face_aspect, only_selected_uvs);
}
MEM_freeN(objects_changed);
@ -2606,7 +2631,9 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
}
if (changed_multi) {
uv_map_clip_correct_multi(objects, objects_len, op, true);
const bool per_face_aspect = true;
const bool only_selected_uvs = false;
uv_map_clip_correct(scene, objects, objects_len, op, per_face_aspect, only_selected_uvs);
}
MEM_freeN(objects);
@ -2766,6 +2793,12 @@ static int sphere_project_exec(bContext *C, wmOperator *op)
const Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
bool only_selected_uvs = false;
if (CTX_wm_space_image(C)) {
/* Inside the UV Editor, only project selected UVs. */
only_selected_uvs = true;
}
ViewLayer *view_layer = CTX_data_view_layer(C);
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
@ -2798,6 +2831,13 @@ static int sphere_project_exec(bContext *C, wmOperator *op)
continue;
}
if (only_selected_uvs) {
if (!uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) {
uvedit_face_select_disable(scene, em->bm, efa, cd_loop_uv_offset);
continue;
}
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
@ -2807,7 +2847,8 @@ static int sphere_project_exec(bContext *C, wmOperator *op)
uv_map_mirror(em, efa);
}
uv_map_clip_correct(obedit, op);
const bool per_face_aspect = true;
uv_map_clip_correct(scene, &obedit, 1, op, per_face_aspect, only_selected_uvs);
DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
@ -2864,6 +2905,12 @@ static int cylinder_project_exec(bContext *C, wmOperator *op)
const Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
bool only_selected_uvs = false;
if (CTX_wm_space_image(C)) {
/* Inside the UV Editor, only project selected UVs. */
only_selected_uvs = true;
}
ViewLayer *view_layer = CTX_data_view_layer(C);
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
@ -2896,16 +2943,21 @@ static int cylinder_project_exec(bContext *C, wmOperator *op)
continue;
}
if (only_selected_uvs && !uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) {
uvedit_face_select_disable(scene, em->bm, efa, cd_loop_uv_offset);
continue;
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
uv_cylinder_project(luv->uv, l->v->co, center, rotmat);
}
uv_map_mirror(em, efa);
}
uv_map_clip_correct(obedit, op);
const bool per_face_aspect = true;
uv_map_clip_correct(scene, &obedit, 1, op, per_face_aspect, only_selected_uvs);
DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
@ -2939,9 +2991,11 @@ void UV_OT_cylinder_project(wmOperatorType *ot)
/** \name Cube UV Project Operator
* \{ */
static void uvedit_unwrap_cube_project(BMesh *bm,
static void uvedit_unwrap_cube_project(const Scene *scene,
BMesh *bm,
float cube_size,
bool use_select,
const bool use_select,
const bool only_selected_uvs,
const float center[3])
{
BMFace *efa;
@ -2973,6 +3027,10 @@ static void uvedit_unwrap_cube_project(BMesh *bm,
if (use_select && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
continue;
}
if (only_selected_uvs && !uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) {
uvedit_face_select_disable(scene, bm, efa, cd_loop_uv_offset);
continue;
}
axis_dominant_v3(&cox, &coy, efa->no);
@ -2989,6 +3047,12 @@ static int cube_project_exec(bContext *C, wmOperator *op)
const Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
bool only_selected_uvs = false;
if (CTX_wm_space_image(C)) {
/* Inside the UV Editor, only cube project selected UVs. */
only_selected_uvs = true;
}
PropertyRNA *prop_cube_size = RNA_struct_find_property(op->ptr, "cube_size");
const float cube_size_init = RNA_property_float_get(op->ptr, prop_cube_size);
@ -3031,9 +3095,10 @@ static int cube_project_exec(bContext *C, wmOperator *op)
}
}
uvedit_unwrap_cube_project(em->bm, cube_size, true, center);
uvedit_unwrap_cube_project(scene, em->bm, cube_size, true, only_selected_uvs, center);
uv_map_clip_correct(obedit, op);
const bool per_face_aspect = true;
uv_map_clip_correct(scene, &obedit, 1, op, per_face_aspect, only_selected_uvs);
DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
@ -3100,7 +3165,7 @@ void ED_uvedit_add_simple_uvs(Main *bmain, const Scene *scene, Object *ob)
/* select all uv loops first - pack parameters needs this to make sure charts are registered */
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(bm, 2.0, false, NULL);
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);