Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/uvedit/uvedit_unwrap_ops.c
| Show First 20 Lines • Show All 992 Lines • ▼ Show 20 Lines | |||||
| /** | /** | ||||
| * \param per_face_aspect: Calculate the aspect ratio per-face, | * \param per_face_aspect: Calculate the aspect ratio per-face, | ||||
| * otherwise use a single aspect for all UV's based on the material of the active face. | * otherwise use a single aspect for all UV's based on the material of the active face. | ||||
| * TODO: using per-face aspect may split UV islands so more advanced UV projection methods | * TODO: using per-face aspect may split UV islands so more advanced UV projection methods | ||||
| * such as "Unwrap" & "Smart UV Projections" will need to handle aspect correction themselves. | * 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. | * For now keep using a single aspect for all faces in this case. | ||||
| */ | */ | ||||
| static void uv_map_clip_correct_multi(Object **objects, | static void uv_map_clip_correct(const Scene *scene, | ||||
| uint objects_len, | Object **objects, | ||||
| wmOperator *op, | uint objects_len, | ||||
| bool per_face_aspect) | wmOperator *op, | ||||
| bool per_face_aspect, | |||||
| bool only_selected_uvs) | |||||
| { | { | ||||
| BMFace *efa; | BMFace *efa; | ||||
| BMLoop *l; | BMLoop *l; | ||||
| BMIter iter, liter; | BMIter iter, liter; | ||||
| MLoopUV *luv; | MLoopUV *luv; | ||||
| float dx, dy, min[2], max[2]; | float dx, dy, min[2], max[2]; | ||||
| const bool correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect"); | const bool correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect"); | ||||
| const bool clip_to_bounds = (RNA_struct_find_property(op->ptr, "clip_to_bounds") && | const bool clip_to_bounds = (RNA_struct_find_property(op->ptr, "clip_to_bounds") && | ||||
| Show All 20 Lines | |||||
| if (scale_to_bounds) { | if (scale_to_bounds) { | ||||
| /* find uv limits */ | /* find uv limits */ | ||||
| BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | ||||
| if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | ||||
| continue; | 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) { | BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | ||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | ||||
| minmax_v2v2_v2(min, max, luv->uv); | minmax_v2v2_v2(min, max, luv->uv); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else if (clip_to_bounds) { | else if (clip_to_bounds) { | ||||
| /* clipping and wrapping */ | /* clipping and wrapping */ | ||||
| BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | ||||
| if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | ||||
| continue; | 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) { | BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | ||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | ||||
| clamp_v2(luv->uv, 0.0f, 1.0f); | clamp_v2(luv->uv, 0.0f, 1.0f); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| Show All 20 Lines | |||||
| BMEditMesh *em = BKE_editmesh_from_object(ob); | BMEditMesh *em = BKE_editmesh_from_object(ob); | ||||
| const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); | const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); | ||||
| BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | ||||
| if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | ||||
| continue; | 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) { | BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | ||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | ||||
| luv->uv[0] = (luv->uv[0] - min[0]) * dx; | luv->uv[0] = (luv->uv[0] - min[0]) * dx; | ||||
| luv->uv[1] = (luv->uv[1] - min[1]) * dy; | luv->uv[1] = (luv->uv[1] - min[1]) * dy; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void uv_map_clip_correct(Object *ob, wmOperator *op) | |||||
| { | |||||
| uv_map_clip_correct_multi(&ob, 1, op, true); | |||||
| } | |||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name UV Unwrap Operator | /** \name UV Unwrap Operator | ||||
| * \{ */ | * \{ */ | ||||
| /* Assumes UV Map exists, doesn't run update funcs. */ | /* Assumes UV Map exists, doesn't run update funcs. */ | ||||
| static void uvedit_unwrap(const Scene *scene, | static void uvedit_unwrap(const Scene *scene, | ||||
| ▲ Show 20 Lines • Show All 410 Lines • ▼ Show 20 Lines | |||||
| static int smart_project_exec(bContext *C, wmOperator *op) | static int smart_project_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| Scene *scene = CTX_data_scene(C); | Scene *scene = CTX_data_scene(C); | ||||
| ViewLayer *view_layer = CTX_data_view_layer(C); | ViewLayer *view_layer = CTX_data_view_layer(C); | ||||
| /* May be NULL. */ | /* May be NULL. */ | ||||
| View3D *v3d = CTX_wm_view3d(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; | |||||
| } | |||||
| const float project_angle_limit = RNA_float_get(op->ptr, "angle_limit"); | 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 island_margin = RNA_float_get(op->ptr, "island_margin"); | ||||
| const float area_weight = RNA_float_get(op->ptr, "area_weight"); | const float area_weight = RNA_float_get(op->ptr, "area_weight"); | ||||
| const float project_angle_limit_cos = cosf(project_angle_limit); | const float project_angle_limit_cos = cosf(project_angle_limit); | ||||
| const float project_angle_limit_half_cos = cosf(project_angle_limit / 2); | const float project_angle_limit_half_cos = cosf(project_angle_limit / 2); | ||||
| /* Memory arena for list links (cleared for each object). */ | /* Memory arena for list links (cleared for each object). */ | ||||
| Show All 22 Lines | |||||
| const uint cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); | const uint cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); | ||||
| ThickFace *thick_faces = MEM_mallocN(sizeof(*thick_faces) * em->bm->totface, __func__); | ThickFace *thick_faces = MEM_mallocN(sizeof(*thick_faces) * em->bm->totface, __func__); | ||||
| uint thick_faces_len = 0; | uint thick_faces_len = 0; | ||||
| BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | ||||
| if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| if (only_selected_uvs) { | |||||
| if (!uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { | |||||
| uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset); | |||||
| continue; | |||||
| } | |||||
| } | |||||
| thick_faces[thick_faces_len].area = BM_face_calc_area(efa); | thick_faces[thick_faces_len].area = BM_face_calc_area(efa); | ||||
| thick_faces[thick_faces_len].efa = efa; | thick_faces[thick_faces_len].efa = efa; | ||||
| thick_faces_len++; | thick_faces_len++; | ||||
| } | } | ||||
| qsort(thick_faces, thick_faces_len, sizeof(ThickFace), smart_uv_project_thickface_area_cmp_fn); | qsort(thick_faces, thick_faces_len, sizeof(ThickFace), smart_uv_project_thickface_area_cmp_fn); | ||||
| /* Remove all zero area faces. */ | /* Remove all zero area faces. */ | ||||
| ▲ Show 20 Lines • Show All 98 Lines • ▼ Show 20 Lines | |||||
| ED_uvedit_pack_islands_multi(scene, | ED_uvedit_pack_islands_multi(scene, | ||||
| objects_changed, | objects_changed, | ||||
| object_changed_len, | object_changed_len, | ||||
| NULL, | NULL, | ||||
| &(struct UVPackIsland_Params){ | &(struct UVPackIsland_Params){ | ||||
| .rotate = true, | .rotate = true, | ||||
| /* We could make this optional. */ | /* We could make this optional. */ | ||||
| .rotate_align_axis = 1, | .rotate_align_axis = 1, | ||||
| .only_selected_uvs = true, | |||||
| .only_selected_faces = true, | .only_selected_faces = true, | ||||
| .correct_aspect = correct_aspect, | .correct_aspect = correct_aspect, | ||||
| .use_seams = true, | .use_seams = true, | ||||
| }); | }); | ||||
| /* #ED_uvedit_pack_islands_multi only supports `per_face_aspect = false`. */ | /* #ED_uvedit_pack_islands_multi only supports `per_face_aspect = false`. */ | ||||
| const bool 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); | MEM_freeN(objects_changed); | ||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| void UV_OT_smart_project(wmOperatorType *ot) | void UV_OT_smart_project(wmOperatorType *ot) | ||||
| ▲ Show 20 Lines • Show All 185 Lines • ▼ Show 20 Lines | |||||
| else { | else { | ||||
| ARRAY_DELETE_REORDER_LAST(objects, ob_index, 1, objects_len); | ARRAY_DELETE_REORDER_LAST(objects, ob_index, 1, objects_len); | ||||
| objects_len -= 1; | objects_len -= 1; | ||||
| ob_index -= 1; | ob_index -= 1; | ||||
| } | } | ||||
| } | } | ||||
| if (changed_multi) { | if (changed_multi) { | ||||
| uv_map_clip_correct_multi(objects, objects_len, op, true); | const bool only_selected_uvs = false; | ||||
| uv_map_clip_correct(scene, objects, objects_len, op, true, only_selected_uvs); | |||||
| } | } | ||||
| MEM_freeN(objects); | MEM_freeN(objects); | ||||
| if (changed_multi) { | if (changed_multi) { | ||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| ▲ Show 20 Lines • Show All 143 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| } | } | ||||
| static int sphere_project_exec(bContext *C, wmOperator *op) | static int sphere_project_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| const Scene *scene = CTX_data_scene(C); | const Scene *scene = CTX_data_scene(C); | ||||
| View3D *v3d = CTX_wm_view3d(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); | ViewLayer *view_layer = CTX_data_view_layer(C); | ||||
| uint objects_len = 0; | uint objects_len = 0; | ||||
| Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( | Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( | ||||
| view_layer, v3d, &objects_len); | view_layer, v3d, &objects_len); | ||||
| for (uint ob_index = 0; ob_index < objects_len; ob_index++) { | for (uint ob_index = 0; ob_index < objects_len; ob_index++) { | ||||
| Object *obedit = objects[ob_index]; | Object *obedit = objects[ob_index]; | ||||
| BMEditMesh *em = BKE_editmesh_from_object(obedit); | BMEditMesh *em = BKE_editmesh_from_object(obedit); | ||||
| BMFace *efa; | BMFace *efa; | ||||
| Show All 16 Lines | |||||
| uv_map_transform(C, op, rotmat); | uv_map_transform(C, op, rotmat); | ||||
| uv_map_transform_center(scene, v3d, obedit, em, center, NULL); | uv_map_transform_center(scene, v3d, obedit, em, center, NULL); | ||||
| BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | ||||
| if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| if (only_selected_uvs) { | |||||
| if (!uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { | |||||
| uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset); | |||||
| continue; | |||||
| } | |||||
| } | |||||
| BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | ||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | ||||
| uv_sphere_project(luv->uv, l->v->co, center, rotmat); | uv_sphere_project(luv->uv, l->v->co, center, rotmat); | ||||
| } | } | ||||
| uv_map_mirror(em, efa); | 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); | DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY); | ||||
| WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); | WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); | ||||
| } | } | ||||
| MEM_freeN(objects); | MEM_freeN(objects); | ||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| Show All 40 Lines | |||||
| } | } | ||||
| } | } | ||||
| static int cylinder_project_exec(bContext *C, wmOperator *op) | static int cylinder_project_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| const Scene *scene = CTX_data_scene(C); | const Scene *scene = CTX_data_scene(C); | ||||
| View3D *v3d = CTX_wm_view3d(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); | ViewLayer *view_layer = CTX_data_view_layer(C); | ||||
| uint objects_len = 0; | uint objects_len = 0; | ||||
| Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( | Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( | ||||
| view_layer, v3d, &objects_len); | view_layer, v3d, &objects_len); | ||||
| for (uint ob_index = 0; ob_index < objects_len; ob_index++) { | for (uint ob_index = 0; ob_index < objects_len; ob_index++) { | ||||
| Object *obedit = objects[ob_index]; | Object *obedit = objects[ob_index]; | ||||
| BMEditMesh *em = BKE_editmesh_from_object(obedit); | BMEditMesh *em = BKE_editmesh_from_object(obedit); | ||||
| BMFace *efa; | BMFace *efa; | ||||
| Show All 16 Lines | |||||
| uv_map_transform(C, op, rotmat); | uv_map_transform(C, op, rotmat); | ||||
| uv_map_transform_center(scene, v3d, obedit, em, center, NULL); | uv_map_transform_center(scene, v3d, obedit, em, center, NULL); | ||||
| BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | ||||
| if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| if (only_selected_uvs && !uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { | |||||
| uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset); | |||||
| continue; | |||||
| } | |||||
| BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | ||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | ||||
| uv_cylinder_project(luv->uv, l->v->co, center, rotmat); | uv_cylinder_project(luv->uv, l->v->co, center, rotmat); | ||||
| } | } | ||||
| uv_map_mirror(em, efa); | 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); | DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY); | ||||
| WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); | WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); | ||||
| } | } | ||||
| MEM_freeN(objects); | MEM_freeN(objects); | ||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| Show All 17 Lines | |||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Cube UV Project Operator | /** \name Cube UV Project Operator | ||||
| * \{ */ | * \{ */ | ||||
| static void uvedit_unwrap_cube_project(BMesh *bm, | static void uvedit_unwrap_cube_project(const Scene *scene, | ||||
| BMEditMesh *em, | |||||
| float cube_size, | float cube_size, | ||||
| bool use_select, | const bool use_select, | ||||
| const bool only_selected_uvs, | |||||
| const float center[3]) | const float center[3]) | ||||
| { | { | ||||
| BMFace *efa; | BMFace *efa; | ||||
| BMLoop *l; | BMLoop *l; | ||||
| BMIter iter, liter; | BMIter iter, liter; | ||||
| MLoopUV *luv; | MLoopUV *luv; | ||||
| float loc[3]; | float loc[3]; | ||||
| int cox, coy; | int cox, coy; | ||||
| int cd_loop_uv_offset; | int cd_loop_uv_offset; | ||||
| cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); | cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); | ||||
| if (center) { | if (center) { | ||||
| copy_v3_v3(loc, center); | copy_v3_v3(loc, center); | ||||
| } | } | ||||
| else { | else { | ||||
| zero_v3(loc); | zero_v3(loc); | ||||
| } | } | ||||
| if (UNLIKELY(cube_size == 0.0f)) { | if (UNLIKELY(cube_size == 0.0f)) { | ||||
| cube_size = 1.0f; | cube_size = 1.0f; | ||||
| } | } | ||||
| /* choose x,y,z axis for projection depending on the largest normal | /* choose x,y,z axis for projection depending on the largest normal | ||||
| * component, but clusters all together around the center of map. */ | * component, but clusters all together around the center of map. */ | ||||
| BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { | BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | ||||
| if (use_select && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | if (use_select && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| if (only_selected_uvs && !uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { | |||||
| uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset); | |||||
| continue; | |||||
| } | |||||
| axis_dominant_v3(&cox, &coy, efa->no); | axis_dominant_v3(&cox, &coy, efa->no); | ||||
| BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | ||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | ||||
| luv->uv[0] = 0.5f + ((l->v->co[cox] - loc[cox]) / cube_size); | luv->uv[0] = 0.5f + ((l->v->co[cox] - loc[cox]) / cube_size); | ||||
| luv->uv[1] = 0.5f + ((l->v->co[coy] - loc[coy]) / cube_size); | luv->uv[1] = 0.5f + ((l->v->co[coy] - loc[coy]) / cube_size); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static int cube_project_exec(bContext *C, wmOperator *op) | static int cube_project_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| const Scene *scene = CTX_data_scene(C); | const Scene *scene = CTX_data_scene(C); | ||||
| View3D *v3d = CTX_wm_view3d(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"); | 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); | const float cube_size_init = RNA_property_float_get(op->ptr, prop_cube_size); | ||||
| ViewLayer *view_layer = CTX_data_view_layer(C); | ViewLayer *view_layer = CTX_data_view_layer(C); | ||||
| uint objects_len = 0; | uint objects_len = 0; | ||||
| Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( | Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( | ||||
| view_layer, v3d, &objects_len); | view_layer, v3d, &objects_len); | ||||
| for (uint ob_index = 0; ob_index < objects_len; ob_index++) { | for (uint ob_index = 0; ob_index < objects_len; ob_index++) { | ||||
| Show All 26 Lines | |||||
| sub_v3_v3v3(dims, bounds[1], bounds[0]); | sub_v3_v3v3(dims, bounds[1], bounds[0]); | ||||
| cube_size = max_fff(UNPACK3(dims)); | cube_size = max_fff(UNPACK3(dims)); | ||||
| if (ob_index == 0) { | if (ob_index == 0) { | ||||
| /* This doesn't fit well with, multiple objects. */ | /* This doesn't fit well with, multiple objects. */ | ||||
| RNA_property_float_set(op->ptr, prop_cube_size, cube_size); | RNA_property_float_set(op->ptr, prop_cube_size, cube_size); | ||||
| } | } | ||||
| } | } | ||||
| uvedit_unwrap_cube_project(em->bm, cube_size, true, center); | uvedit_unwrap_cube_project(scene, em, 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); | DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY); | ||||
| WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); | WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); | ||||
| } | } | ||||
| MEM_freeN(objects); | MEM_freeN(objects); | ||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | |||||
| me, | me, | ||||
| (&(struct BMeshFromMeshParams){ | (&(struct BMeshFromMeshParams){ | ||||
| .calc_face_normal = true, | .calc_face_normal = true, | ||||
| .calc_vert_normal = true, | .calc_vert_normal = true, | ||||
| })); | })); | ||||
| /* select all uv loops first - pack parameters needs this to make sure charts are registered */ | /* select all uv loops first - pack parameters needs this to make sure charts are registered */ | ||||
| ED_uvedit_select_all(bm); | ED_uvedit_select_all(bm); | ||||
| /* A cube size of 2.0 maps [-1..1] vertex coords to [0.0..1.0] in UV coords. */ | /* 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. */ | /* Set the margin really quickly before the packing operation. */ | ||||
| scene->toolsettings->uvcalc_margin = 0.001f; | scene->toolsettings->uvcalc_margin = 0.001f; | ||||
| uvedit_pack_islands(scene, ob, bm); | uvedit_pack_islands(scene, ob, bm); | ||||
| BM_mesh_bm_to_me(bmain, bm, me, (&(struct BMeshToMeshParams){0})); | BM_mesh_bm_to_me(bmain, bm, me, (&(struct BMeshToMeshParams){0})); | ||||
| BM_mesh_free(bm); | BM_mesh_free(bm); | ||||
| if (sync_selection) { | if (sync_selection) { | ||||
| scene->toolsettings->uv_flag |= UV_SYNC_SELECTION; | scene->toolsettings->uv_flag |= UV_SYNC_SELECTION; | ||||
| } | } | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| Context not available. | |||||