12#include <fmt/format.h>
47#include "RNA_prototypes.hh"
64struct StitchPreviewer {
68 uint *uvs_per_polygon;
73 float *preview_stitchable;
74 float *preview_unstitchable;
77 uint num_unstitchable;
84struct IslandStitchData;
91struct IslandStitchData {
100 int num_rot_elements_neg;
102 char addedForPreview;
104 char stitchableCandidate;
106 bool use_edge_rotation;
110struct UVVertAverage {
144 UvElementMap *element_map;
158 bool *island_is_stitchable;
161 int total_separate_edges;
162 int total_separate_uvs;
164 void **selection_stack;
168 uint *tris_per_island;
170 StitchPreviewer *stitch_preview;
174struct StitchStateContainer {
195 StitchState **states;
197 int active_object_index;
200struct PreviewPosition {
202 int polycount_position;
209 STITCH_STITCHABLE = 2,
210 STITCH_PROCESSED = 4,
212 STITCH_STITCHABLE_CANDIDATE = 16,
215#define STITCH_NO_PREVIEW -1
229struct StitchStateInit {
230 int uv_selected_count;
231 UvElementID *to_select;
239 StitchPreviewer *stitch_preview;
242 stitch_preview->preview_polys =
nullptr;
243 stitch_preview->preview_stitchable =
nullptr;
244 stitch_preview->preview_unstitchable =
nullptr;
245 stitch_preview->uvs_per_polygon =
nullptr;
247 stitch_preview->preview_uvs = 0;
248 stitch_preview->num_polys = 0;
249 stitch_preview->num_stitchable = 0;
250 stitch_preview->num_unstitchable = 0;
252 stitch_preview->static_tris =
nullptr;
254 stitch_preview->num_static_tris = 0;
256 return stitch_preview;
262 if (stitch_preview) {
278 status.item(fmt::format(
"{} {}",
280 (ssc->mode == STITCH_VERT ?
IFACE_(
"Vertices") :
IFACE_(
"Edges"))),
283 status.item(fmt::format(
"{} : {}",
285 (ssc->mode == STITCH_VERT ?
IFACE_(
"Vertex") :
IFACE_(
"Edge"))),
288 status.item_bool(
IFACE_(
"Snap"), ssc->snap_islands, ICON_EVENT_S);
289 status.item_bool(
IFACE_(
"Midpoints"), ssc->midpoints, ICON_EVENT_M);
290 status.item_bool(
IFACE_(
"Limit"), ssc->use_limit, ICON_EVENT_L);
291 if (ssc->use_limit) {
292 status.item(fmt::format(
"{} ({:.2f})",
IFACE_(
"Limit Distance"), ssc->limit_dist),
294 ICON_MOUSE_MMB_SCROLL);
299 const float medianPoint[2],
303 float uv_rotation_result[2];
319 StitchStateContainer *ssc)
327 limit = ssc->limit_dist;
329 if (ssc->use_limit) {
337 if (
fabsf(luv[0] - luv_iter[0]) < limit &&
fabsf(luv[1] - luv_iter[1]) < limit) {
348 StitchStateContainer *ssc,
353 if (edge_iter == edge) {
357 limit = ssc->limit_dist;
359 if (ssc->use_limit) {
366 if (
fabsf(luv_orig1[0] - luv_iter1[0]) < limit &&
fabsf(luv_orig1[1] - luv_iter1[1]) < limit &&
367 fabsf(luv_orig2[0] - luv_iter2[0]) < limit &&
fabsf(luv_orig2[1] - luv_iter2[1]) < limit)
379 StitchStateContainer *ssc)
381 if ((ssc->snap_islands &&
element->island == element_iter->
island) ||
382 (!ssc->midpoints &&
element->island == element_iter->
island))
393 StitchStateContainer *ssc,
396 if ((ssc->snap_islands && edge->element->island == edge_iter->element->island) ||
397 (!ssc->midpoints && edge->element->island == edge_iter->element->island))
408 PreviewPosition *preview_position,
409 StitchPreviewer *preview,
410 IslandStitchData *island_stitch_data,
415 for (
int i = 0;
i <
state->element_map->total_islands;
i++) {
416 if (island_stitch_data[
i].addedForPreview) {
417 int numOfIslandUVs = 0, j;
418 int totelem = island_stitch_data[
i].num_rot_elements_neg +
419 island_stitch_data[
i].num_rot_elements;
421 float rotation_mat[2][2];
424 if (island_stitch_data[
i].num_rot_elements > 1) {
425 island_stitch_data[
i].rotation /= island_stitch_data[
i].num_rot_elements;
428 if (island_stitch_data[
i].num_rot_elements_neg > 1) {
429 island_stitch_data[
i].rotation_neg /= island_stitch_data[
i].num_rot_elements_neg;
432 if (island_stitch_data[
i].numOfElements > 1) {
433 island_stitch_data[
i].medianPoint[0] /= island_stitch_data[
i].numOfElements;
434 island_stitch_data[
i].medianPoint[1] /= island_stitch_data[
i].numOfElements;
436 island_stitch_data[
i].translation[0] /= island_stitch_data[
i].numOfElements;
437 island_stitch_data[
i].translation[1] /= island_stitch_data[
i].numOfElements;
440 island_stitch_data[
i].medianPoint[1] /=
state->aspect;
441 if ((island_stitch_data[
i].rotation + island_stitch_data[
i].rotation_neg <
float(
M_PI_2)) ||
442 island_stitch_data[
i].num_rot_elements == 0 ||
443 island_stitch_data[
i].num_rot_elements_neg == 0)
445 rotation = (island_stitch_data[
i].rotation * island_stitch_data[
i].num_rot_elements -
446 island_stitch_data[
i].rotation_neg *
447 island_stitch_data[
i].num_rot_elements_neg) /
451 rotation = (island_stitch_data[
i].rotation * island_stitch_data[
i].num_rot_elements +
452 (2.0f *
float(
M_PI) - island_stitch_data[
i].rotation_neg) *
453 island_stitch_data[
i].num_rot_elements_neg) /
458 numOfIslandUVs =
state->element_map->island_total_uvs[
i];
460 for (j = 0; j < numOfIslandUVs; j++,
element++) {
462 if (!(
element->flag & STITCH_PROCESSED)) {
472 add_v2_v2(luv, island_stitch_data[
i].translation);
477 int face_preview_pos =
481 island_stitch_data[
i].medianPoint,
482 preview->preview_polys + face_preview_pos +
483 2 *
element->loop_of_face_index,
486 add_v2_v2(preview->preview_polys + face_preview_pos + 2 *
element->loop_of_face_index,
487 island_stitch_data[
i].translation);
491 element->flag &= STITCH_SELECTED;
499 StitchStateContainer *ssc,
501 UVVertAverage *uv_average,
502 const uint *uvfinal_map,
503 IslandStitchData *island_stitch_data)
506 float uv1[2], uv2[2];
507 float edgecos, edgesin;
511 element1 =
state->uvs[edge->uv1];
512 element2 =
state->uvs[edge->uv2];
517 if (ssc->mode == STITCH_VERT) {
518 index1 = uvfinal_map[element1 -
state->element_map->storage];
519 index2 = uvfinal_map[element2 -
state->element_map->storage];
528 uv1[0] = luv2[0] - luv1[0];
529 uv1[1] = luv2[1] - luv1[1];
531 uv1[1] /=
state->aspect;
533 uv2[0] = uv_average[index2].uv[0] - uv_average[index1].uv[0];
534 uv2[1] = uv_average[index2].uv[1] - uv_average[index1].uv[1];
536 uv2[1] /=
state->aspect;
545 if (edgesin > 0.0f) {
546 island_stitch_data[element1->
island].num_rot_elements++;
547 island_stitch_data[element1->
island].rotation += rotation;
550 island_stitch_data[element1->
island].num_rot_elements_neg++;
551 island_stitch_data[element1->
island].rotation_neg += rotation;
557 StitchStateContainer *ssc,
559 IslandStitchData *island_stitch_data)
561 float rotation = 0, rotation_neg = 0;
562 int rot_elem = 0, rot_elem_neg = 0;
564 if (
element->island == ssc->static_island && !ssc->midpoints) {
569 for (; element_iter; element_iter = element_iter->
next) {
576 if (!ssc->midpoints && element_iter->
island != ssc->static_island) {
580 int index_tmp1 = element_iter -
state->element_map->storage;
581 index_tmp1 =
state->map[index_tmp1];
583 index_tmp2 =
state->map[index_tmp2];
586 float edgecos =
dot_v2v2(normal,
state->normals + index_tmp1 * 2);
588 if (edgesin > 0.0f) {
599 if (ssc->midpoints) {
601 rotation_neg /= 2.0f;
603 island_stitch_data[
element->island].num_rot_elements += rot_elem;
604 island_stitch_data[
element->island].rotation += rotation;
605 island_stitch_data[
element->island].num_rot_elements_neg += rot_elem_neg;
606 island_stitch_data[
element->island].rotation_neg += rotation_neg;
612 if (
state->island_is_stitchable) {
615 if (
state->element_map) {
621 if (
state->selection_stack) {
624 if (
state->tris_per_island) {
630 if (
state->normals) {
637 state->stitch_preview =
nullptr;
638 if (
state->edge_hash) {
648 for (
uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
659 UvEdge *edges =
state->edges;
660 const int *map =
state->map;
662 for (
int i = 0;
i <
state->total_separate_edges;
i++) {
663 UvEdge *edge = edges +
i;
670 if (edge->flag & STITCH_BOUNDARY) {
676 UvEdge *last_set = edge;
681 for (; iter1; iter1 = iter1->
next) {
693 int index1 = map[iter1 - element_map->
storage];
694 int index2 = map[iter2 - element_map->
storage];
696 UvEdge *edge2, *eiter;
700 if (index1 > index2) {
701 std::swap(index1, index2);
704 edgetmp.uv1 = index1;
705 edgetmp.uv2 = index2;
711 for (eiter = edge; eiter; eiter = eiter->next) {
712 if (edge2 == eiter) {
721 last_set->next = edge2;
740 StitchStateContainer *ssc,
742 IslandStitchData *island_stitch_data)
745 for (; element_iter; element_iter = element_iter->
next) {
748 island_stitch_data[element_iter->
island].stitchableCandidate = 1;
749 island_stitch_data[
element->island].stitchableCandidate = 1;
750 element->flag |= STITCH_STITCHABLE_CANDIDATE;
758 StitchStateContainer *ssc,
760 IslandStitchData *island_stitch_data)
762 UvEdge *edge_iter = edge->first;
764 for (; edge_iter; edge_iter = edge_iter->next) {
766 island_stitch_data[edge_iter->element->island].stitchableCandidate = 1;
767 island_stitch_data[edge->element->island].stitchableCandidate = 1;
768 edge->flag |= STITCH_STITCHABLE_CANDIDATE;
775 StitchPreviewer *preview,
776 PreviewPosition *preview_position)
781 preview_position[index].data_position = preview->preview_uvs * 2;
782 preview_position[index].polycount_position = preview->num_polys++;
783 preview->preview_uvs += efa->
len;
789 StitchStateContainer *ssc,
791 IslandStitchData *island_stitch_data,
792 PreviewPosition *preview_position)
794 StitchPreviewer *preview =
state->stitch_preview;
797 if (ssc->snap_islands && !ssc->midpoints && ssc->static_island ==
element->island) {
801 if (ssc->snap_islands) {
802 island_stitch_data[
element->island].addedForPreview = 1;
814 StitchStateContainer *ssc,
816 IslandStitchData *island_stitch_data,
817 PreviewPosition *preview_position)
819 StitchPreviewer *preview =
state->stitch_preview;
822 if (ssc->states[ssc->active_object_index] !=
state) {
823 preview->num_unstitchable++;
828 for (; element_iter; element_iter = element_iter->
next) {
834 if ((element_iter->
island == ssc->static_island) ||
835 (
element->island == ssc->static_island))
837 element->flag |= STITCH_STITCHABLE;
838 preview->num_stitchable++;
840 element, ssc,
state, island_stitch_data, preview_position);
848 if (!(
element->flag & STITCH_STITCHABLE)) {
849 preview->num_unstitchable++;
855 StitchStateContainer *ssc,
857 IslandStitchData *island_stitch_data,
858 PreviewPosition *preview_position)
860 StitchPreviewer *preview =
state->stitch_preview;
863 if (ssc->states[ssc->active_object_index] !=
state) {
864 preview->num_unstitchable++;
868 UvEdge *edge_iter = edge->first;
870 for (; edge_iter; edge_iter = edge_iter->next) {
871 if (edge_iter == edge) {
875 if ((edge_iter->element->island == ssc->static_island) ||
876 (edge->element->island == ssc->static_island))
878 edge->flag |= STITCH_STITCHABLE;
879 preview->num_stitchable++;
881 state->uvs[edge->uv1], ssc,
state, island_stitch_data, preview_position);
883 state->uvs[edge->uv2], ssc,
state, island_stitch_data, preview_position);
890 if (!(edge->flag & STITCH_STITCHABLE)) {
891 preview->num_unstitchable++;
898 PreviewPosition *preview_position,
899 UVVertAverage *final_position,
900 StitchStateContainer *ssc,
905 StitchPreviewer *preview =
state->stitch_preview;
909 if (
element->flag & STITCH_STITCHABLE) {
918 element_iter->
flag |= STITCH_PROCESSED;
926 int face_preview_pos =
929 copy_v2_v2(preview->preview_polys + face_preview_pos +
931 final_position[index].uv);
936 if ((!ssc->snap_islands) ||
937 ((!ssc->midpoints) && (element_iter->
island == ssc->static_island)))
939 element_iter->
flag &= STITCH_SELECTED;
942 element_iter = element_iter->
next;
943 }
while (element_iter && !element_iter->
separate);
954 StitchPreviewer *preview;
955 IslandStitchData *island_stitch_data =
nullptr;
956 int previous_island = ssc->static_island;
960 UVVertAverage *final_position =
nullptr;
961 bool is_active_state = (
state == ssc->states[ssc->active_object_index]);
965 char stitch_midpoints = ssc->midpoints;
967 uint *uvfinal_map =
nullptr;
969 PreviewPosition *preview_position =
nullptr;
974 if (preview ==
nullptr) {
978 preview_position =
static_cast<PreviewPosition *
>(
979 MEM_mallocN(
bm->totface *
sizeof(*preview_position),
"stitch_face_preview_position"));
981 for (
i = 0;
i <
bm->totface;
i++) {
986 "stitch_island_data");
987 if (!island_stitch_data) {
998 for (
i = 0;
i <
state->selection_size;
i++) {
999 if (ssc->mode == STITCH_VERT) {
1004 UvEdge *edge = (UvEdge *)
state->selection_stack[
i];
1010 for (
int island_idx = 0; island_idx <
state->element_map->total_islands; island_idx++) {
1011 state->island_is_stitchable[island_idx] = island_stitch_data[island_idx].stitchableCandidate ?
1016 if (is_active_state) {
1018 ssc->static_island %=
state->element_map->total_islands;
1019 while (!(island_stitch_data[ssc->static_island].stitchableCandidate)) {
1020 ssc->static_island++;
1021 ssc->static_island %=
state->element_map->total_islands;
1024 if (ssc->static_island == previous_island) {
1030 for (
i = 0;
i <
state->selection_size;
i++) {
1031 if (ssc->mode == STITCH_VERT) {
1033 if (
element->flag & STITCH_STITCHABLE_CANDIDATE) {
1034 element->flag &= ~STITCH_STITCHABLE_CANDIDATE;
1036 cd_loop_uv_offset,
element, ssc,
state, island_stitch_data, preview_position);
1040 preview->num_unstitchable++;
1044 UvEdge *edge = (UvEdge *)
state->selection_stack[
i];
1045 if (edge->flag & STITCH_STITCHABLE_CANDIDATE) {
1046 edge->flag &= ~STITCH_STITCHABLE_CANDIDATE;
1048 cd_loop_uv_offset, edge, ssc,
state, island_stitch_data, preview_position);
1051 preview->num_unstitchable++;
1062 int stitchBufferIndex = 0, unstitchBufferIndex = 0;
1063 int preview_size = (ssc->mode == STITCH_VERT) ? 2 : 4;
1065 preview->preview_stitchable = (
float *)
MEM_mallocN(
1066 preview->num_stitchable *
sizeof(
float) * preview_size,
"stitch_preview_stitchable_data");
1067 preview->preview_unstitchable = (
float *)
MEM_mallocN(preview->num_unstitchable *
1068 sizeof(
float) * preview_size,
1069 "stitch_preview_unstitchable_data");
1072 if (!preview->preview_stitchable || !preview->preview_unstitchable) {
1077 if (ssc->mode == STITCH_VERT) {
1078 for (
i = 0;
i <
state->total_separate_uvs;
i++) {
1080 if (
element->flag & STITCH_STITCHABLE) {
1082 copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 2], luv);
1083 stitchBufferIndex++;
1085 else if (
element->flag & STITCH_SELECTED) {
1087 copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 2], luv);
1088 unstitchBufferIndex++;
1093 for (
i = 0;
i <
state->total_separate_edges;
i++) {
1094 UvEdge *edge =
state->edges +
i;
1098 if (edge->flag & STITCH_STITCHABLE) {
1100 copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4], luv);
1103 copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4 + 2], luv);
1105 stitchBufferIndex++;
1106 BLI_assert(stitchBufferIndex <= preview->num_stitchable);
1108 else if (edge->flag & STITCH_SELECTED) {
1110 copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4], luv);
1113 copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4 + 2], luv);
1115 unstitchBufferIndex++;
1116 BLI_assert(unstitchBufferIndex <= preview->num_unstitchable);
1122 if (ssc->states[ssc->active_object_index] !=
state) {
1132 if (ssc->snap_islands) {
1133 for (
i = 0;
i <
state->element_map->total_islands;
i++) {
1134 if (island_stitch_data[
i].addedForPreview) {
1135 int numOfIslandUVs =
state->element_map->island_total_uvs[
i];
1137 for (
int j = 0; j < numOfIslandUVs; j++,
element++) {
1152 uint buffer_index = 0;
1155 preview->preview_polys =
static_cast<float *
>(
1156 MEM_mallocN(
sizeof(
float[2]) * preview->preview_uvs,
"tri_uv_stitch_prev"));
1159 preview->static_tris =
static_cast<float *
>(
1160 MEM_mallocN((
sizeof(
float[6]) *
state->tris_per_island[ssc->static_island]),
1161 "static_island_preview_tris"));
1163 preview->num_static_tris =
state->tris_per_island[ssc->static_island];
1165 if (!preview->preview_polys) {
1176 int numoftris = efa->
len - 2;
1178 int face_preview_pos = preview_position[index].data_position;
1180 preview->uvs_per_polygon[preview_position[index].polycount_position] = efa->
len;
1183 copy_v2_v2(preview->preview_polys + face_preview_pos +
i * 2, luv);
1188 if (
element->island == ssc->static_island) {
1193 if (
i < numoftris) {
1199 memcpy(preview->static_tris + buffer_index, fuv,
sizeof(
float[2]));
1200 memcpy(preview->static_tris + buffer_index + 2, luv,
sizeof(
float[2]));
1201 memcpy(preview->static_tris + buffer_index + 4, luvnext,
sizeof(
float[2]));
1217 if (ssc->mode == STITCH_VERT) {
1218 final_position =
static_cast<UVVertAverage *
>(
1219 MEM_callocN(
state->selection_size *
sizeof(*final_position),
"stitch_uv_average"));
1220 uvfinal_map =
static_cast<uint *
>(
1221 MEM_mallocN(
state->element_map->total_uvs *
sizeof(*uvfinal_map),
"stitch_uv_final_map"));
1224 final_position =
static_cast<UVVertAverage *
>(
1225 MEM_callocN(
state->total_separate_uvs *
sizeof(*final_position),
"stitch_uv_average"));
1229 for (
i = 0;
i <
state->selection_size;
i++) {
1230 if (ssc->mode == STITCH_VERT) {
1233 if (
element->flag & STITCH_STITCHABLE) {
1240 final_position[
i].count = 1;
1242 if (ssc->snap_islands &&
element->island == ssc->static_island && !stitch_midpoints) {
1247 for (; element_iter; element_iter = element_iter->
next) {
1250 l = element_iter->
l;
1252 if (stitch_midpoints) {
1254 final_position[
i].count++;
1256 else if (element_iter->
island == ssc->static_island) {
1266 if (stitch_midpoints) {
1267 final_position[
i].uv[0] /= final_position[
i].count;
1268 final_position[
i].uv[1] /= final_position[
i].count;
1272 UvEdge *edge =
static_cast<UvEdge *
>(
state->selection_stack[
i]);
1274 if (edge->flag & STITCH_STITCHABLE) {
1279 l =
state->uvs[edge->uv1]->l;
1281 l =
state->uvs[edge->uv2]->l;
1284 copy_v2_v2(final_position[edge->uv1].uv, luv1);
1285 copy_v2_v2(final_position[edge->uv2].uv, luv2);
1286 final_position[edge->uv1].count = 1;
1287 final_position[edge->uv2].count = 1;
1289 state->uvs[edge->uv1]->flag |= STITCH_STITCHABLE;
1290 state->uvs[edge->uv2]->flag |= STITCH_STITCHABLE;
1292 if (ssc->snap_islands && edge->element->island == ssc->static_island && !stitch_midpoints)
1297 for (edge_iter = edge->first; edge_iter; edge_iter = edge_iter->next) {
1300 l =
state->uvs[edge_iter->uv1]->l;
1302 l =
state->uvs[edge_iter->uv2]->l;
1305 if (stitch_midpoints) {
1306 add_v2_v2(final_position[edge->uv1].uv, luv1);
1307 final_position[edge->uv1].count++;
1308 add_v2_v2(final_position[edge->uv2].uv, luv2);
1309 final_position[edge->uv2].count++;
1311 else if (edge_iter->element->island == ssc->static_island) {
1312 copy_v2_v2(final_position[edge->uv1].uv, luv1);
1313 copy_v2_v2(final_position[edge->uv2].uv, luv2);
1323 if (ssc->mode == STITCH_EDGE && stitch_midpoints) {
1324 for (
i = 0;
i <
state->total_separate_uvs;
i++) {
1325 final_position[
i].uv[0] /= final_position[
i].count;
1326 final_position[
i].uv[1] /= final_position[
i].count;
1331 if (ssc->snap_islands) {
1332 if (ssc->mode == STITCH_VERT) {
1333 for (
i = 0;
i <
state->selection_size;
i++) {
1336 if (
element->flag & STITCH_STITCHABLE) {
1346 island_stitch_data[
element->island].translation[0] += final_position[
i].uv[0] - luv[0];
1347 island_stitch_data[
element->island].translation[1] += final_position[
i].uv[1] - luv[1];
1348 island_stitch_data[
element->island].medianPoint[0] += luv[0];
1349 island_stitch_data[
element->island].medianPoint[1] += luv[1];
1350 island_stitch_data[
element->island].numOfElements++;
1355 for (
i = 0;
i <
state->total_separate_edges;
i++) {
1356 UvEdge *edge =
state->edges +
i;
1357 if ((edge->flag & STITCH_BOUNDARY) && (
state->uvs[edge->uv1]->flag & STITCH_STITCHABLE) &&
1358 (
state->uvs[edge->uv2]->flag & STITCH_STITCHABLE))
1366 island_stitch_data);
1367 island_stitch_data[
state->uvs[edge->uv1]->island].use_edge_rotation =
true;
1372 if (
final && ssc->clear_seams) {
1373 for (
i = 0;
i <
state->total_separate_edges;
i++) {
1374 UvEdge *edge =
state->edges +
i;
1375 if ((
state->uvs[edge->uv1]->flag & STITCH_STITCHABLE) &&
1376 (
state->uvs[edge->uv2]->flag & STITCH_STITCHABLE))
1383 for (
i = 0;
i <
state->selection_size;
i++) {
1385 if (!island_stitch_data[
element->island].use_edge_rotation) {
1386 if (
element->flag & STITCH_STITCHABLE) {
1388 cd_loop_uv_offset,
element, ssc,
state, island_stitch_data);
1394 for (
i = 0;
i <
state->total_separate_uvs;
i++) {
1397 if (
element->flag & STITCH_STITCHABLE) {
1407 island_stitch_data[
element->island].translation[0] += final_position[
i].uv[0] - luv[0];
1408 island_stitch_data[
element->island].translation[1] += final_position[
i].uv[1] - luv[1];
1409 island_stitch_data[
element->island].medianPoint[0] += luv[0];
1410 island_stitch_data[
element->island].medianPoint[1] += luv[1];
1411 island_stitch_data[
element->island].numOfElements++;
1415 for (
i = 0;
i <
state->selection_size;
i++) {
1416 UvEdge *edge =
static_cast<UvEdge *
>(
state->selection_stack[
i]);
1418 if (edge->flag & STITCH_STITCHABLE) {
1420 cd_loop_uv_offset, edge, ssc,
state, final_position,
nullptr, island_stitch_data);
1421 island_stitch_data[
state->uvs[edge->uv1]->island].use_edge_rotation =
true;
1426 if (
final && ssc->clear_seams) {
1427 for (
i = 0;
i <
state->selection_size;
i++) {
1428 UvEdge *edge =
static_cast<UvEdge *
>(
state->selection_stack[
i]);
1429 if (edge->flag & STITCH_STITCHABLE) {
1438 for (
i = 0;
i <
state->selection_size;
i++) {
1439 if (ssc->mode == STITCH_VERT) {
1443 scene,
element,
i, preview_position, final_position, ssc,
state,
final);
1446 UvEdge *edge =
static_cast<UvEdge *
>(
state->selection_stack[
i]);
1449 state->uvs[edge->uv1],
1457 state->uvs[edge->uv2],
1465 edge->flag &= (STITCH_SELECTED | STITCH_BOUNDARY);
1470 if (ssc->snap_islands) {
1472 cd_loop_uv_offset,
state, preview_position, preview, island_stitch_data,
final);
1476 if (ssc->mode == STITCH_VERT) {
1487 for (
uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
1499 const UvEdge *edge =
static_cast<const UvEdge *
>(key);
1506 const UvEdge *edge1 =
static_cast<const UvEdge *
>(a);
1507 const UvEdge *edge2 =
static_cast<const UvEdge *
>(
b);
1511 if ((edge1->uv1 == edge2->uv1) && (edge1->uv2 == edge2->uv2)) {
1521 UvEdge **selection_stack = (UvEdge **)
state->selection_stack;
1523 for (eiter = edge->first; eiter; eiter = eiter->next) {
1524 if (eiter->flag & STITCH_SELECTED) {
1526 if (always_select) {
1530 eiter->flag &= ~STITCH_SELECTED;
1531 for (
i = 0;
i <
state->selection_size;
i++) {
1532 if (selection_stack[
i] == eiter) {
1533 (
state->selection_size)--;
1534 selection_stack[
i] = selection_stack[
state->selection_size];
1540 eiter->flag |= STITCH_SELECTED;
1541 selection_stack[
state->selection_size++] = eiter;
1552 for (; element_iter; element_iter = element_iter->
next) {
1555 if (element_iter->
flag & STITCH_SELECTED) {
1557 if (always_select) {
1561 element_iter->
flag &= ~STITCH_SELECTED;
1562 for (
i = 0;
i <
state->selection_size;
i++) {
1563 if (selection_stack[
i] == element_iter) {
1564 (
state->selection_size)--;
1565 selection_stack[
i] = selection_stack[
state->selection_size];
1571 element_iter->
flag |= STITCH_SELECTED;
1572 selection_stack[
state->selection_size++] = element_iter;
1580 void **old_selection_stack =
state->selection_stack;
1581 int old_selection_size =
state->selection_size;
1582 state->selection_size = 0;
1584 if (from_stitch_mode == STITCH_VERT) {
1586 state->selection_stack =
static_cast<void **
>(
1588 "stitch_new_edge_selection_stack"));
1591 for (
i = 0;
i <
state->total_separate_edges;
i++) {
1592 UvEdge *edge =
state->edges +
i;
1596 if ((element1->
flag & STITCH_SELECTED) && (element2->
flag & STITCH_SELECTED)) {
1602 for (
i = 0;
i < old_selection_size;
i++) {
1605 element->flag &= ~STITCH_SELECTED;
1610 state->selection_stack =
static_cast<void **
>(
1612 "stitch_new_vert_selection_stack"));
1614 for (
i = 0;
i < old_selection_size;
i++) {
1615 UvEdge *edge =
static_cast<UvEdge *
>(old_selection_stack[
i]);
1622 edge->flag &= ~STITCH_SELECTED;
1630 for (
uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
1634 if (ssc->mode == STITCH_VERT) {
1635 ssc->mode = STITCH_EDGE;
1638 ssc->mode = STITCH_VERT;
1647 BMLoop *l1 = edge->element->l;
1655 tangent[1] /= aspect;
1657 normal[0] = tangent[1];
1658 normal[1] = -tangent[0];
1679 StitchStateContainer *ssc = (StitchStateContainer *)arg;
1681 for (
uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
1683 uint num_line = 0, num_tri, tri_idx = 0, line_idx = 0;
1684 StitchState *
state = ssc->states[ob_index];
1685 StitchPreviewer *stitch_preview =
state->stitch_preview;
1691 if (
format.attr_len == 0) {
1698 if (stitch_preview->static_tris) {
1702 for (
int i = 0;
i < stitch_preview->num_static_tris * 3;
i++) {
1709 if (stitch_preview->preview_polys) {
1710 for (
int i = 0;
i < stitch_preview->num_polys;
i++) {
1711 num_line += stitch_preview->uvs_per_polygon[
i];
1714 num_tri = num_line - 2 * stitch_preview->num_polys;
1723 for (
int i = 0;
i < stitch_preview->num_polys;
i++) {
1724 BLI_assert(stitch_preview->uvs_per_polygon[
i] >= 3);
1729 vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + 2]);
1731 for (j = 1; j < stitch_preview->uvs_per_polygon[
i] - 1; j++) {
1734 vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index + (j + 0) * 2]);
1736 vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index + (j + 1) * 2]);
1739 vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + (j + 0) * 2]);
1741 vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + (j + 1) * 2]);
1748 vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + j * 2]);
1750 index += stitch_preview->uvs_per_polygon[
i] * 2;
1762 if (ssc->mode == STITCH_VERT) {
1768 for (
int i = 0;
i < stitch_preview->num_stitchable;
i++) {
1776 for (
int i = 0;
i < stitch_preview->num_unstitchable;
i++) {
1785 for (
int i = 0;
i < stitch_preview->num_stitchable * 2;
i++) {
1793 for (
int i = 0;
i < stitch_preview->num_unstitchable * 2;
i++) {
1808 if (!element1 || !element2) {
1812 int uv1 =
state->map[element1 -
state->element_map->storage];
1813 int uv2 =
state->map[element2 -
state->element_map->storage];
1829 StitchStateContainer *ssc,
1831 StitchStateInit *state_init)
1855 state->obedit = obedit;
1865 if (!
state->element_map) {
1872 int unique_uvs =
state->element_map->total_unique_uvs;
1873 state->total_separate_uvs = unique_uvs;
1888 if (!
state->uvs || !map || !edge_hash || !all_edges) {
1925 int offset1 = map[itmp1];
1926 int offset2 = map[itmp2];
1928 all_edges[counter].next =
nullptr;
1929 all_edges[counter].first =
nullptr;
1930 all_edges[counter].flag = 0;
1931 all_edges[counter].element =
element;
1934 if (offset1 < offset2) {
1935 all_edges[counter].uv1 = offset1;
1936 all_edges[counter].uv2 = offset2;
1939 all_edges[counter].uv1 = offset2;
1940 all_edges[counter].uv2 = offset1;
1943 edge =
static_cast<UvEdge *
>(
BLI_ghash_lookup(edge_hash, &all_edges[counter]));
1949 all_edges[counter].flag = STITCH_BOUNDARY;
1964 state->total_separate_edges = total_edges;
1979 for (
i = 0;
i < total_edges;
i++) {
1991 for (
i = 0;
i < total_edges;
i++) {
1992 UvEdge *edge = edges +
i;
1994 if (edge->flag & STITCH_BOUNDARY) {
2007 state->selection_size = 0;
2010 if (state_init !=
nullptr) {
2011 int faceIndex, elementIndex;
2013 enum StitchModes stored_mode = StitchModes(
RNA_enum_get(op->
ptr,
"stored_mode"));
2017 int selected_count = state_init->uv_selected_count;
2019 if (stored_mode == STITCH_VERT) {
2020 state->selection_stack =
static_cast<void **
>(
2022 "uv_stitch_selection_stack"));
2024 while (selected_count--) {
2025 faceIndex = state_init->to_select[selected_count].faceIndex;
2026 elementIndex = state_init->to_select[selected_count].elementIndex;
2035 state->selection_stack =
static_cast<void **
>(
2037 "uv_stitch_selection_stack"));
2039 while (selected_count--) {
2040 UvEdge tmp_edge, *edge;
2042 faceIndex = state_init->to_select[selected_count].faceIndex;
2043 elementIndex = state_init->to_select[selected_count].elementIndex;
2072 if (ssc->mode != stored_mode) {
2077 if (ssc->mode == STITCH_VERT) {
2078 state->selection_stack =
static_cast<void **
>(
2080 "uv_stitch_selection_stack"));
2094 state->selection_stack =
static_cast<void **
>(
2096 "uv_stitch_selection_stack"));
2120 "stitch island tris");
2121 for (
i = 0;
i <
state->element_map->total_islands;
i++) {
2122 state->tris_per_island[
i] = 0;
2135 if (!
state->island_is_stitchable) {
2150 StitchState *active_state = ssc->states[ssc->active_object_index];
2151 StitchState *original_active_state = active_state;
2153 int original_island = ssc->static_island;
2156 ssc->static_island++;
2157 if (ssc->static_island >= active_state->element_map->
total_islands) {
2159 ssc->active_object_index++;
2160 ssc->active_object_index %= ssc->objects_len;
2162 active_state = ssc->states[ssc->active_object_index];
2163 ssc->static_island = 0;
2166 if (active_state->island_is_stitchable[ssc->static_island]) {
2170 }
while (!(active_state == original_active_state && ssc->static_island == original_island));
2188 scene, view_layer, v3d);
2198 "Stitching only works with less than %i objects selected (%i selected)",
2200 int(objects.
size()));
2213 ssc->active_object_index =
RNA_int_get(op->
ptr,
"active_object_index");
2214 ssc->static_island = 0;
2222 ssc->mode = STITCH_VERT;
2225 ssc->mode = STITCH_EDGE;
2230 ssc->mode = STITCH_VERT;
2233 ssc->mode = STITCH_EDGE;
2240 ssc->objects_len = 0;
2242 int *objs_selection_count =
nullptr;
2243 UvElementID *selected_uvs_arr =
nullptr;
2244 StitchStateInit *state_init =
nullptr;
2252 objs_selection_count =
static_cast<int *
>(
2253 MEM_mallocN(
sizeof(
int *) * objects.
size(),
"objects_selection_count"));
2256 int total_selected = 0;
2257 for (
uint ob_index = 0; ob_index < objects.
size(); ob_index++) {
2258 total_selected += objs_selection_count[ob_index];
2265 selected_uvs_arr[sel_idx].faceIndex =
RNA_int_get(&itemptr,
"face_index");
2266 selected_uvs_arr[sel_idx].elementIndex =
RNA_int_get(&itemptr,
"element_index");
2274 state_init->to_select = selected_uvs_arr;
2277 for (
uint ob_index = 0; ob_index < objects.
size(); ob_index++) {
2278 Object *obedit = objects[ob_index];
2280 if (state_init !=
nullptr) {
2281 state_init->uv_selected_count = objs_selection_count[ob_index];
2284 StitchState *stitch_state_ob =
stitch_init(
C, op, ssc, obedit, state_init);
2286 if (state_init !=
nullptr) {
2288 state_init->to_select += state_init->uv_selected_count;
2291 if (stitch_state_ob) {
2292 ssc->objects[ssc->objects_len] = obedit;
2293 ssc->states[ssc->objects_len] = stitch_state_ob;
2302 if (ssc->objects_len == 0) {
2308 ssc->active_object_index %= ssc->objects_len;
2312 StitchState *
state = ssc->states[ssc->active_object_index];
2313 ssc->static_island %=
state->element_map->total_islands;
2318 if (!
state->island_is_stitchable[ssc->static_island]) {
2320 state = ssc->states[ssc->active_object_index];
2346 StitchStateContainer *ssc = (StitchStateContainer *)op->
customdata;
2348 for (
uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
2349 StitchState *
state = ssc->states[ob_index];
2369 StitchStateContainer *ssc = (StitchStateContainer *)op->
customdata;
2379 RNA_int_set(op->
ptr,
"active_object_index", ssc->active_object_index);
2383 int *objs_selection_count =
nullptr;
2384 objs_selection_count =
static_cast<int *
>(
2385 MEM_mallocN(
sizeof(
int *) * ssc->objects_len,
"objects_selection_count"));
2391 for (
uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
2392 StitchState *
state = ssc->states[ob_index];
2396 for (
int i = 0;
i <
state->selection_size;
i++) {
2399 if (ssc->mode == STITCH_VERT) {
2412 objs_selection_count[ob_index] =
state->selection_size;
2430 for (
uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
2431 StitchState *
state = ssc->states[ob_index];
2471 StitchStateContainer *ssc)
2480 if (ssc->mode == STITCH_VERT) {
2487 StitchState *
state =
nullptr;
2488 for (
uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
2489 if (hit.
ob == ssc->objects[ob_index]) {
2490 state = ssc->states[ob_index];
2506 StitchState *
state =
nullptr;
2507 for (
uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
2508 if (hit.
ob == ssc->objects[ob_index]) {
2509 state = ssc->states[ob_index];
2525 StitchStateContainer *ssc;
2528 ssc =
static_cast<StitchStateContainer *
>(op->
customdata);
2529 StitchState *active_state = ssc->states[ssc->active_object_index];
2531 switch (event->
type) {
2558 ssc->limit_dist += 0.01f;
2572 ssc->limit_dist -= 0.01f;
2573 ssc->limit_dist = std::max(0.01f, ssc->limit_dist);
2587 ssc->use_limit = !ssc->use_limit;
2601 StitchState *new_active_state = ssc->states[ssc->active_object_index];
2604 if (active_state != new_active_state) {
2622 ssc->midpoints = !ssc->midpoints;
2637 StitchState *selected_state =
stitch_select(
C, scene, event, ssc);
2650 ssc->snap_islands = !ssc->snap_islands;
2689 {STITCH_VERT,
"VERTEX", 0,
"Vertex",
""},
2690 {STITCH_EDGE,
"EDGE", 0,
"Edge",
""},
2691 {0,
nullptr, 0,
nullptr,
nullptr},
2695 ot->name =
"Stitch";
2696 ot->description =
"Stitch selected UV vertices by proximity";
2697 ot->idname =
"UV_OT_stitch";
2709 ot->srna,
"use_limit",
false,
"Use Limit",
"Stitch UVs within a specified limit distance");
2714 "Snap islands together (on edge stitch mode, rotates the islands too)");
2722 "Limit distance in normalized coordinates",
2731 "Island that stays in place when stitching islands",
2735 "active_object_index",
2740 "Index of the active object",
2747 "UVs are stitched at midpoint instead of at static island");
2748 RNA_def_boolean(
ot->srna,
"clear_seams",
true,
"Clear Seams",
"Clear seams of stitched edges");
2754 "Use vertex or edge stitching");
2759 "Stored Operation Mode",
2760 "Use vertex or edge stitching");
2763 ot->srna,
"selection", &RNA_SelectedUvElement,
"Selection",
"");
2769 "objects_selection_count",
2774 "Objects Selection Count",
SpaceImage * CTX_wm_space_image(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
CustomData interface, see also DNA_customdata_types.h.
int CustomData_get_offset(const CustomData *data, eCustomDataType type)
BMEditMesh * BKE_editmesh_from_object(Object *ob)
Return the BMEditMesh for a given object.
blender::Vector< Object * > BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(const Scene *scene, ViewLayer *view_layer, const View3D *v3d)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
BLI_INLINE void * BLI_ghashIterator_getKey(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
unsigned int BLI_ghashutil_uinthash(unsigned int key)
#define GHASH_ITER(gh_iter_, ghash_)
GHash * BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
unsigned int BLI_ghash_len(const GHash *gh) ATTR_WARN_UNUSED_RESULT
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
void BLI_ghash_insert(GHash *gh, void *key, void *val)
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
void mul_v2_m2v2(float r[2], const float mat[2][2], const float vec[2])
void angle_to_mat2(float R[2][2], float angle)
MINLINE void sub_v2_v2(float r[2], const float a[2])
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void add_v2_v2(float r[2], const float a[2])
MINLINE void negate_v2_v2(float r[2], const float a[2])
MINLINE float cross_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE float dot_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v2(float n[2])
void DEG_id_tag_update(ID *id, unsigned int flags)
Object is a sort of wrapper for general info.
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)
UvElement * BM_uv_element_get_head(UvElementMap *element_map, UvElement *child)
void ED_workspace_status_text(bContext *C, const char *str)
void ED_region_tag_redraw(ARegion *region)
bool ED_operator_uvedit(bContext *C)
void * ED_region_draw_cb_activate(ARegionType *art, void(*draw)(const bContext *, ARegion *, void *), void *customdata, int type)
#define REGION_DRAW_POST_VIEW
bool ED_region_draw_cb_exit(ARegionType *art, void *handle)
bool uvedit_edge_select_test(const Scene *scene, const BMesh *bm, const BMLoop *l, const BMUVOffsets &offsets)
float ED_uvedit_get_aspect_y(Object *obedit)
bool uvedit_uv_select_test(const Scene *scene, const BMesh *bm, const BMLoop *l, const BMUVOffsets &offsets)
void uvedit_uv_select_enable(const Scene *scene, BMesh *bm, BMLoop *l)
void GPU_batch_discard(blender::gpu::Batch *batch)
void GPU_batch_program_set_builtin(blender::gpu::Batch *batch, GPUBuiltinShader shader_id)
blender::gpu::Batch * GPU_batch_create_ex(GPUPrimType primitive_type, blender::gpu::VertBuf *vertex_buf, blender::gpu::IndexBuf *index_buf, GPUBatchFlag owns_flag)
void GPU_batch_draw(blender::gpu::Batch *batch)
#define GPU_batch_uniform_4fv(batch, name, val)
@ GPU_SHADER_3D_UNIFORM_COLOR
void GPU_blend(GPUBlend blend)
void GPU_point_size(float size)
static blender::gpu::VertBuf * GPU_vertbuf_create_with_format(const GPUVertFormat &format)
void GPU_vertbuf_attr_set(blender::gpu::VertBuf *, uint a_idx, uint v_idx, const void *data)
void GPU_vertbuf_data_alloc(blender::gpu::VertBuf &verts, uint v_len)
Read Guarded memory(de)allocation.
#define RNA_BEGIN(sptr, itemptr, propname)
#define RNA_MAX_ARRAY_LENGTH
@ TH_STITCH_PREVIEW_UNSTITCHABLE
@ TH_STITCH_PREVIEW_ACTIVE
@ TH_STITCH_PREVIEW_STITCHABLE
void UI_GetThemeColor4fv(int colorid, float col[4])
float UI_GetThemeValuef(int colorid)
void UI_view2d_region_to_view(const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
#define BM_FACE_FIRST_LOOP(p)
#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_flag_test(ele, hflag)
void * BM_iter_at_index(BMesh *bm, const char itype, void *data, int index)
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
#define BM_ITER_ELEM_INDEX(ele, iter, data, itype, indexvar)
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
BLI_INLINE BMFace * BM_face_at_index(BMesh *bm, const int index)
ATTR_WARN_UNUSED_RESULT const void * element
ATTR_WARN_UNUSED_RESULT const BMLoop * l
BMUVOffsets BM_uv_map_offsets_get(const BMesh *bm)
struct @021025263243242147216143265077100330027142264337::@225245033123204053237120173316075113304004012000 batch
void * MEM_mallocN(size_t len, const char *str)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_callocN(size_t len, const char *str)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
void RNA_int_set_array(PointerRNA *ptr, const char *name, const int *values)
void RNA_int_get_array(PointerRNA *ptr, const char *name, int *values)
void RNA_collection_clear(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
void RNA_collection_add(PointerRNA *ptr, const char *name, PointerRNA *r_value)
int RNA_int_get(PointerRNA *ptr, const char *name)
float RNA_float_get(PointerRNA *ptr, const char *name)
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_int_array(StructOrFunctionRNA *cont_, const char *identifier, const int len, const int *default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_array(PropertyRNA *prop, int length)
PropertyRNA * RNA_def_collection_runtime(StructOrFunctionRNA *cont_, const char *identifier, StructRNA *type, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
static bool uv_edge_compare(const void *a, const void *b)
static uint uv_edge_hash(const void *key)
ARegionRuntimeHandle * runtime
struct ToolSettings * toolsettings
unsigned short loop_of_face_index
wmEventModifierFlag modifier
struct ReportList * reports
bool uv_find_nearest_vert_multi(Scene *scene, blender::Span< Object * > objects, const float co[2], float penalty_dist, UvNearestHit *hit)
UvNearestHit uv_nearest_hit_init_max(const View2D *v2d)
void uvedit_live_unwrap_update(SpaceImage *sima, Scene *scene, Object *obedit)
bool uv_find_nearest_edge_multi(Scene *scene, blender::Span< Object * > objects, const float co[2], float penalty, UvNearestHit *hit)
static int stitch_init_all(bContext *C, wmOperator *op)
static StitchState * stitch_init(bContext *C, wmOperator *op, StitchStateContainer *ssc, Object *obedit, StitchStateInit *state_init)
static void stitch_propagate_uv_final_position(Scene *scene, UvElement *element, int index, PreviewPosition *preview_position, UVVertAverage *final_position, StitchStateContainer *ssc, StitchState *state, const bool final)
static void stitch_switch_selection_mode_all(StitchStateContainer *ssc)
static void stitch_select_edge(UvEdge *edge, StitchState *state, int always_select)
static bool stitch_check_uvs_state_stitchable(const int cd_loop_uv_offset, UvElement *element, UvElement *element_iter, StitchStateContainer *ssc)
static wmOperatorStatus stitch_exec(bContext *C, wmOperator *op)
static void stitch_exit(bContext *C, wmOperator *op, int finished)
static void stitch_draw_vbo(blender::gpu::VertBuf *vbo, GPUPrimType prim_type, const float col[4])
void UV_OT_stitch(wmOperatorType *ot)
static void stitch_island_calculate_vert_rotation(const int cd_loop_uv_offset, UvElement *element, StitchStateContainer *ssc, StitchState *state, IslandStitchData *island_stitch_data)
static void determine_uv_stitchability(const int cd_loop_uv_offset, UvElement *element, StitchStateContainer *ssc, StitchState *state, IslandStitchData *island_stitch_data)
static void stitch_draw(const bContext *, ARegion *, void *arg)
static void stitch_update_header(StitchStateContainer *ssc, bContext *C)
static int stitch_process_data_all(StitchStateContainer *ssc, Scene *scene, int final)
static void stitch_validate_edge_stitchability(const int cd_loop_uv_offset, UvEdge *edge, StitchStateContainer *ssc, StitchState *state, IslandStitchData *island_stitch_data, PreviewPosition *preview_position)
static bool stitch_check_edges_state_stitchable(const int cd_loop_uv_offset, UvEdge *edge, UvEdge *edge_iter, StitchStateContainer *ssc, StitchState *state)
static void stitch_uv_edge_generate_linked_edges(GHash *edge_hash, StitchState *state)
static bool uv_edge_compare(const void *a, const void *b)
static void state_delete_all(StitchStateContainer *ssc)
static void stitch_island_calculate_edge_rotation(const int cd_loop_uv_offset, UvEdge *edge, StitchStateContainer *ssc, StitchState *state, UVVertAverage *uv_average, const uint *uvfinal_map, IslandStitchData *island_stitch_data)
static void stitch_validate_uv_stitchability(const int cd_loop_uv_offset, UvElement *element, StitchStateContainer *ssc, StitchState *state, IslandStitchData *island_stitch_data, PreviewPosition *preview_position)
static void stitch_set_face_preview_buffer_position(BMFace *efa, StitchPreviewer *preview, PreviewPosition *preview_position)
static wmOperatorStatus stitch_invoke(bContext *C, wmOperator *op, const wmEvent *)
static void stitch_uv_rotate(const float mat[2][2], const float medianPoint[2], float uv[2], float aspect)
static void stitch_calculate_edge_normal(const int cd_loop_uv_offset, UvEdge *edge, float *normal, float aspect)
static StitchState * stitch_select(bContext *C, Scene *scene, const wmEvent *event, StitchStateContainer *ssc)
static void stitch_cancel(bContext *C, wmOperator *op)
static wmOperatorStatus stitch_modal(bContext *C, wmOperator *op, const wmEvent *event)
static bool goto_next_island(StitchStateContainer *ssc)
static UvEdge * uv_edge_get(BMLoop *l, StitchState *state)
static bool stitch_check_uvs_stitchable(const int cd_loop_uv_offset, UvElement *element, UvElement *element_iter, StitchStateContainer *ssc)
static uint uv_edge_hash(const void *key)
#define STITCH_NO_PREVIEW
static void stitch_preview_delete(StitchPreviewer *stitch_preview)
static bool stitch_check_edges_stitchable(const int cd_loop_uv_offset, UvEdge *edge, UvEdge *edge_iter, StitchStateContainer *ssc, StitchState *state)
static void stitch_setup_face_preview_for_uv_group(UvElement *element, StitchStateContainer *ssc, StitchState *state, IslandStitchData *island_stitch_data, PreviewPosition *preview_position)
static void determine_uv_edge_stitchability(const int cd_loop_uv_offset, UvEdge *edge, StitchStateContainer *ssc, StitchState *state, IslandStitchData *island_stitch_data)
static void stitch_set_selection_mode(StitchState *state, const char from_stitch_mode)
static void state_delete(StitchState *state)
static void stitch_select_uv(UvElement *element, StitchState *state, int always_select)
static int stitch_process_data(StitchStateContainer *ssc, StitchState *state, Scene *scene, int final)
static void stitch_calculate_island_snapping(const int cd_loop_uv_offset, StitchState *state, PreviewPosition *preview_position, StitchPreviewer *preview, IslandStitchData *island_stitch_data, int final)
static StitchPreviewer * stitch_preview_init()
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)