12#include <fmt/format.h>
49#include "RNA_prototypes.hh"
66struct StitchPreviewer {
70 uint *uvs_per_polygon;
75 float *preview_stitchable;
76 float *preview_unstitchable;
79 uint num_unstitchable;
86struct IslandStitchData;
93struct IslandStitchData {
101 int num_rot_elements;
102 int num_rot_elements_neg;
104 char addedForPreview;
106 char stitchableCandidate;
108 bool use_edge_rotation;
112struct UVVertAverage {
146 UvElementMap *element_map;
160 bool *island_is_stitchable;
163 int total_separate_edges;
164 int total_separate_uvs;
166 void **selection_stack;
170 uint *tris_per_island;
172 StitchPreviewer *stitch_preview;
176struct StitchStateContainer {
197 StitchState **states;
199 int active_object_index;
202struct PreviewPosition {
204 int polycount_position;
211 STITCH_STITCHABLE = 2,
212 STITCH_PROCESSED = 4,
214 STITCH_STITCHABLE_CANDIDATE = 16,
217#define STITCH_NO_PREVIEW -1
231struct StitchStateInit {
232 int uv_selected_count;
233 UvElementID *to_select;
241 StitchPreviewer *stitch_preview;
244 stitch_preview->preview_polys =
nullptr;
245 stitch_preview->preview_stitchable =
nullptr;
246 stitch_preview->preview_unstitchable =
nullptr;
247 stitch_preview->uvs_per_polygon =
nullptr;
249 stitch_preview->preview_uvs = 0;
250 stitch_preview->num_polys = 0;
251 stitch_preview->num_stitchable = 0;
252 stitch_preview->num_unstitchable = 0;
254 stitch_preview->static_tris =
nullptr;
256 stitch_preview->num_static_tris = 0;
258 return stitch_preview;
264 if (stitch_preview) {
278 status.
item(
IFACE_(
"Confirm"), ICON_MOUSE_LMB);
279 status.
item(
IFACE_(
"Cancel"), ICON_EVENT_ESC);
280 status.
item(fmt::format(
"{} {}",
282 (ssc->mode == STITCH_VERT ?
IFACE_(
"Vertices") :
IFACE_(
"Edges"))),
285 status.
item(fmt::format(
"{} : {}",
287 (ssc->mode == STITCH_VERT ?
IFACE_(
"Vertex") :
IFACE_(
"Edge"))),
289 status.
item(
IFACE_(
"Switch Island"), ICON_EVENT_I);
293 if (ssc->use_limit) {
294 status.
item(fmt::format(
"{} ({:.2f})",
IFACE_(
"Limit Distance"), ssc->limit_dist),
296 ICON_MOUSE_MMB_SCROLL);
301 const float medianPoint[2],
305 float uv_rotation_result[2];
321 StitchStateContainer *ssc)
329 limit = ssc->limit_dist;
331 if (ssc->use_limit) {
339 if (
fabsf(luv[0] - luv_iter[0]) < limit &&
fabsf(luv[1] - luv_iter[1]) < limit) {
350 StitchStateContainer *ssc,
355 if (edge_iter == edge) {
359 limit = ssc->limit_dist;
361 if (ssc->use_limit) {
368 if (
fabsf(luv_orig1[0] - luv_iter1[0]) < limit &&
fabsf(luv_orig1[1] - luv_iter1[1]) < limit &&
369 fabsf(luv_orig2[0] - luv_iter2[0]) < limit &&
fabsf(luv_orig2[1] - luv_iter2[1]) < limit)
381 StitchStateContainer *ssc)
383 if ((ssc->snap_islands &&
element->island == element_iter->
island) ||
384 (!ssc->midpoints &&
element->island == element_iter->
island))
395 StitchStateContainer *ssc,
398 if ((ssc->snap_islands && edge->element->island == edge_iter->element->island) ||
399 (!ssc->midpoints && edge->element->island == edge_iter->element->island))
410 PreviewPosition *preview_position,
411 StitchPreviewer *preview,
412 IslandStitchData *island_stitch_data,
417 for (
int i = 0;
i <
state->element_map->total_islands;
i++) {
418 if (island_stitch_data[
i].addedForPreview) {
419 int numOfIslandUVs = 0, j;
420 int totelem = island_stitch_data[
i].num_rot_elements_neg +
421 island_stitch_data[
i].num_rot_elements;
423 float rotation_mat[2][2];
426 if (island_stitch_data[
i].num_rot_elements > 1) {
427 island_stitch_data[
i].rotation /= island_stitch_data[
i].num_rot_elements;
430 if (island_stitch_data[
i].num_rot_elements_neg > 1) {
431 island_stitch_data[
i].rotation_neg /= island_stitch_data[
i].num_rot_elements_neg;
434 if (island_stitch_data[
i].numOfElements > 1) {
435 island_stitch_data[
i].medianPoint[0] /= island_stitch_data[
i].numOfElements;
436 island_stitch_data[
i].medianPoint[1] /= island_stitch_data[
i].numOfElements;
438 island_stitch_data[
i].translation[0] /= island_stitch_data[
i].numOfElements;
439 island_stitch_data[
i].translation[1] /= island_stitch_data[
i].numOfElements;
442 island_stitch_data[
i].medianPoint[1] /=
state->aspect;
443 if ((island_stitch_data[
i].rotation + island_stitch_data[
i].rotation_neg <
float(
M_PI_2)) ||
444 island_stitch_data[
i].num_rot_elements == 0 ||
445 island_stitch_data[
i].num_rot_elements_neg == 0)
447 rotation = (island_stitch_data[
i].rotation * island_stitch_data[
i].num_rot_elements -
448 island_stitch_data[
i].rotation_neg *
449 island_stitch_data[
i].num_rot_elements_neg) /
453 rotation = (island_stitch_data[
i].rotation * island_stitch_data[
i].num_rot_elements +
454 (2.0f * float(
M_PI) - island_stitch_data[
i].rotation_neg) *
455 island_stitch_data[
i].num_rot_elements_neg) /
460 numOfIslandUVs =
state->element_map->island_total_uvs[
i];
462 for (j = 0; j < numOfIslandUVs; j++,
element++) {
464 if (!(
element->flag & STITCH_PROCESSED)) {
474 add_v2_v2(luv, island_stitch_data[
i].translation);
479 int face_preview_pos =
483 island_stitch_data[
i].medianPoint,
484 preview->preview_polys + face_preview_pos +
485 2 *
element->loop_of_face_index,
488 add_v2_v2(preview->preview_polys + face_preview_pos + 2 *
element->loop_of_face_index,
489 island_stitch_data[
i].translation);
493 element->flag &= STITCH_SELECTED;
501 StitchStateContainer *ssc,
503 UVVertAverage *uv_average,
504 const uint *uvfinal_map,
505 IslandStitchData *island_stitch_data)
508 float uv1[2], uv2[2];
509 float edgecos, edgesin;
513 element1 =
state->uvs[edge->uv1];
514 element2 =
state->uvs[edge->uv2];
519 if (ssc->mode == STITCH_VERT) {
520 index1 = uvfinal_map[element1 -
state->element_map->storage];
521 index2 = uvfinal_map[element2 -
state->element_map->storage];
530 uv1[0] = luv2[0] - luv1[0];
531 uv1[1] = luv2[1] - luv1[1];
533 uv1[1] /=
state->aspect;
535 uv2[0] = uv_average[index2].uv[0] - uv_average[index1].uv[0];
536 uv2[1] = uv_average[index2].uv[1] - uv_average[index1].uv[1];
538 uv2[1] /=
state->aspect;
547 if (edgesin > 0.0f) {
548 island_stitch_data[element1->
island].num_rot_elements++;
549 island_stitch_data[element1->
island].rotation += rotation;
552 island_stitch_data[element1->
island].num_rot_elements_neg++;
553 island_stitch_data[element1->
island].rotation_neg += rotation;
559 StitchStateContainer *ssc,
561 IslandStitchData *island_stitch_data)
563 float rotation = 0, rotation_neg = 0;
564 int rot_elem = 0, rot_elem_neg = 0;
566 if (
element->island == ssc->static_island && !ssc->midpoints) {
571 for (; element_iter; element_iter = element_iter->
next) {
578 if (!ssc->midpoints && element_iter->
island != ssc->static_island) {
582 int index_tmp1 = element_iter -
state->element_map->storage;
583 index_tmp1 =
state->map[index_tmp1];
585 index_tmp2 =
state->map[index_tmp2];
588 float edgecos =
dot_v2v2(normal,
state->normals + index_tmp1 * 2);
590 if (edgesin > 0.0f) {
601 if (ssc->midpoints) {
603 rotation_neg /= 2.0f;
605 island_stitch_data[
element->island].num_rot_elements += rot_elem;
606 island_stitch_data[
element->island].rotation += rotation;
607 island_stitch_data[
element->island].num_rot_elements_neg += rot_elem_neg;
608 island_stitch_data[
element->island].rotation_neg += rotation_neg;
614 if (
state->island_is_stitchable) {
617 if (
state->element_map) {
623 if (
state->selection_stack) {
626 if (
state->tris_per_island) {
632 if (
state->normals) {
639 state->stitch_preview =
nullptr;
640 if (
state->edge_hash) {
650 for (
uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
661 UvEdge *edges =
state->edges;
662 const int *map =
state->map;
664 for (
int i = 0;
i <
state->total_separate_edges;
i++) {
665 UvEdge *edge = edges +
i;
672 if (edge->flag & STITCH_BOUNDARY) {
678 UvEdge *last_set = edge;
683 for (; iter1; iter1 = iter1->
next) {
695 int index1 = map[iter1 - element_map->
storage];
696 int index2 = map[iter2 - element_map->
storage];
698 UvEdge *edge2, *eiter;
702 if (index1 > index2) {
703 std::swap(index1, index2);
706 edgetmp.uv1 = index1;
707 edgetmp.uv2 = index2;
713 for (eiter = edge; eiter; eiter = eiter->next) {
714 if (edge2 == eiter) {
723 last_set->next = edge2;
742 StitchStateContainer *ssc,
744 IslandStitchData *island_stitch_data)
747 for (; element_iter; element_iter = element_iter->
next) {
750 island_stitch_data[element_iter->
island].stitchableCandidate = 1;
751 island_stitch_data[
element->island].stitchableCandidate = 1;
752 element->flag |= STITCH_STITCHABLE_CANDIDATE;
760 StitchStateContainer *ssc,
762 IslandStitchData *island_stitch_data)
764 UvEdge *edge_iter = edge->first;
766 for (; edge_iter; edge_iter = edge_iter->next) {
768 island_stitch_data[edge_iter->element->island].stitchableCandidate = 1;
769 island_stitch_data[edge->element->island].stitchableCandidate = 1;
770 edge->flag |= STITCH_STITCHABLE_CANDIDATE;
777 StitchPreviewer *preview,
778 PreviewPosition *preview_position)
783 preview_position[index].data_position = preview->preview_uvs * 2;
784 preview_position[index].polycount_position = preview->num_polys++;
785 preview->preview_uvs += efa->
len;
791 StitchStateContainer *ssc,
793 IslandStitchData *island_stitch_data,
794 PreviewPosition *preview_position)
796 StitchPreviewer *preview =
state->stitch_preview;
799 if (ssc->snap_islands && !ssc->midpoints && ssc->static_island ==
element->island) {
803 if (ssc->snap_islands) {
804 island_stitch_data[
element->island].addedForPreview = 1;
816 StitchStateContainer *ssc,
818 IslandStitchData *island_stitch_data,
819 PreviewPosition *preview_position)
821 StitchPreviewer *preview =
state->stitch_preview;
824 if (ssc->states[ssc->active_object_index] !=
state) {
825 preview->num_unstitchable++;
830 for (; element_iter; element_iter = element_iter->
next) {
836 if ((element_iter->
island == ssc->static_island) ||
837 (
element->island == ssc->static_island))
839 element->flag |= STITCH_STITCHABLE;
840 preview->num_stitchable++;
842 element, ssc,
state, island_stitch_data, preview_position);
850 if (!(
element->flag & STITCH_STITCHABLE)) {
851 preview->num_unstitchable++;
857 StitchStateContainer *ssc,
859 IslandStitchData *island_stitch_data,
860 PreviewPosition *preview_position)
862 StitchPreviewer *preview =
state->stitch_preview;
865 if (ssc->states[ssc->active_object_index] !=
state) {
866 preview->num_unstitchable++;
870 UvEdge *edge_iter = edge->first;
872 for (; edge_iter; edge_iter = edge_iter->next) {
873 if (edge_iter == edge) {
877 if ((edge_iter->element->island == ssc->static_island) ||
878 (edge->element->island == ssc->static_island))
880 edge->flag |= STITCH_STITCHABLE;
881 preview->num_stitchable++;
883 state->uvs[edge->uv1], ssc,
state, island_stitch_data, preview_position);
885 state->uvs[edge->uv2], ssc,
state, island_stitch_data, preview_position);
892 if (!(edge->flag & STITCH_STITCHABLE)) {
893 preview->num_unstitchable++;
900 PreviewPosition *preview_position,
901 UVVertAverage *final_position,
902 StitchStateContainer *ssc,
907 StitchPreviewer *preview =
state->stitch_preview;
911 if (
element->flag & STITCH_STITCHABLE) {
920 element_iter->
flag |= STITCH_PROCESSED;
928 int face_preview_pos =
931 copy_v2_v2(preview->preview_polys + face_preview_pos +
933 final_position[index].uv);
938 if ((!ssc->snap_islands) ||
939 ((!ssc->midpoints) && (element_iter->
island == ssc->static_island)))
941 element_iter->
flag &= STITCH_SELECTED;
944 element_iter = element_iter->
next;
945 }
while (element_iter && !element_iter->
separate);
956 StitchPreviewer *preview;
957 IslandStitchData *island_stitch_data =
nullptr;
958 int previous_island = ssc->static_island;
962 UVVertAverage *final_position =
nullptr;
963 bool is_active_state = (
state == ssc->states[ssc->active_object_index]);
967 char stitch_midpoints = ssc->midpoints;
969 uint *uvfinal_map =
nullptr;
971 PreviewPosition *preview_position =
nullptr;
976 if (preview ==
nullptr) {
980 preview_position =
static_cast<PreviewPosition *
>(
981 MEM_mallocN(
bm->totface *
sizeof(*preview_position),
"stitch_face_preview_position"));
983 for (
i = 0;
i <
bm->totface;
i++) {
988 "stitch_island_data");
989 if (!island_stitch_data) {
1000 for (
i = 0;
i <
state->selection_size;
i++) {
1001 if (ssc->mode == STITCH_VERT) {
1006 UvEdge *edge = (UvEdge *)
state->selection_stack[
i];
1012 for (
int island_idx = 0; island_idx <
state->element_map->total_islands; island_idx++) {
1013 state->island_is_stitchable[island_idx] = island_stitch_data[island_idx].stitchableCandidate ?
1018 if (is_active_state) {
1020 ssc->static_island %=
state->element_map->total_islands;
1021 while (!(island_stitch_data[ssc->static_island].stitchableCandidate)) {
1022 ssc->static_island++;
1023 ssc->static_island %=
state->element_map->total_islands;
1026 if (ssc->static_island == previous_island) {
1032 for (
i = 0;
i <
state->selection_size;
i++) {
1033 if (ssc->mode == STITCH_VERT) {
1035 if (
element->flag & STITCH_STITCHABLE_CANDIDATE) {
1036 element->flag &= ~STITCH_STITCHABLE_CANDIDATE;
1038 cd_loop_uv_offset,
element, ssc,
state, island_stitch_data, preview_position);
1042 preview->num_unstitchable++;
1046 UvEdge *edge = (UvEdge *)
state->selection_stack[
i];
1047 if (edge->flag & STITCH_STITCHABLE_CANDIDATE) {
1048 edge->flag &= ~STITCH_STITCHABLE_CANDIDATE;
1050 cd_loop_uv_offset, edge, ssc,
state, island_stitch_data, preview_position);
1053 preview->num_unstitchable++;
1064 int stitchBufferIndex = 0, unstitchBufferIndex = 0;
1065 int preview_size = (ssc->mode == STITCH_VERT) ? 2 : 4;
1067 preview->preview_stitchable = (
float *)
MEM_mallocN(
1068 preview->num_stitchable *
sizeof(
float) * preview_size,
"stitch_preview_stitchable_data");
1069 preview->preview_unstitchable = (
float *)
MEM_mallocN(preview->num_unstitchable *
1070 sizeof(
float) * preview_size,
1071 "stitch_preview_unstitchable_data");
1074 if (!preview->preview_stitchable || !preview->preview_unstitchable) {
1079 if (ssc->mode == STITCH_VERT) {
1080 for (
i = 0;
i <
state->total_separate_uvs;
i++) {
1082 if (
element->flag & STITCH_STITCHABLE) {
1084 copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 2], luv);
1085 stitchBufferIndex++;
1087 else if (
element->flag & STITCH_SELECTED) {
1089 copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 2], luv);
1090 unstitchBufferIndex++;
1095 for (
i = 0;
i <
state->total_separate_edges;
i++) {
1096 UvEdge *edge =
state->edges +
i;
1100 if (edge->flag & STITCH_STITCHABLE) {
1102 copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4], luv);
1105 copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4 + 2], luv);
1107 stitchBufferIndex++;
1108 BLI_assert(stitchBufferIndex <= preview->num_stitchable);
1110 else if (edge->flag & STITCH_SELECTED) {
1112 copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4], luv);
1115 copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4 + 2], luv);
1117 unstitchBufferIndex++;
1118 BLI_assert(unstitchBufferIndex <= preview->num_unstitchable);
1124 if (ssc->states[ssc->active_object_index] !=
state) {
1134 if (ssc->snap_islands) {
1135 for (
i = 0;
i <
state->element_map->total_islands;
i++) {
1136 if (island_stitch_data[
i].addedForPreview) {
1137 int numOfIslandUVs =
state->element_map->island_total_uvs[
i];
1139 for (
int j = 0; j < numOfIslandUVs; j++,
element++) {
1154 uint buffer_index = 0;
1157 preview->preview_polys =
static_cast<float *
>(
1158 MEM_mallocN(
sizeof(
float[2]) * preview->preview_uvs,
"tri_uv_stitch_prev"));
1161 preview->static_tris =
static_cast<float *
>(
1162 MEM_mallocN((
sizeof(
float[6]) *
state->tris_per_island[ssc->static_island]),
1163 "static_island_preview_tris"));
1165 preview->num_static_tris =
state->tris_per_island[ssc->static_island];
1167 if (!preview->preview_polys) {
1178 int numoftris = efa->
len - 2;
1180 int face_preview_pos = preview_position[index].data_position;
1182 preview->uvs_per_polygon[preview_position[index].polycount_position] = efa->
len;
1185 copy_v2_v2(preview->preview_polys + face_preview_pos +
i * 2, luv);
1190 if (
element->island == ssc->static_island) {
1195 if (
i < numoftris) {
1201 memcpy(preview->static_tris + buffer_index, fuv,
sizeof(
float[2]));
1202 memcpy(preview->static_tris + buffer_index + 2, luv,
sizeof(
float[2]));
1203 memcpy(preview->static_tris + buffer_index + 4, luvnext,
sizeof(
float[2]));
1219 if (ssc->mode == STITCH_VERT) {
1220 final_position =
static_cast<UVVertAverage *
>(
1221 MEM_callocN(
state->selection_size *
sizeof(*final_position),
"stitch_uv_average"));
1222 uvfinal_map =
static_cast<uint *
>(
1223 MEM_mallocN(
state->element_map->total_uvs *
sizeof(*uvfinal_map),
"stitch_uv_final_map"));
1226 final_position =
static_cast<UVVertAverage *
>(
1227 MEM_callocN(
state->total_separate_uvs *
sizeof(*final_position),
"stitch_uv_average"));
1231 for (
i = 0;
i <
state->selection_size;
i++) {
1232 if (ssc->mode == STITCH_VERT) {
1235 if (
element->flag & STITCH_STITCHABLE) {
1242 final_position[
i].count = 1;
1244 if (ssc->snap_islands &&
element->island == ssc->static_island && !stitch_midpoints) {
1249 for (; element_iter; element_iter = element_iter->
next) {
1252 l = element_iter->
l;
1254 if (stitch_midpoints) {
1256 final_position[
i].count++;
1258 else if (element_iter->
island == ssc->static_island) {
1268 if (stitch_midpoints) {
1269 final_position[
i].uv[0] /= final_position[
i].count;
1270 final_position[
i].uv[1] /= final_position[
i].count;
1274 UvEdge *edge =
static_cast<UvEdge *
>(
state->selection_stack[
i]);
1276 if (edge->flag & STITCH_STITCHABLE) {
1281 l =
state->uvs[edge->uv1]->l;
1283 l =
state->uvs[edge->uv2]->l;
1286 copy_v2_v2(final_position[edge->uv1].uv, luv1);
1287 copy_v2_v2(final_position[edge->uv2].uv, luv2);
1288 final_position[edge->uv1].count = 1;
1289 final_position[edge->uv2].count = 1;
1291 state->uvs[edge->uv1]->flag |= STITCH_STITCHABLE;
1292 state->uvs[edge->uv2]->flag |= STITCH_STITCHABLE;
1294 if (ssc->snap_islands && edge->element->island == ssc->static_island && !stitch_midpoints)
1299 for (edge_iter = edge->first; edge_iter; edge_iter = edge_iter->next) {
1302 l =
state->uvs[edge_iter->uv1]->l;
1304 l =
state->uvs[edge_iter->uv2]->l;
1307 if (stitch_midpoints) {
1308 add_v2_v2(final_position[edge->uv1].uv, luv1);
1309 final_position[edge->uv1].count++;
1310 add_v2_v2(final_position[edge->uv2].uv, luv2);
1311 final_position[edge->uv2].count++;
1313 else if (edge_iter->element->island == ssc->static_island) {
1314 copy_v2_v2(final_position[edge->uv1].uv, luv1);
1315 copy_v2_v2(final_position[edge->uv2].uv, luv2);
1325 if (ssc->mode == STITCH_EDGE && stitch_midpoints) {
1326 for (
i = 0;
i <
state->total_separate_uvs;
i++) {
1327 final_position[
i].uv[0] /= final_position[
i].count;
1328 final_position[
i].uv[1] /= final_position[
i].count;
1333 if (ssc->snap_islands) {
1334 if (ssc->mode == STITCH_VERT) {
1335 for (
i = 0;
i <
state->selection_size;
i++) {
1338 if (
element->flag & STITCH_STITCHABLE) {
1348 island_stitch_data[
element->island].translation[0] += final_position[
i].uv[0] - luv[0];
1349 island_stitch_data[
element->island].translation[1] += final_position[
i].uv[1] - luv[1];
1350 island_stitch_data[
element->island].medianPoint[0] += luv[0];
1351 island_stitch_data[
element->island].medianPoint[1] += luv[1];
1352 island_stitch_data[
element->island].numOfElements++;
1357 for (
i = 0;
i <
state->total_separate_edges;
i++) {
1358 UvEdge *edge =
state->edges +
i;
1359 if ((edge->flag & STITCH_BOUNDARY) && (
state->uvs[edge->uv1]->flag & STITCH_STITCHABLE) &&
1360 (
state->uvs[edge->uv2]->flag & STITCH_STITCHABLE))
1368 island_stitch_data);
1369 island_stitch_data[
state->uvs[edge->uv1]->island].use_edge_rotation =
true;
1374 if (
final && ssc->clear_seams) {
1375 for (
i = 0;
i <
state->total_separate_edges;
i++) {
1376 UvEdge *edge =
state->edges +
i;
1377 if ((
state->uvs[edge->uv1]->flag & STITCH_STITCHABLE) &&
1378 (
state->uvs[edge->uv2]->flag & STITCH_STITCHABLE))
1385 for (
i = 0;
i <
state->selection_size;
i++) {
1387 if (!island_stitch_data[
element->island].use_edge_rotation) {
1388 if (
element->flag & STITCH_STITCHABLE) {
1390 cd_loop_uv_offset,
element, ssc,
state, island_stitch_data);
1396 for (
i = 0;
i <
state->total_separate_uvs;
i++) {
1399 if (
element->flag & STITCH_STITCHABLE) {
1409 island_stitch_data[
element->island].translation[0] += final_position[
i].uv[0] - luv[0];
1410 island_stitch_data[
element->island].translation[1] += final_position[
i].uv[1] - luv[1];
1411 island_stitch_data[
element->island].medianPoint[0] += luv[0];
1412 island_stitch_data[
element->island].medianPoint[1] += luv[1];
1413 island_stitch_data[
element->island].numOfElements++;
1417 for (
i = 0;
i <
state->selection_size;
i++) {
1418 UvEdge *edge =
static_cast<UvEdge *
>(
state->selection_stack[
i]);
1420 if (edge->flag & STITCH_STITCHABLE) {
1422 cd_loop_uv_offset, edge, ssc,
state, final_position,
nullptr, island_stitch_data);
1423 island_stitch_data[
state->uvs[edge->uv1]->island].use_edge_rotation =
true;
1428 if (
final && ssc->clear_seams) {
1429 for (
i = 0;
i <
state->selection_size;
i++) {
1430 UvEdge *edge =
static_cast<UvEdge *
>(
state->selection_stack[
i]);
1431 if (edge->flag & STITCH_STITCHABLE) {
1440 for (
i = 0;
i <
state->selection_size;
i++) {
1441 if (ssc->mode == STITCH_VERT) {
1445 scene,
element,
i, preview_position, final_position, ssc,
state,
final);
1448 UvEdge *edge =
static_cast<UvEdge *
>(
state->selection_stack[
i]);
1451 state->uvs[edge->uv1],
1459 state->uvs[edge->uv2],
1467 edge->flag &= (STITCH_SELECTED | STITCH_BOUNDARY);
1472 if (ssc->snap_islands) {
1474 cd_loop_uv_offset,
state, preview_position, preview, island_stitch_data,
final);
1478 if (ssc->mode == STITCH_VERT) {
1489 for (
uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
1501 const UvEdge *edge =
static_cast<const UvEdge *
>(key);
1508 const UvEdge *edge1 =
static_cast<const UvEdge *
>(a);
1509 const UvEdge *edge2 =
static_cast<const UvEdge *
>(
b);
1513 if ((edge1->uv1 == edge2->uv1) && (edge1->uv2 == edge2->uv2)) {
1523 UvEdge **selection_stack = (UvEdge **)
state->selection_stack;
1525 for (eiter = edge->first; eiter; eiter = eiter->next) {
1526 if (eiter->flag & STITCH_SELECTED) {
1528 if (always_select) {
1532 eiter->flag &= ~STITCH_SELECTED;
1533 for (
i = 0;
i <
state->selection_size;
i++) {
1534 if (selection_stack[
i] == eiter) {
1535 (
state->selection_size)--;
1536 selection_stack[
i] = selection_stack[
state->selection_size];
1542 eiter->flag |= STITCH_SELECTED;
1543 selection_stack[
state->selection_size++] = eiter;
1554 for (; element_iter; element_iter = element_iter->
next) {
1557 if (element_iter->
flag & STITCH_SELECTED) {
1559 if (always_select) {
1563 element_iter->
flag &= ~STITCH_SELECTED;
1564 for (
i = 0;
i <
state->selection_size;
i++) {
1565 if (selection_stack[
i] == element_iter) {
1566 (
state->selection_size)--;
1567 selection_stack[
i] = selection_stack[
state->selection_size];
1573 element_iter->
flag |= STITCH_SELECTED;
1574 selection_stack[
state->selection_size++] = element_iter;
1582 void **old_selection_stack =
state->selection_stack;
1583 int old_selection_size =
state->selection_size;
1584 state->selection_size = 0;
1586 if (from_stitch_mode == STITCH_VERT) {
1588 state->selection_stack =
static_cast<void **
>(
1590 "stitch_new_edge_selection_stack"));
1593 for (
i = 0;
i <
state->total_separate_edges;
i++) {
1594 UvEdge *edge =
state->edges +
i;
1598 if ((element1->
flag & STITCH_SELECTED) && (element2->
flag & STITCH_SELECTED)) {
1604 for (
i = 0;
i < old_selection_size;
i++) {
1607 element->flag &= ~STITCH_SELECTED;
1612 state->selection_stack =
static_cast<void **
>(
1614 "stitch_new_vert_selection_stack"));
1616 for (
i = 0;
i < old_selection_size;
i++) {
1617 UvEdge *edge =
static_cast<UvEdge *
>(old_selection_stack[
i]);
1624 edge->flag &= ~STITCH_SELECTED;
1632 for (
uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
1636 if (ssc->mode == STITCH_VERT) {
1637 ssc->mode = STITCH_EDGE;
1640 ssc->mode = STITCH_VERT;
1649 BMLoop *l1 = edge->element->l;
1657 tangent[1] /= aspect;
1659 normal[0] = tangent[1];
1660 normal[1] = -tangent[0];
1681 StitchStateContainer *ssc = (StitchStateContainer *)arg;
1683 for (
uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
1685 uint num_line = 0, num_tri, tri_idx = 0, line_idx = 0;
1686 StitchState *
state = ssc->states[ob_index];
1687 StitchPreviewer *stitch_preview =
state->stitch_preview;
1693 if (
format.attr_len == 0) {
1700 if (stitch_preview->static_tris) {
1704 for (
int i = 0;
i < stitch_preview->num_static_tris * 3;
i++) {
1711 if (stitch_preview->preview_polys) {
1712 for (
int i = 0;
i < stitch_preview->num_polys;
i++) {
1713 num_line += stitch_preview->uvs_per_polygon[
i];
1716 num_tri = num_line - 2 * stitch_preview->num_polys;
1725 for (
int i = 0;
i < stitch_preview->num_polys;
i++) {
1726 BLI_assert(stitch_preview->uvs_per_polygon[
i] >= 3);
1731 vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + 2]);
1733 for (j = 1; j < stitch_preview->uvs_per_polygon[
i] - 1; j++) {
1736 vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index + (j + 0) * 2]);
1738 vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index + (j + 1) * 2]);
1741 vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + (j + 0) * 2]);
1743 vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + (j + 1) * 2]);
1750 vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + j * 2]);
1752 index += stitch_preview->uvs_per_polygon[
i] * 2;
1764 if (ssc->mode == STITCH_VERT) {
1770 for (
int i = 0;
i < stitch_preview->num_stitchable;
i++) {
1778 for (
int i = 0;
i < stitch_preview->num_unstitchable;
i++) {
1787 for (
int i = 0;
i < stitch_preview->num_stitchable * 2;
i++) {
1795 for (
int i = 0;
i < stitch_preview->num_unstitchable * 2;
i++) {
1810 if (!element1 || !element2) {
1814 int uv1 =
state->map[element1 -
state->element_map->storage];
1815 int uv2 =
state->map[element2 -
state->element_map->storage];
1831 StitchStateContainer *ssc,
1833 StitchStateInit *state_init)
1857 state->obedit = obedit;
1867 if (!
state->element_map) {
1874 int unique_uvs =
state->element_map->total_unique_uvs;
1875 state->total_separate_uvs = unique_uvs;
1890 if (!
state->uvs || !map || !edge_hash || !all_edges) {
1927 int offset1 = map[itmp1];
1928 int offset2 = map[itmp2];
1930 all_edges[counter].next =
nullptr;
1931 all_edges[counter].first =
nullptr;
1932 all_edges[counter].flag = 0;
1933 all_edges[counter].element =
element;
1936 if (offset1 < offset2) {
1937 all_edges[counter].uv1 = offset1;
1938 all_edges[counter].uv2 = offset2;
1941 all_edges[counter].uv1 = offset2;
1942 all_edges[counter].uv2 = offset1;
1945 edge =
static_cast<UvEdge *
>(
BLI_ghash_lookup(edge_hash, &all_edges[counter]));
1951 all_edges[counter].flag = STITCH_BOUNDARY;
1966 state->total_separate_edges = total_edges;
1981 for (
i = 0;
i < total_edges;
i++) {
1993 for (
i = 0;
i < total_edges;
i++) {
1994 UvEdge *edge = edges +
i;
1996 if (edge->flag & STITCH_BOUNDARY) {
2009 state->selection_size = 0;
2012 if (state_init !=
nullptr) {
2013 int faceIndex, elementIndex;
2015 enum StitchModes stored_mode = StitchModes(
RNA_enum_get(op->
ptr,
"stored_mode"));
2019 int selected_count = state_init->uv_selected_count;
2021 if (stored_mode == STITCH_VERT) {
2022 state->selection_stack =
static_cast<void **
>(
2024 "uv_stitch_selection_stack"));
2026 while (selected_count--) {
2027 faceIndex = state_init->to_select[selected_count].faceIndex;
2028 elementIndex = state_init->to_select[selected_count].elementIndex;
2037 state->selection_stack =
static_cast<void **
>(
2039 "uv_stitch_selection_stack"));
2041 while (selected_count--) {
2042 UvEdge tmp_edge, *edge;
2044 faceIndex = state_init->to_select[selected_count].faceIndex;
2045 elementIndex = state_init->to_select[selected_count].elementIndex;
2074 if (ssc->mode != stored_mode) {
2079 if (ssc->mode == STITCH_VERT) {
2080 state->selection_stack =
static_cast<void **
>(
2082 "uv_stitch_selection_stack"));
2096 state->selection_stack =
static_cast<void **
>(
2098 "uv_stitch_selection_stack"));
2122 "stitch island tris");
2123 for (
i = 0;
i <
state->element_map->total_islands;
i++) {
2124 state->tris_per_island[
i] = 0;
2137 if (!
state->island_is_stitchable) {
2152 StitchState *active_state = ssc->states[ssc->active_object_index];
2153 StitchState *original_active_state = active_state;
2155 int original_island = ssc->static_island;
2158 ssc->static_island++;
2159 if (ssc->static_island >= active_state->element_map->
total_islands) {
2161 ssc->active_object_index++;
2162 ssc->active_object_index %= ssc->objects_len;
2164 active_state = ssc->states[ssc->active_object_index];
2165 ssc->static_island = 0;
2168 if (active_state->island_is_stitchable[ssc->static_island]) {
2172 }
while (!(active_state == original_active_state && ssc->static_island == original_island));
2190 scene, view_layer, v3d);
2200 "Stitching only works with less than %i objects selected (%i selected)",
2202 int(objects.
size()));
2215 ssc->active_object_index =
RNA_int_get(op->
ptr,
"active_object_index");
2216 ssc->static_island = 0;
2224 ssc->mode = STITCH_VERT;
2227 ssc->mode = STITCH_EDGE;
2232 ssc->mode = STITCH_VERT;
2235 ssc->mode = STITCH_EDGE;
2242 ssc->objects_len = 0;
2244 int *objs_selection_count =
nullptr;
2245 UvElementID *selected_uvs_arr =
nullptr;
2246 StitchStateInit *state_init =
nullptr;
2254 objs_selection_count =
static_cast<int *
>(
2255 MEM_mallocN(
sizeof(
int *) * objects.
size(),
"objects_selection_count"));
2258 int total_selected = 0;
2259 for (
uint ob_index = 0; ob_index < objects.
size(); ob_index++) {
2260 total_selected += objs_selection_count[ob_index];
2267 selected_uvs_arr[sel_idx].faceIndex =
RNA_int_get(&itemptr,
"face_index");
2268 selected_uvs_arr[sel_idx].elementIndex =
RNA_int_get(&itemptr,
"element_index");
2276 state_init->to_select = selected_uvs_arr;
2279 for (
uint ob_index = 0; ob_index < objects.
size(); ob_index++) {
2280 Object *obedit = objects[ob_index];
2282 if (state_init !=
nullptr) {
2283 state_init->uv_selected_count = objs_selection_count[ob_index];
2286 StitchState *stitch_state_ob =
stitch_init(
C, op, ssc, obedit, state_init);
2288 if (state_init !=
nullptr) {
2290 state_init->to_select += state_init->uv_selected_count;
2293 if (stitch_state_ob) {
2294 ssc->objects[ssc->objects_len] = obedit;
2295 ssc->states[ssc->objects_len] = stitch_state_ob;
2304 if (ssc->objects_len == 0) {
2310 ssc->active_object_index %= ssc->objects_len;
2314 StitchState *
state = ssc->states[ssc->active_object_index];
2315 ssc->static_island %=
state->element_map->total_islands;
2320 if (!
state->island_is_stitchable[ssc->static_island]) {
2322 state = ssc->states[ssc->active_object_index];
2348 StitchStateContainer *ssc = (StitchStateContainer *)op->
customdata;
2350 for (
uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
2351 StitchState *
state = ssc->states[ob_index];
2371 StitchStateContainer *ssc = (StitchStateContainer *)op->
customdata;
2381 RNA_int_set(op->
ptr,
"active_object_index", ssc->active_object_index);
2385 int *objs_selection_count =
nullptr;
2386 objs_selection_count =
static_cast<int *
>(
2387 MEM_mallocN(
sizeof(
int *) * ssc->objects_len,
"objects_selection_count"));
2393 for (
uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
2394 StitchState *
state = ssc->states[ob_index];
2398 for (
int i = 0;
i <
state->selection_size;
i++) {
2401 if (ssc->mode == STITCH_VERT) {
2414 objs_selection_count[ob_index] =
state->selection_size;
2432 for (
uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
2433 StitchState *
state = ssc->states[ob_index];
2473 StitchStateContainer *ssc)
2482 if (ssc->mode == STITCH_VERT) {
2489 StitchState *
state =
nullptr;
2490 for (
uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
2491 if (hit.
ob == ssc->objects[ob_index]) {
2492 state = ssc->states[ob_index];
2508 StitchState *
state =
nullptr;
2509 for (
uint ob_index = 0; ob_index < ssc->objects_len; ob_index++) {
2510 if (hit.
ob == ssc->objects[ob_index]) {
2511 state = ssc->states[ob_index];
2527 StitchStateContainer *ssc;
2530 ssc =
static_cast<StitchStateContainer *
>(op->
customdata);
2531 StitchState *active_state = ssc->states[ssc->active_object_index];
2533 switch (event->
type) {
2560 ssc->limit_dist += 0.01f;
2574 ssc->limit_dist -= 0.01f;
2575 ssc->limit_dist = std::max(0.01f, ssc->limit_dist);
2589 ssc->use_limit = !ssc->use_limit;
2603 StitchState *new_active_state = ssc->states[ssc->active_object_index];
2606 if (active_state != new_active_state) {
2624 ssc->midpoints = !ssc->midpoints;
2639 StitchState *selected_state =
stitch_select(
C, scene, event, ssc);
2652 ssc->snap_islands = !ssc->snap_islands;
2691 {STITCH_VERT,
"VERTEX", 0,
"Vertex",
""},
2692 {STITCH_EDGE,
"EDGE", 0,
"Edge",
""},
2693 {0,
nullptr, 0,
nullptr,
nullptr},
2697 ot->name =
"Stitch";
2698 ot->description =
"Stitch selected UV vertices by proximity";
2699 ot->idname =
"UV_OT_stitch";
2711 ot->srna,
"use_limit",
false,
"Use Limit",
"Stitch UVs within a specified limit distance");
2716 "Snap islands together (on edge stitch mode, rotates the islands too)");
2724 "Limit distance in normalized coordinates",
2733 "Island that stays in place when stitching islands",
2737 "active_object_index",
2742 "Index of the active object",
2749 "UVs are stitched at midpoint instead of at static island");
2750 RNA_def_boolean(
ot->srna,
"clear_seams",
true,
"Clear Seams",
"Clear seams of stitched edges");
2756 "Use vertex or edge stitching");
2761 "Stored Operation Mode",
2762 "Use vertex or edge stitching");
2765 ot->srna,
"selection", &RNA_SelectedUvElement,
"Selection",
"");
2771 "objects_selection_count",
2776 "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)
float ED_uvedit_get_aspect_y(Object *obedit)
void uvedit_uv_select_enable(const Scene *scene, BMesh *bm, BMLoop *l, const BMUVOffsets &offsets)
bool uvedit_uv_select_test(const Scene *scene, const BMLoop *l, const BMUVOffsets &offsets)
bool uvedit_edge_select_test(const Scene *scene, const BMLoop *l, const BMUVOffsets &offsets)
blender::gpu::Batch * GPU_batch_create_ex(GPUPrimType primitive_type, blender::gpu::VertBuf *vertex_buf, blender::gpu::IndexBuf *index_buf, eGPUBatchFlag owns_flag)
void GPU_batch_discard(blender::gpu::Batch *batch)
void GPU_batch_program_set_builtin(blender::gpu::Batch *batch, eGPUBuiltinShader shader_id)
void GPU_batch_draw(blender::gpu::Batch *batch)
#define GPU_batch_uniform_4fv(batch, name, val)
@ GPU_SHADER_3D_UNIFORM_COLOR
void GPU_blend(eGPUBlend blend)
void GPU_point_size(float size)
#define GPU_vertbuf_create_with_format(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)
void item_bool(std::string text, bool inverted, int icon1, int icon2=0)
void item(std::string text, int icon1, int icon2=0)
struct @064345207361167251075330302113175271221317160336::@113254110077376341056327177062323111323010325277 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)