Blender V5.0
uvedit_islands.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
15
16#include "BLI_listbase.h"
17#include "BLI_math_vector.h"
18
19#include "BKE_editmesh.hh"
20
21#include "DNA_image_types.h"
22
23#include "ED_uvedit.hh" /* Own include. */
24
25/* -------------------------------------------------------------------- */
28
29bool uv_coords_isect_udim(const Image *image, const int udim_grid[2], const float coords[2])
30{
31 const float coords_floor[2] = {floorf(coords[0]), floorf(coords[1])};
32 const bool is_tiled_image = image && (image->source == IMA_SRC_TILED);
33
34 if (coords[0] < udim_grid[0] && coords[0] > 0 && coords[1] < udim_grid[1] && coords[1] > 0) {
35 return true;
36 }
37 /* Check if selection lies on a valid UDIM image tile. */
38 if (is_tiled_image) {
39 LISTBASE_FOREACH (const ImageTile *, tile, &image->tiles) {
40 const int tile_index = tile->tile_number - 1001;
41 const int target_x = (tile_index % 10);
42 const int target_y = (tile_index / 10);
43 if (coords_floor[0] == target_x && coords_floor[1] == target_y) {
44 return true;
45 }
46 }
47 }
48 /* Probably not required since UDIM grid checks for 1001. */
49 else if (image && !is_tiled_image) {
50 if (is_zero_v2(coords_floor)) {
51 return true;
52 }
53 }
54
55 return false;
56}
57
59
60/* -------------------------------------------------------------------- */
63
68
69static bool bm_loop_uv_shared_edge_check(const BMLoop *l_a, const BMLoop *l_b, void *user_data)
70{
71 const SharedUVLoopData *data = static_cast<const SharedUVLoopData *>(user_data);
72
73 if (data->use_seams) {
74 if (BM_elem_flag_test(l_a->e, BM_ELEM_SEAM)) {
75 return false;
76 }
77 }
78
79 return BM_loop_uv_share_edge_check((BMLoop *)l_a, (BMLoop *)l_b, data->offsets.uv);
80}
81
92 const BMesh *bm,
93 BMFace *efa,
94 const bool only_selected_faces,
95 const bool only_selected_uvs)
96{
98 return false;
99 }
100 if (only_selected_faces) {
101 if (only_selected_uvs) {
102 return BM_elem_flag_test(efa, BM_ELEM_SELECT) && uvedit_face_select_test(scene, bm, efa);
103 }
105 }
106 return true;
107}
108
110 BMesh *bm,
111 ListBase *island_list,
112 const bool only_selected_faces,
113 const bool only_selected_uvs,
114 const bool use_seams,
115 const float aspect_y,
116 const BMUVOffsets &uv_offsets)
117{
118 BLI_assert(uv_offsets.uv >= 0);
119 int island_added = 0;
121
122 int *groups_array = MEM_malloc_arrayN<int>(bm->totface, __func__);
123
124 int (*group_index)[2];
125
126 /* Set the tag for `BM_mesh_calc_face_groups`. */
127 BMFace *f;
128 BMIter iter;
129 BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
130 const bool face_affected = uvedit_is_face_affected_for_calc_uv_islands(
131 scene, bm, f, only_selected_faces, only_selected_uvs);
132 BM_elem_flag_set(f, BM_ELEM_TAG, face_affected);
133 }
134
135 SharedUVLoopData user_data = {{0}};
136 user_data.offsets = uv_offsets;
137 user_data.use_seams = use_seams;
138
139 const int group_len = BM_mesh_calc_face_groups(bm,
140 groups_array,
141 &group_index,
142 nullptr,
144 &user_data,
146 BM_EDGE);
147
148 for (int i = 0; i < group_len; i++) {
149 const int faces_start = group_index[i][0];
150 const int faces_len = group_index[i][1];
151 BMFace **faces = MEM_malloc_arrayN<BMFace *>(faces_len, __func__);
152
153 for (int j = 0; j < faces_len; j++) {
154 faces[j] = BM_face_at_index(bm, groups_array[faces_start + j]);
155 }
156
157 FaceIsland *island = MEM_callocN<FaceIsland>(__func__);
158 island->faces = faces;
159 island->faces_len = faces_len;
160 island->offsets = uv_offsets;
161 island->aspect_y = aspect_y;
162 BLI_addtail(island_list, island);
163 island_added += 1;
164 }
165
166 MEM_freeN(groups_array);
167 MEM_freeN(group_index);
168 return island_added;
169}
170
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
MINLINE bool is_zero_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
@ IMA_SRC_TILED
bool uvedit_face_select_test(const Scene *scene, const BMesh *bm, const BMFace *efa)
@ BM_ELEM_HIDDEN
@ BM_ELEM_SEAM
@ BM_ELEM_SELECT
@ BM_ELEM_TAG
#define BM_elem_flag_set(ele, hflag, val)
#define BM_elem_flag_test(ele, hflag)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_FACES_OF_MESH
BMesh const char void * data
BMesh * bm
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
BLI_INLINE BMFace * BM_face_at_index(BMesh *bm, const int index)
#define BM_FACE
#define BM_EDGE
int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int(**r_group_index)[2], BMLoopFilterFunc filter_fn, BMLoopPairFilterFunc filter_pair_fn, void *user_data, const char hflag_test, const char htype_step)
ATTR_WARN_UNUSED_RESULT const BMLoop * l_b
bool BM_loop_uv_share_edge_check(const BMLoop *l_a, const BMLoop *l_b, const int cd_loop_uv_offset)
const ccl_global KernelWorkTile * tile
const int tile_index
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static char faces[256]
#define floorf
struct BMEdge * e
float aspect_y
Definition ED_uvedit.hh:374
BMFace ** faces
Definition ED_uvedit.hh:367
BMUVOffsets offsets
Definition ED_uvedit.hh:373
ListBase tiles
short source
BMUVOffsets offsets
i
Definition text_draw.cc:230
int bm_mesh_calc_uv_islands(const Scene *scene, BMesh *bm, ListBase *island_list, const bool only_selected_faces, const bool only_selected_uvs, const bool use_seams, const float aspect_y, const BMUVOffsets &uv_offsets)
bool uv_coords_isect_udim(const Image *image, const int udim_grid[2], const float coords[2])
static bool bm_loop_uv_shared_edge_check(const BMLoop *l_a, const BMLoop *l_b, void *user_data)
static bool uvedit_is_face_affected_for_calc_uv_islands(const Scene *scene, const BMesh *bm, BMFace *efa, const bool only_selected_faces, const bool only_selected_uvs)