39 const float calc_dist,
49 r_td2d->
loc[0] = uv[0] * aspect[0];
50 r_td2d->
loc[1] = uv[1] * aspect[1];
51 r_td2d->
loc[2] = 0.0f;
55 r_td->loc = r_td2d->
loc;
56 copy_v2_v2(r_td->center, center ? center : r_td->loc);
57 r_td->center[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) {
283 island_center =
static_cast<IslandCenter *
>(
306 if (element && !element->flag) {
308 add_v2_v2(island_center[element->island].co, luv);
309 island_center[element->island].co_num++;
310 element->flag =
true;
321 float *prop_dists =
nullptr;
325 if (((is_prop_edit && !is_prop_connected) ?
count : countsel) == 0) {
329 if (is_island_center) {
331 mul_v2_fl(island_center[i].co, 1.0f / island_center[i].co_num);
336 tc->data_len = (is_prop_edit) ?
count : countsel;
351 if (is_prop_connected) {
352 prop_dists =
static_cast<float *
>(
368 const float *center =
nullptr;
371 if (!is_prop_edit && !selected) {
375 if (is_prop_connected) {
377 prop_distance = prop_dists[idx];
380 if (is_island_center) {
383 center = island_center[element->island].co;
398 if (is_prop_connected) {
401 if (is_island_center) {
424 float aspect_inv[2], size[2];
426 aspect_inv[0] = 1.0f / t->
aspect[0];
427 aspect_inv[1] = 1.0f / t->
aspect[1];
429 if (use_pixel_round) {
437 for (a = 0, td = tc->data_2d; a < tc->data_len; a++, td++) {
438 td->
loc2d[0] = td->
loc[0] * aspect_inv[0];
439 td->
loc2d[1] = td->
loc[1] * aspect_inv[1];
441 if (use_pixel_round) {
442 td->
loc2d[0] *= size[0];
443 td->
loc2d[1] *= size[1];
447 td->
loc2d[0] = roundf(td->
loc2d[0] - 0.5f) + 0.5f;
448 td->
loc2d[1] = roundf(td->
loc2d[1] - 0.5f) + 0.5f;
456 td->
loc2d[0] /= size[0];
457 td->
loc2d[1] /= size[1];
509 for (
int i = 0; i < tc->
data_len; i++, td++) {
522 groups_offs_buffer_.
reserve(this->sd_len);
523 groups_offs_indices_.
reserve((this->sd_len / 4) + 2);
526 for (
int i = 0; i < tc->
data_len; i++, td++) {
534 groups_offs_indices_.
append(groups_offs_buffer_.
size());
544 if (l_orig != l_iter &&
555 groups_offs_indices_.
append(groups_offs_buffer_.
size());
565 return groups_offs_buffer_.
as_span().slice(this->
groups()[group_index]);
572 for (
const int group_index : this->
groups().index_range()) {
587 for (
const int group_index : this->
groups().index_range()) {
602 const int group_index)
604 return sd_array.
slice(this->
groups()[group_index]);
608 const int group_index)
610 return sd_array.
slice(this->
groups()[group_index]);
617 if (uv_groups ==
nullptr) {
618 uv_groups = MEM_new<UVGroups>(__func__);
619 uv_groups->
init(tc,
bm, offsets);
628 custom_data->data =
nullptr;
655 for (
const int group_index : uv_groups->
groups().index_range()) {
656 const int size_prev = r_loc_dst_buffer.
size();
666 bool skip = std::any_of(
667 uvs_added.
begin(), uvs_added.
end(), [&](
const float3 &uv_dest_added) {
668 return compare_v2v2(uv_dest, uv_dest_added, FLT_EPSILON);
677 const int size_new = r_loc_dst_buffer.
size() - size_prev;
689 for (
float3 &dest : r_loc_dst_buffer) {
697 sv.co_link_orig_3d = r_loc_dst_buffer.
as_span().slice(start, sv.co_link_orig_3d.size());
714 if (group.size() == 1) {
717 if (group.size() > 2) {
729 if (l_a_prev->
v != l_b_prev->
v) {
730 std::swap(l_b_prev, l_b_next);
731 if (l_a_prev->
v != l_b_prev->
v) {
736 if (l_a_next->
v != l_b_next->
v) {
762 const float2 &ray_direction,
777 if (
isect_ray_seg_v2(uv_tmp, ray_direction, uv_iter, uv_iter_next, &lambda,
nullptr) ||
778 isect_ray_seg_v2(uv_tmp, -ray_direction, uv_iter, uv_iter_next, &lambda,
nullptr))
780 float2 isect_co = uv_tmp + ray_direction * lambda;
785 if (dist_sq_test < dist_sq_best) {
787 dist_sq_best = dist_sq_test;
791 }
while ((l_iter = l_iter->
next) != l_last);
813 float2 ray_dir = (uv - uv_prev) + (uv_next - uv);
815 ray_dir[0] /= aspect[0];
816 ray_dir[1] /= aspect[1];
846 for (
int i = 0; i < tc->
data_len; i++, td++) {
857 for (
const int group_index : uv_groups->
groups().index_range()) {
867 for (
const int group_index : uv_groups->
groups().index_range()) {
868 int2 &group_linked_pair = groups_linked[group_index];
876 if (group_index_dst == -1) {
880 if (
ELEM(group_index_dst, group_linked_pair[0], group_linked_pair[1])) {
891 if (group_linked_pair[1] != -1) {
895 const int slot =
int(group_linked_pair[0] != -1);
896 group_linked_pair[slot] = group_index_dst;
900 if (group_linked_pair[0] == -1) {
912 if (r_sv[i].loop_nr != -1) {
921 int i_curr = group_index;
922 int i_prev = groups_linked[group_index][1];
923 while (!
ELEM(i_prev, -1, group_index)) {
924 int tmp = groups_linked[i_prev][0] != i_curr ? groups_linked[i_prev][0] :
925 groups_linked[i_prev][1];
938 struct SlideTempDataUV {
953 int find_best_dir(
const SlideTempDataUV *curr_side_other,
958 bool *r_do_isect_curr_dirs)
const
960 *r_do_isect_curr_dirs =
false;
961 const BMFace *f_curr = l_src->
f;
962 if (curr_side_other->fdata[0].f &&
963 (curr_side_other->fdata[0].f == f_curr ||
964 compare_v2v2(dst, curr_side_other->fdata[0].dst, FLT_EPSILON)))
969 if (curr_side_other->fdata[1].f &&
970 (curr_side_other->fdata[1].f == f_curr ||
971 compare_v2v2(dst, curr_side_other->fdata[1].dst, FLT_EPSILON)))
976 if (curr_side_other->fdata[0].f || curr_side_other->fdata[1].f) {
979 const BMLoop *l_edge_dst = l_src->
prev == l_dst ? l_src->
prev : l_src;
981 while (l_other != l_edge_dst) {
982 const BMLoop *l_other_dst = l_other->
v == l_src->
v ? l_other->
next : l_other;
988 if (l_other->
f == curr_side_other->fdata[0].f) {
992 if (l_other->
f == curr_side_other->fdata[1].f) {
996 l_other = (l_other->
v == l_src->
v ? l_other->
prev : l_other->
next)->radial_next;
999 if (best_dir != -1) {
1000 *r_do_isect_curr_dirs =
true;
1005 if (
ELEM(
nullptr, this->fdata[0].f, this->fdata[1].f)) {
1006 return int(this->fdata[0].f !=
nullptr);
1010 *r_do_isect_curr_dirs =
true;
1012 float2 dir_curr = dst - src;
1017 return int(dot0 < dot1);
1019 } prev = {}, curr = {},
next = {}, tmp = {};
1027 while (curr.i != -1) {
1028 int tmp_i = prev.i == -1 ? i_prev : prev.i;
1029 next.i = groups_linked[curr.i][0] != tmp_i ? groups_linked[curr.i][0] :
1030 groups_linked[curr.i][1];
1042 for (
int td_index_next : td_indices_next) {
1044 if (l_curr->
f != l_next->
f) {
1051 if (l_curr->
next == l_next) {
1052 l1_dst = l_curr->
prev;
1053 l2_dst = l_next->
next;
1056 l1_dst = l_curr->
next;
1057 l2_dst = l_next->
prev;
1064 bool isect_curr_dirs =
false;
1068 int best_dir = curr.find_best_dir(&tmp, l_curr, l1_dst, src, dst, &isect_curr_dirs);
1070 if (curr.fdata[best_dir].f ==
nullptr) {
1071 curr.fdata[best_dir].f = l_curr->
f;
1072 if (curr.vert_is_inner) {
1076 curr.fdata[best_dir].dst = dst;
1081 next.fdata[best_dir].f = l_curr->
f;
1090 next.fdata[best_dir].dst = dst_next;
1093 if (isect_curr_dirs) {
1095 const float2 &dst0 = prev.fdata[best_dir].dst;
1096 const float2 &dst1 = curr.fdata[best_dir].dst;
1097 const float2 &dst2 = dst;
1098 const float2 &dst3 =
next.fdata[best_dir].dst;
1121 float2 iloc = sv.td->iloc;
1123 if (curr.fdata[0].f) {
1124 float2 dst = curr.fdata[0].dst * aspect;
1125 sv.dir_side[0] =
float3(dst - iloc, 0.0f);
1127 if (curr.fdata[1].f) {
1128 float2 dst = curr.fdata[1].dst * aspect;
1129 sv.dir_side[1] =
float3(dst - iloc, 0.0f);
1132 sv.loop_nr = loop_nr;
1136 if (i_prev != -1 && prev.i == i_prev) {
1146 next.fdata[0].f =
next.fdata[1].f =
nullptr;
1150 *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)
void ED_uvedit_live_unwrap_re_solve()
bool uvedit_edge_select_test_ex(const ToolSettings *ts, const BMLoop *l, BMUVOffsets offsets)
bool uvedit_face_visible_test(const Scene *scene, BMFace *efa)
bool uvedit_uv_select_test_ex(const ToolSettings *ts, const BMLoop *l, BMUVOffsets offsets)
bool uvedit_uv_select_test(const Scene *scene, BMLoop *l, 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)
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMLoop * l_b
BMUVOffsets BM_uv_map_get_offsets(const BMesh *bm)
IndexRange index_range() const
constexpr MutableSpan slice(const int64_t start, const 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
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
void MEM_freeN(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
void *(* MEM_dupallocN)(const 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< float, 3 > float3
struct BMLoop * radial_next
void(* free_cb)(TransInfo *, TransDataContainer *tc, TransCustomData *custom_data)
TransCustomDataContainer custom
blender::float3 dir_side[2]
Array< TransDataEdgeSlideVert > sd_array_create_and_init_edge(TransDataContainer *tc)
MutableSpan< TransDataEdgeSlideVert > sd_group_get(MutableSpan< TransDataEdgeSlideVert > sd_array, const int group_index)
OffsetIndices< int > groups() const
Array< TransDataVertSlideVert > sd_array_create_and_init(TransDataContainer *tc)
MutableSpan< TransDataVertSlideVert > sd_group_get(MutableSpan< TransDataVertSlideVert > sd_array, const int group_index)
void init(const TransDataContainer *tc, BMesh *bm, const BMUVOffsets &offsets)
Span< int > td_indices_get(const int group_index) const