40 const float calc_dist,
50 r_td2d->
loc[0] =
uv[0] * aspect[0];
51 r_td2d->
loc[1] =
uv[1] * aspect[1];
52 r_td2d->
loc[2] = 0.0f;
71 r_td->
dist = calc_dist;
84 const float aspect[2])
86#define TMP_LOOP_SELECT_TAG BM_ELEM_TAG_ALT
130 dists[loop_idx] = dist;
135 float *dists_prev =
static_cast<float *
>(
MEM_dupallocN(dists));
141 BMLoop *l_other, *l_connected;
154 float other_uv[2], edge_vec[2];
164 float dist =
len_v2(edge_vec) + dists_prev[
i];
166 if (dist < dists[i_other]) {
167 dists[i_other] = dist;
174 bool other_vert_sel, connected_vert_sel;
179 if (l_connected == l_other) {
193 bool connected = other_vert_sel == connected_vert_sel &&
201 dists[i_connected] = dist;
212 for (
LinkNode *lnk = queue_next; lnk; lnk = lnk->
next) {
219 dists_prev[
i] = dists[
i];
244#undef TMP_LOOP_SELECT_TAG
264 struct IslandCenter {
267 } *island_center =
nullptr;
268 int count = 0, countsel = 0;
276 if (is_island_center) {
279 if (elementmap ==
nullptr) {
308 island_center[
element->island].co_num++;
320 float *prop_dists =
nullptr;
324 if (((is_prop_edit && !is_prop_connected) ?
count : countsel) == 0) {
328 if (is_island_center) {
330 mul_v2_fl(island_center[
i].co, 1.0f / island_center[
i].co_num);
335 tc->data_len = (is_prop_edit) ?
count : countsel;
348 if (is_prop_connected) {
364 const float *center =
nullptr;
367 if (!is_prop_edit && !selected) {
371 if (is_prop_connected) {
373 prop_distance = prop_dists[idx];
376 if (is_island_center) {
379 center = island_center[
element->island].co;
394 if (is_prop_connected) {
397 if (is_island_center) {
420 float aspect_inv[2],
size[2];
422 aspect_inv[0] = 1.0f / t->
aspect[0];
423 aspect_inv[1] = 1.0f / t->
aspect[1];
425 if (use_pixel_round) {
433 for (a = 0, td = tc->data_2d; a < tc->data_len; a++, td++) {
434 td->
loc2d[0] = td->
loc[0] * aspect_inv[0];
435 td->
loc2d[1] = td->
loc[1] * aspect_inv[1];
437 if (use_pixel_round) {
514 groups_offs_buffer_.reserve(this->sd_len);
515 groups_offs_indices_.reserve((this->sd_len / 4) + 2);
526 groups_offs_indices_.append(groups_offs_buffer_.size());
536 if (l_orig != l_iter &&
547 groups_offs_indices_.append(groups_offs_buffer_.size());
557 return groups_offs_buffer_.as_span().
slice(this->
groups()[group_index]);
564 for (
const int group_index : this->
groups().index_range()) {
579 for (
const int group_index : this->
groups().index_range()) {
594 const int group_index)
596 return sd_array.
slice(this->
groups()[group_index]);
600 const int group_index)
602 return sd_array.
slice(this->
groups()[group_index]);
609 if (uv_groups ==
nullptr) {
610 uv_groups = MEM_new<UVGroups>(__func__);
611 uv_groups->
init(tc,
bm, offsets);
620 custom_data->data =
nullptr;
647 for (
const int group_index : uv_groups->
groups().index_range()) {
648 const int size_prev = r_loc_dst_buffer.
size();
654 for (
BMLoop *l_dst : {
l->prev,
l->next}) {
658 bool skip = std::any_of(
659 uvs_added.
begin(), uvs_added.
end(), [&](
const float3 &uv_dest_added) {
660 return compare_v2v2(uv_dest, uv_dest_added, FLT_EPSILON);
669 const int size_new = r_loc_dst_buffer.
size() - size_prev;
681 for (
float3 &dest : r_loc_dst_buffer) {
689 sv.co_link_orig_3d = r_loc_dst_buffer.
as_span().slice(start, sv.co_link_orig_3d.size());
706 if (group.
size() == 1) {
709 if (group.
size() > 2) {
721 if (l_a_prev->
v != l_b_prev->
v) {
722 std::swap(l_b_prev, l_b_next);
723 if (l_a_prev->
v != l_b_prev->
v) {
728 if (l_a_next->
v != l_b_next->
v) {
754 const float2 &ray_direction,
769 if (
isect_ray_seg_v2(uv_tmp, ray_direction, uv_iter, uv_iter_next, &lambda,
nullptr) ||
770 isect_ray_seg_v2(uv_tmp, -ray_direction, uv_iter, uv_iter_next, &lambda,
nullptr))
772 float2 isect_co = uv_tmp + ray_direction * lambda;
777 if (dist_sq_test < dist_sq_best) {
779 dist_sq_best = dist_sq_test;
783 }
while ((l_iter = l_iter->
next) != l_last);
805 float2 ray_dir = (
uv - uv_prev) + (uv_next -
uv);
807 ray_dir[0] /= aspect[0];
808 ray_dir[1] /= aspect[1];
845 for (
const int group_index : uv_groups->
groups().index_range()) {
855 for (
const int group_index : uv_groups->
groups().index_range()) {
856 int2 &group_linked_pair = groups_linked[group_index];
862 for (
BMLoop *l_dst : {
l->prev,
l->next}) {
864 if (group_index_dst == -1) {
868 if (
ELEM(group_index_dst, group_linked_pair[0], group_linked_pair[1])) {
873 BMLoop *l_edge = l_dst ==
l->prev ? l_dst :
l;
879 if (group_linked_pair[1] != -1) {
883 const int slot = int(group_linked_pair[0] != -1);
884 group_linked_pair[slot] = group_index_dst;
888 if (group_linked_pair[0] == -1) {
900 if (sv_array[
i].loop_nr != -1) {
909 int i_curr = group_index;
910 int i_prev = groups_linked[group_index][1];
911 while (!
ELEM(i_prev, -1, group_index)) {
912 int tmp = groups_linked[i_prev][0] != i_curr ? groups_linked[i_prev][0] :
913 groups_linked[i_prev][1];
926 struct SlideTempDataUV {
941 int find_best_dir(
const SlideTempDataUV *curr_side_other,
946 bool *r_do_isect_curr_dirs)
const
948 *r_do_isect_curr_dirs =
false;
949 const BMFace *f_curr = l_src->
f;
950 if (curr_side_other->fdata[0].f &&
951 (curr_side_other->fdata[0].f == f_curr ||
952 compare_v2v2(dst, curr_side_other->fdata[0].dst, FLT_EPSILON)))
957 if (curr_side_other->fdata[1].f &&
958 (curr_side_other->fdata[1].f == f_curr ||
959 compare_v2v2(dst, curr_side_other->fdata[1].dst, FLT_EPSILON)))
964 if (curr_side_other->fdata[0].f || curr_side_other->fdata[1].f) {
967 const BMLoop *l_edge_dst = l_src->
prev == l_dst ? l_src->
prev : l_src;
969 while (l_other != l_edge_dst) {
970 const BMLoop *l_other_dst = l_other->
v == l_src->
v ? l_other->
next : l_other;
976 if (l_other->
f == curr_side_other->fdata[0].f) {
980 if (l_other->
f == curr_side_other->fdata[1].f) {
984 l_other = (l_other->
v == l_src->
v ? l_other->
prev : l_other->
next)->radial_next;
987 if (best_dir != -1) {
988 *r_do_isect_curr_dirs =
true;
993 if (
ELEM(
nullptr, this->fdata[0].f, this->fdata[1].f)) {
994 return int(this->fdata[0].f !=
nullptr);
998 *r_do_isect_curr_dirs =
true;
1000 float2 dir_curr = dst - src;
1005 return int(dot0 < dot1);
1007 } prev = {}, curr = {},
next = {}, tmp = {};
1015 while (curr.i != -1) {
1016 int tmp_i = prev.i == -1 ? i_prev : prev.i;
1017 next.i = groups_linked[curr.i][0] != tmp_i ? groups_linked[curr.i][0] :
1018 groups_linked[curr.i][1];
1030 for (
int td_index_next : td_indices_next) {
1032 if (l_curr->
f != l_next->
f) {
1039 if (l_curr->
next == l_next) {
1040 l1_dst = l_curr->
prev;
1041 l2_dst = l_next->
next;
1044 l1_dst = l_curr->
next;
1045 l2_dst = l_next->
prev;
1052 bool isect_curr_dirs =
false;
1056 int best_dir = curr.find_best_dir(&tmp, l_curr, l1_dst, src, dst, &isect_curr_dirs);
1058 if (curr.fdata[best_dir].f ==
nullptr) {
1059 curr.fdata[best_dir].f = l_curr->
f;
1060 if (curr.vert_is_inner) {
1064 curr.fdata[best_dir].dst = dst;
1069 next.fdata[best_dir].f = l_curr->
f;
1078 next.fdata[best_dir].dst = dst_next;
1081 if (isect_curr_dirs) {
1083 const float2 &dst0 = prev.fdata[best_dir].dst;
1084 const float2 &dst1 = curr.fdata[best_dir].dst;
1085 const float2 &dst2 = dst;
1086 const float2 &dst3 =
next.fdata[best_dir].dst;
1109 float2 iloc = sv.td->iloc;
1111 if (curr.fdata[0].f) {
1112 float2 dst = curr.fdata[0].dst * aspect;
1113 sv.dir_side[0] =
float3(dst - iloc, 0.0f);
1115 if (curr.fdata[1].f) {
1116 float2 dst = curr.fdata[1].dst * aspect;
1117 sv.dir_side[1] =
float3(dst - iloc, 0.0f);
1120 sv.loop_nr = loop_nr;
1124 if (i_prev != -1 && prev.i == i_prev) {
1134 next.fdata[0].f =
next.fdata[1].f =
nullptr;
1138 *r_group_len = loop_nr;
SpaceImage * CTX_wm_space_image(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
CustomData interface, see also DNA_customdata_types.h.
BMEditMesh * BKE_editmesh_from_object(Object *ob)
Return the BMEditMesh for a given object.
BLI_LINKSTACK_*** wrapper macros for using a LinkNode to store a stack of pointers,...
#define BLI_LINKSTACK_PUSH(var, ptr)
#define BLI_LINKSTACK_DECLARE(var, type)
#define BLI_LINKSTACK_SIZE(var)
#define BLI_LINKSTACK_FREE(var)
#define BLI_LINKSTACK_INIT(var)
#define BLI_LINKSTACK_POP(var)
#define BLI_LINKSTACK_SWAP(var_a, var_b)
#define ISECT_LINE_LINE_COLINEAR
bool isect_ray_seg_v2(const float ray_origin[2], const float ray_direction[2], const float v0[2], const float v1[2], float *r_lambda, float *r_u)
int isect_line_line_v2_point(const float v0[2], const float v1[2], const float v2[2], const float v3[2], float r_vi[2])
void unit_m3(float m[3][3])
MINLINE float len_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void mul_v2_v2(float r[2], const float a[2])
MINLINE void mul_v2_fl(float r[2], float f)
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void add_v2_v2(float r[2], const float a[2])
MINLINE bool equals_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT
MINLINE bool compare_v2v2(const float v1[2], const float v2[2], float limit) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
#define POINTER_FROM_INT(i)
#define POINTER_AS_INT(i)
void DEG_id_tag_update(ID *id, unsigned int flags)
@ SI_PIXEL_ROUND_DISABLED
@ V3D_AROUND_LOCAL_ORIGINS
void ED_space_image_get_size(SpaceImage *sima, int *r_width, int *r_height)
bool ED_space_image_show_uvedit(const SpaceImage *sima, Object *obedit)
UvElement * BM_uv_element_get(const UvElementMap *element_map, const BMLoop *l)
void BM_uv_element_map_free(UvElementMap *element_map)
UvElementMap * BM_uv_element_map_create(BMesh *bm, const Scene *scene, bool uv_selected, bool use_winding, bool use_seams, bool do_islands)
void ED_uvedit_live_unwrap_begin(Scene *scene, Object *obedit, struct wmWindow *win_modal)
char ED_uvedit_select_mode_get(const Scene *scene)
bool uvedit_edge_select_test_ex(const ToolSettings *ts, const BMesh *bm, const BMLoop *l, const BMUVOffsets &offsets)
void ED_uvedit_live_unwrap_re_solve()
bool uvedit_uv_select_test(const Scene *scene, const BMesh *bm, const BMLoop *l, const BMUVOffsets &offsets)
bool uvedit_face_visible_test(const Scene *scene, const BMFace *efa)
bool uvedit_uv_select_test_ex(const ToolSettings *ts, const BMesh *bm, const BMLoop *l, const BMUVOffsets &offsets)
Read Guarded memory(de)allocation.
#define BM_ELEM_CD_GET_FLOAT_P(ele, offset)
#define BM_elem_index_get(ele)
#define BM_elem_flag_disable(ele, hflag)
#define BM_elem_index_set(ele, index)
#define BM_elem_flag_test(ele, hflag)
#define BM_elem_flag_test_bool(ele, hflag)
#define BM_elem_flag_enable(ele, hflag)
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
BMesh const char void * data
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
ATTR_WARN_UNUSED_RESULT const void * element
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMLoop * l_b
BMUVOffsets BM_uv_map_offsets_get(const BMesh *bm)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
constexpr Span slice(int64_t start, int64_t size) const
IndexRange index_range() const
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr int64_t size() const
constexpr const T * end() const
constexpr const T * begin() const
void append(const T &value)
void reserve(const int64_t min_capacity)
Span< T > as_span() const
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_dupallocN(const void *vmemh)
void MEM_freeN(void *vmemh)
T distance(const T &a, const T &b)
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
T midpoint(const T &a, const T &b)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
T distance_squared(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
VecBase< T, 3 > orthogonal(const VecBase< T, 3 > &v)
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
VecBase< float, 3 > float3
struct BMLoop * radial_next