159
201
#define STITCH_NO_PREVIEW -1
161
/* previewer stuff (see uvedit_intern.h for more info) */
162
static StitchPreviewer *_stitch_preview;
164
208
/* constructor */
165
209
static StitchPreviewer *stitch_preview_init(void)
167
_stitch_preview = MEM_mallocN(sizeof(StitchPreviewer), "stitch_previewer");
168
_stitch_preview->preview_polys = NULL;
169
_stitch_preview->preview_stitchable = NULL;
170
_stitch_preview->preview_unstitchable = NULL;
171
_stitch_preview->uvs_per_polygon = NULL;
173
_stitch_preview->preview_uvs = 0;
174
_stitch_preview->num_polys = 0;
175
_stitch_preview->num_stitchable = 0;
176
_stitch_preview->num_unstitchable = 0;
178
_stitch_preview->static_tris = NULL;
180
_stitch_preview->num_static_tris = 0;
182
return _stitch_preview;
211
StitchPreviewer *stitch_preview;
213
stitch_preview = MEM_mallocN(sizeof(StitchPreviewer), "stitch_previewer");
214
stitch_preview->preview_polys = NULL;
215
stitch_preview->preview_stitchable = NULL;
216
stitch_preview->preview_unstitchable = NULL;
217
stitch_preview->uvs_per_polygon = NULL;
219
stitch_preview->preview_uvs = 0;
220
stitch_preview->num_polys = 0;
221
stitch_preview->num_stitchable = 0;
222
stitch_preview->num_unstitchable = 0;
224
stitch_preview->static_tris = NULL;
226
stitch_preview->num_static_tris = 0;
228
return stitch_preview;
185
231
/* destructor...yeah this should be C++ :) */
186
static void stitch_preview_delete(void)
232
static void stitch_preview_delete(StitchPreviewer *stitch_preview)
188
if (_stitch_preview) {
189
if (_stitch_preview->preview_polys) {
190
MEM_freeN(_stitch_preview->preview_polys);
191
_stitch_preview->preview_polys = NULL;
193
if (_stitch_preview->uvs_per_polygon) {
194
MEM_freeN(_stitch_preview->uvs_per_polygon);
195
_stitch_preview->uvs_per_polygon = NULL;
197
if (_stitch_preview->preview_stitchable) {
198
MEM_freeN(_stitch_preview->preview_stitchable);
199
_stitch_preview->preview_stitchable = NULL;
201
if (_stitch_preview->preview_unstitchable) {
202
MEM_freeN(_stitch_preview->preview_unstitchable);
203
_stitch_preview->preview_unstitchable = NULL;
205
if (_stitch_preview->static_tris) {
206
MEM_freeN(_stitch_preview->static_tris);
207
_stitch_preview->static_tris = NULL;
210
MEM_freeN(_stitch_preview);
211
_stitch_preview = NULL;
234
if (stitch_preview) {
235
if (stitch_preview->preview_polys) {
236
MEM_freeN(stitch_preview->preview_polys);
237
stitch_preview->preview_polys = NULL;
239
if (stitch_preview->uvs_per_polygon) {
240
MEM_freeN(stitch_preview->uvs_per_polygon);
241
stitch_preview->uvs_per_polygon = NULL;
243
if (stitch_preview->preview_stitchable) {
244
MEM_freeN(stitch_preview->preview_stitchable);
245
stitch_preview->preview_stitchable = NULL;
247
if (stitch_preview->preview_unstitchable) {
248
MEM_freeN(stitch_preview->preview_unstitchable);
249
stitch_preview->preview_unstitchable = NULL;
251
if (stitch_preview->static_tris) {
252
MEM_freeN(stitch_preview->static_tris);
253
stitch_preview->static_tris = NULL;
255
MEM_freeN(stitch_preview);
216
/* "getter method" */
217
StitchPreviewer *uv_get_stitch_previewer(void)
219
return _stitch_preview;
222
259
#define HEADER_LENGTH 256
224
261
/* This function updates the header of the UV editor when the stitch tool updates its settings */
225
static void stitch_update_header(StitchState *stitch_state, bContext *C)
262
static void stitch_update_header(StitchState *state, bContext *C)
227
static char str[] = "(S)nap %s, (M)idpoints %s, (L)imit %.2f (Alt Wheel adjust) %s, Switch (I)sland, shift select vertices";
264
static char str[] = "Mode(TAB) %s, (S)nap %s, (M)idpoints %s, (L)imit %.2f (Alt Wheel adjust) %s, Switch (I)sland, shift select vertices";
229
266
char msg[HEADER_LENGTH];
230
267
ScrArea *sa = CTX_wm_area(C);
233
270
BLI_snprintf(msg, HEADER_LENGTH, str,
234
stitch_state->snap_islands ? "On" : "Off",
235
stitch_state->midpoints ? "On" : "Off",
236
stitch_state->limit_dist,
237
stitch_state->use_limit ? "On" : "Off");
271
state->mode == STITCH_VERT ? "Vertex" : "Edge",
272
state->snap_islands ? "On" : "Off",
273
state->midpoints ? "On" : "Off",
275
state->use_limit ? "On" : "Off");
239
277
ED_area_headerprint(sa, msg);
253
static void stitch_uv_rotate(float rotation, float medianPoint[2], float uv[2])
291
static void stitch_uv_rotate(float mat[2][2], float medianPoint[2], float uv[2], float aspect)
255
293
float uv_rotation_result[2];
257
uv[0] -= medianPoint[0];
258
uv[1] -= medianPoint[1];
260
uv_rotation_result[0] = cos(rotation) * uv[0] - sin(rotation) * uv[1];
261
uv_rotation_result[1] = sin(rotation) * uv[0] + cos(rotation) * uv[1];
263
uv[0] = uv_rotation_result[0] + medianPoint[0];
264
uv[1] = uv_rotation_result[1] + medianPoint[1];
297
sub_v2_v2(uv, medianPoint);
298
mul_v2_m2v2(uv_rotation_result, mat, uv);
299
add_v2_v2v2(uv, uv_rotation_result, medianPoint);
304
/* check if two uvelements are stitchable. This should only operate on -different- separate UvElements */
267
305
static int stitch_check_uvs_stitchable(UvElement *element, UvElement *element_iter, StitchState *state)
272
309
if (element_iter == element) {
276
313
limit = state->limit_dist;
277
do_limit = state->use_limit;
280
MLoopUV *luv_orig, *luv_iter;
281
BMLoop *l_orig, *l_iter;
285
luv_orig = CustomData_bmesh_get(&state->em->bm->ldata, l_orig->head.data, CD_MLOOPUV);
286
l_iter = element_iter->l;
287
luv_iter = CustomData_bmesh_get(&state->em->bm->ldata, l_iter->head.data, CD_MLOOPUV);
289
if (fabs(luv_orig->uv[0] - luv_iter->uv[0]) < limit &&
290
fabs(luv_orig->uv[1] - luv_iter->uv[1]) < limit)
315
if (state->use_limit) {
316
MLoopUV *luv, *luv_iter;
321
luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
323
luv_iter = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
325
if (fabsf(luv->uv[0] - luv_iter->uv[0]) < limit &&
326
fabsf(luv->uv[1] - luv_iter->uv[1]) < limit)
339
static int stitch_check_edges_stitchable(UvEdge *edge, UvEdge *edge_iter, StitchState *state)
343
if (edge_iter == edge) {
347
limit = state->limit_dist;
349
if (state->use_limit) {
351
MLoopUV *luv_orig1, *luv_iter1;
352
MLoopUV *luv_orig2, *luv_iter2;
354
l = state->uvs[edge->uv1]->l;
355
luv_orig1 = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
356
l = state->uvs[edge_iter->uv1]->l;
357
luv_iter1 = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
359
l = state->uvs[edge->uv2]->l;
360
luv_orig2 = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
361
l = state->uvs[edge_iter->uv2]->l;
362
luv_iter2 = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
364
if (fabsf(luv_orig1->uv[0] - luv_iter1->uv[0]) < limit &&
365
fabsf(luv_orig1->uv[1] - luv_iter1->uv[1]) < limit &&
366
fabsf(luv_orig2->uv[0] - luv_iter2->uv[0]) < limit &&
367
fabsf(luv_orig2->uv[1] - luv_iter2->uv[1]) < limit)
304
380
static int stitch_check_uvs_state_stitchable(UvElement *element, UvElement *element_iter, StitchState *state)
392
static int stitch_check_edges_state_stitchable(UvEdge *edge, UvEdge *edge_iter, StitchState *state)
394
if ((state->snap_islands && edge->element->island == edge_iter->element->island) ||
395
(!state->midpoints && edge->element->island == edge_iter->element->island))
400
return stitch_check_edges_stitchable(edge, edge_iter, state);
316
403
/* calculate snapping for islands */
317
404
static void stitch_calculate_island_snapping(StitchState *state, PreviewPosition *preview_position, StitchPreviewer *preview, IslandStitchData *island_stitch_data, int final)
320
407
UvElement *element;
322
for (i = 0; i < state->element_map->totalIslands; i++) {
409
for (i = 0; i < state->element_map->totalIslands; i++) {
323
410
if (island_stitch_data[i].addedForPreview) {
324
411
int numOfIslandUVs = 0, j;
412
int totelem = island_stitch_data[i].num_rot_elements_neg + island_stitch_data[i].num_rot_elements;
414
float rotation_mat[2][2];
326
416
/* check to avoid divide by 0 */
327
if (island_stitch_data[i].num_rot_elements > 0) {
417
if (island_stitch_data[i].num_rot_elements > 1)
328
418
island_stitch_data[i].rotation /= island_stitch_data[i].num_rot_elements;
420
if (island_stitch_data[i].num_rot_elements_neg > 1)
421
island_stitch_data[i].rotation_neg /= island_stitch_data[i].num_rot_elements_neg;
423
if (island_stitch_data[i].numOfElements > 1) {
329
424
island_stitch_data[i].medianPoint[0] /= island_stitch_data[i].numOfElements;
330
425
island_stitch_data[i].medianPoint[1] /= island_stitch_data[i].numOfElements;
332
island_stitch_data[i].translation[0] /= island_stitch_data[i].numOfElements;
333
island_stitch_data[i].translation[1] /= island_stitch_data[i].numOfElements;
427
island_stitch_data[i].translation[0] /= island_stitch_data[i].numOfElements;
428
island_stitch_data[i].translation[1] /= island_stitch_data[i].numOfElements;
431
island_stitch_data[i].medianPoint[1] /= state->aspect;
432
if ((island_stitch_data[i].rotation + island_stitch_data[i].rotation_neg < (float)M_PI_2) ||
433
island_stitch_data[i].num_rot_elements == 0 || island_stitch_data[i].num_rot_elements_neg == 0)
435
rotation = (island_stitch_data[i].rotation * island_stitch_data[i].num_rot_elements -
436
island_stitch_data[i].rotation_neg *
437
island_stitch_data[i].num_rot_elements_neg) / totelem;
440
rotation = (island_stitch_data[i].rotation * island_stitch_data[i].num_rot_elements +
441
(2.0f * (float)M_PI - island_stitch_data[i].rotation_neg) *
442
island_stitch_data[i].num_rot_elements_neg) / totelem;
445
rotate_m2(rotation_mat, rotation);
334
446
numOfIslandUVs = getNumOfIslandUvs(state->element_map, i);
335
447
element = &state->element_map->buf[state->element_map->islandIndices[i]];
336
448
for (j = 0; j < numOfIslandUVs; j++, element++) {
376
489
int index1, index2;
378
491
MLoopUV *luv1, *luv2;
381
493
element1 = state->uvs[edge->uv1];
382
494
element2 = state->uvs[edge->uv2];
385
luv1 = CustomData_bmesh_get(&state->em->bm->ldata, l1->head.data, CD_MLOOPUV);
387
luv2 = CustomData_bmesh_get(&state->em->bm->ldata, l2->head.data, CD_MLOOPUV);
389
index1 = uvfinal_map[element1 - state->element_map->buf];
390
index2 = uvfinal_map[element2 - state->element_map->buf];
496
luv1 = CustomData_bmesh_get(&state->em->bm->ldata, element1->l->head.data, CD_MLOOPUV);
497
luv2 = CustomData_bmesh_get(&state->em->bm->ldata, element2->l->head.data, CD_MLOOPUV);
499
if (state->mode == STITCH_VERT) {
500
index1 = uvfinal_map[element1 - state->element_map->buf];
501
index2 = uvfinal_map[element2 - state->element_map->buf];
392
507
/* the idea here is to take the directions of the edges and find the rotation between final and initial
393
508
* direction. This, using inner and outer vector products, gives the angle. Directions are differences so... */
394
509
uv1[0] = luv2->uv[0] - luv1->uv[0];
395
510
uv1[1] = luv2->uv[1] - luv1->uv[1];
512
uv1[1] /= state->aspect;
397
514
uv2[0] = uv_average[index2].uv[0] - uv_average[index1].uv[0];
398
515
uv2[1] = uv_average[index2].uv[1] - uv_average[index1].uv[1];
517
uv2[1] /= state->aspect;
400
519
normalize_v2(uv1);
401
520
normalize_v2(uv2);
403
edgecos = uv1[0] * uv2[0] + uv1[1] * uv2[1];
404
edgesin = uv1[0] * uv2[1] - uv2[0] * uv1[1];
406
rotation = (edgesin > 0) ? acos(MAX2(-1.0, MIN2(1.0, edgecos))) : -acos(MAX2(-1.0, MIN2(1.0, edgecos)));
408
island_stitch_data[element1->island].num_rot_elements++;
409
island_stitch_data[element1->island].rotation += rotation;
522
edgecos = dot_v2v2(uv1, uv2);
523
edgesin = cross_v2v2(uv1, uv2);
524
rotation = acosf(max_ff(-1.0f, min_ff(1.0f, edgecos)));
526
if (edgesin > 0.0f) {
527
island_stitch_data[element1->island].num_rot_elements++;
528
island_stitch_data[element1->island].rotation += rotation;
531
island_stitch_data[element1->island].num_rot_elements_neg++;
532
island_stitch_data[element1->island].rotation_neg += rotation;
413
537
static void stitch_island_calculate_vert_rotation(UvElement *element, StitchState *state, IslandStitchData *island_stitch_data)
415
float edgecos = 1, edgesin = 0;
539
float edgecos = 1.0f, edgesin = 0.0f;
417
541
UvElement *element_iter;
542
float rotation = 0, rotation_neg = 0;
543
int rot_elem = 0, rot_elem_neg = 0;
421
546
if (element->island == state->static_island && !state->midpoints)
441
569
negate_v2_v2(normal, state->normals + index_tmp2 * 2);
442
570
edgecos = dot_v2v2(normal, state->normals + index_tmp1 * 2);
443
571
edgesin = cross_v2v2(normal, state->normals + index_tmp1 * 2);
444
rotation += (edgesin > 0) ? acos(edgecos) : -acos(edgecos);
572
if (edgesin > 0.0f) {
573
rotation += acosf(max_ff(-1.0f, min_ff(1.0f, edgecos)));
577
rotation_neg += acosf(max_ff(-1.0f, min_ff(1.0f, edgecos)));
448
if (state->midpoints)
450
island_stitch_data[element->island].num_rot_elements++;
583
if (state->midpoints) {
585
rotation_neg /= 2.0f;
587
island_stitch_data[element->island].num_rot_elements += rot_elem;
451
588
island_stitch_data[element->island].rotation += rotation;
455
static void stitch_state_delete(StitchState *stitch_state)
458
if (stitch_state->element_map) {
459
EDBM_uv_element_map_free(stitch_state->element_map);
461
if (stitch_state->uvs) {
462
MEM_freeN(stitch_state->uvs);
464
if (stitch_state->selection_stack) {
465
MEM_freeN(stitch_state->selection_stack);
467
if (stitch_state->tris_per_island) {
468
MEM_freeN(stitch_state->tris_per_island);
470
if (stitch_state->map) {
471
MEM_freeN(stitch_state->map);
473
if (stitch_state->normals) {
474
MEM_freeN(stitch_state->normals);
476
if (stitch_state->edges) {
477
MEM_freeN(stitch_state->edges);
479
MEM_freeN(stitch_state);
589
island_stitch_data[element->island].num_rot_elements_neg += rot_elem_neg;
590
island_stitch_data[element->island].rotation_neg += rotation_neg;
594
static void state_delete(StitchState *state)
597
if (state->element_map) {
598
EDBM_uv_element_map_free(state->element_map);
601
MEM_freeN(state->uvs);
603
if (state->selection_stack) {
604
MEM_freeN(state->selection_stack);
606
if (state->tris_per_island) {
607
MEM_freeN(state->tris_per_island);
610
MEM_freeN(state->map);
612
if (state->normals) {
613
MEM_freeN(state->normals);
616
MEM_freeN(state->edges);
618
if (state->stitch_preview) {
619
stitch_preview_delete(state->stitch_preview);
621
if (state->edge_hash) {
622
BLI_ghash_free(state->edge_hash, NULL, NULL);
628
static void stitch_uv_edge_generate_linked_edges(GHash *edge_hash, StitchState *state)
630
UvEdge *edges = state->edges;
631
int *map = state->map;
632
UvElementMap *element_map = state->element_map;
633
UvElement *first_element = element_map->buf;
636
for (i = 0; i < state->total_separate_edges; i++) {
637
UvEdge *edge = edges + i;
642
/* only boundary edges can be stitched. Yes. Sorry about that :p */
643
if (edge->flag & STITCH_BOUNDARY) {
644
UvElement *element1 = state->uvs[edge->uv1];
645
UvElement *element2 = state->uvs[edge->uv2];
647
/* Now iterate through all faces and try to find edges sharing the same vertices */
648
UvElement *iter1 = element_map->vert[BM_elem_index_get(element1->l->v)];
649
UvEdge *last_set = edge;
650
int elemindex2 = BM_elem_index_get(element2->l->v);
654
for (; iter1; iter1 = iter1->next) {
655
UvElement *iter2 = NULL;
657
/* check to see if other vertex of edge belongs to same vertex as */
658
if (BM_elem_index_get(iter1->l->next->v) == elemindex2)
659
iter2 = ED_uv_element_get(element_map, iter1->l->f, iter1->l->next);
660
else if (BM_elem_index_get(iter1->l->prev->v) == elemindex2)
661
iter2 = ED_uv_element_get(element_map, iter1->l->f, iter1->l->prev);
664
int index1 = map[iter1 - first_element];
665
int index2 = map[iter2 - first_element];
667
/* make certain we do not have the same edge! */
668
if (state->uvs[index2] != element2 && state->uvs[index1] != element1) {
673
/* make sure the indices are well behaved */
674
if (index1 < index2) {
675
edgetmp.uv1 = index1;
676
edgetmp.uv2 = index2;
679
edgetmp.uv1 = index2;
680
edgetmp.uv2 = index1;
683
/* get the edge from the hash */
684
edge2 = BLI_ghash_lookup(edge_hash, &edgetmp);
686
/* here I am taking care of non manifold case, assuming more than two matching edges.
687
* I am not too sure we want this though */
688
last_set->next = edge2;
690
/* set first, similarly to uv elements. Now we can iterate among common edges easily */
697
/* so stitchability code works */
485
704
/* checks for remote uvs that may be stitched with a certain uv, flags them if stitchable. */
810
static void stitch_validate_edge_stichability(UvEdge *edge, StitchState *state, IslandStitchData *island_stitch_data,
811
PreviewPosition *preview_position) {
812
UvEdge *edge_iter = edge->first;
813
StitchPreviewer *preview = state->stitch_preview;
815
for (; edge_iter; edge_iter = edge_iter->next) {
816
if (edge_iter == edge)
818
if (stitch_check_edges_state_stitchable(edge, edge_iter, state)) {
819
if ((edge_iter->element->island == state->static_island) || (edge->element->island == state->static_island)) {
820
edge->flag |= STITCH_STITCHABLE;
821
preview->num_stitchable++;
822
stitch_setup_face_preview_for_uv_group(state->uvs[edge->uv1], state, island_stitch_data, preview_position);
823
stitch_setup_face_preview_for_uv_group(state->uvs[edge->uv2], state, island_stitch_data, preview_position);
829
/* this can happen if the uvs to be stitched are not on a stitchable island */
830
if (!(edge->flag & STITCH_STITCHABLE)) {
831
preview->num_unstitchable++;
836
static void stitch_propagate_uv_final_position(UvElement *element, int index, PreviewPosition *preview_position, UVVertAverage *final_position, StitchState *state, char final, Scene *scene)
838
StitchPreviewer *preview = state->stitch_preview;
840
if (element->flag & STITCH_STITCHABLE) {
841
UvElement *element_iter = element;
842
/* propagate to coincident uvs */
848
luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
850
element_iter->flag |= STITCH_PROCESSED;
851
/* either flush to preview or to the MTFace, if final */
853
copy_v2_v2(luv->uv, final_position[index].uv);
855
uvedit_uv_select_enable(state->em, scene, l, FALSE);
858
int face_preview_pos = preview_position[BM_elem_index_get(element_iter->l->f)].data_position;
859
if (face_preview_pos != STITCH_NO_PREVIEW) {
860
copy_v2_v2(preview->preview_polys + face_preview_pos + 2 * element_iter->tfindex,
861
final_position[index].uv);
865
/* end of calculations, keep only the selection flag */
866
if ( (!state->snap_islands) || ((!state->midpoints) && (element_iter->island == state->static_island))) {
867
element_iter->flag &= STITCH_SELECTED;
870
element_iter = element_iter->next;
871
} while (element_iter && !element_iter->separate);
581
875
/* main processing function. It calculates preview and final positions. */
582
876
static int stitch_process_data(StitchState *state, Scene *scene, int final)
636
937
for (i = 0; i < state->selection_size; i++) {
637
UvElement *element = state->selection_stack[i];
638
if (element->flag & STITCH_STITCHABLE_CANDIDATE) {
639
element->flag &= ~STITCH_STITCHABLE_CANDIDATE;
640
stitch_validate_stichability(element, state, island_stitch_data, preview_position);
938
if (state->mode == STITCH_VERT) {
939
UvElement *element = (UvElement *)state->selection_stack[i];
940
if (element->flag & STITCH_STITCHABLE_CANDIDATE) {
941
element->flag &= ~STITCH_STITCHABLE_CANDIDATE;
942
stitch_validate_uv_stichability(element, state, island_stitch_data, preview_position);
945
/* add to preview for unstitchable */
946
preview->num_unstitchable++;
643
/* add to preview for unstitchable */
644
preview->num_unstitchable++;
950
UvEdge *edge = (UvEdge *)state->selection_stack[i];
951
if (edge->flag & STITCH_STITCHABLE_CANDIDATE) {
952
edge->flag &= ~STITCH_STITCHABLE_CANDIDATE;
953
stitch_validate_edge_stichability(edge, state, island_stitch_data, preview_position);
956
preview->num_unstitchable++;
729
1043
/* fill the appropriate preview buffers */
730
for (i = 0; i < state->total_separate_uvs; i++) {
731
UvElement *element = (UvElement *)state->uvs[i];
732
if (element->flag & STITCH_STITCHABLE) {
734
luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
736
copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 2], luv->uv);
1044
if (state->mode == STITCH_VERT) {
1045
for (i = 0; i < state->total_separate_uvs; i++) {
1046
UvElement *element = (UvElement *)state->uvs[i];
1047
if (element->flag & STITCH_STITCHABLE) {
1049
luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
1051
copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 2], luv->uv);
1053
stitchBufferIndex++;
1055
else if (element->flag & STITCH_SELECTED) {
1057
luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
1059
copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 2], luv->uv);
1060
unstitchBufferIndex++;
740
else if (element->flag & STITCH_SELECTED) {
742
luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
744
copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 2], luv->uv);
745
unstitchBufferIndex++;
1065
for (i = 0; i < state->total_separate_edges; i++) {
1066
UvEdge *edge = state->edges + i;
1067
UvElement *element1 = state->uvs[edge->uv1];
1068
UvElement *element2 = state->uvs[edge->uv2];
1070
if (edge->flag & STITCH_STITCHABLE) {
1072
luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
1073
copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4], luv->uv);
1076
luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
1077
copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4 + 2], luv->uv);
1079
stitchBufferIndex++;
1080
BLI_assert(stitchBufferIndex <= preview->num_stitchable);
1082
else if (edge->flag & STITCH_SELECTED) {
1084
luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
1085
copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4], luv->uv);
1088
luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
1089
copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4 + 2], luv->uv);
1091
unstitchBufferIndex++;
1092
BLI_assert(unstitchBufferIndex <= preview->num_unstitchable);
751
1099
* Here we calculate the final coordinates of the uvs *
752
1100
******************************************************/
754
final_position = MEM_callocN(state->selection_size * sizeof(*final_position), "stitch_uv_average");
755
uvfinal_map = MEM_mallocN(state->element_map->totalUVs * sizeof(*uvfinal_map), "stitch_uv_final_map");
1102
if (state->mode == STITCH_VERT) {
1103
final_position = MEM_callocN(state->selection_size * sizeof(*final_position), "stitch_uv_average");
1104
uvfinal_map = MEM_mallocN(state->element_map->totalUVs * sizeof(*uvfinal_map), "stitch_uv_final_map");
1107
final_position = MEM_callocN(state->total_separate_uvs * sizeof(*final_position), "stitch_uv_average");
757
1110
/* first pass, calculate final position for stitchable uvs of the static island */
758
1111
for (i = 0; i < state->selection_size; i++) {
759
UvElement *element = state->selection_stack[i];
760
if (element->flag & STITCH_STITCHABLE) {
763
UvElement *element_iter;
766
luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
769
uvfinal_map[element - state->element_map->buf] = i;
771
copy_v2_v2(final_position[i].uv, luv->uv);
772
final_position[i].count = 1;
774
if (state->snap_islands && element->island == state->static_island && !stitch_midpoints)
777
element_iter = state->element_map->vert[BM_elem_index_get(l->v)];
779
for ( ; element_iter; element_iter = element_iter->next) {
780
if (element_iter->separate) {
781
if (stitch_check_uvs_state_stitchable(element, element_iter, state)) {
783
luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
1112
if (state->mode == STITCH_VERT) {
1113
UvElement *element = state->selection_stack[i];
1115
if (element->flag & STITCH_STITCHABLE) {
1118
UvElement *element_iter;
1121
luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
1123
uvfinal_map[element - state->element_map->buf] = i;
1125
copy_v2_v2(final_position[i].uv, luv->uv);
1126
final_position[i].count = 1;
1128
if (state->snap_islands && element->island == state->static_island && !stitch_midpoints)
1131
element_iter = state->element_map->vert[BM_elem_index_get(l->v)];
1133
for ( ; element_iter; element_iter = element_iter->next) {
1134
if (element_iter->separate) {
1135
if (stitch_check_uvs_state_stitchable(element, element_iter, state)) {
1136
l = element_iter->l;
1137
luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
1138
if (stitch_midpoints) {
1139
add_v2_v2(final_position[i].uv, luv->uv);
1140
final_position[i].count++;
1142
else if (element_iter->island == state->static_island) {
1143
/* if multiple uvs on the static island exist,
1144
* last checked remains. to disambiguate we need to limit or use
1146
copy_v2_v2(final_position[i].uv, luv->uv);
1152
if (stitch_midpoints) {
1153
final_position[i].uv[0] /= final_position[i].count;
1154
final_position[i].uv[1] /= final_position[i].count;
1158
UvEdge *edge = state->selection_stack[i];
1160
if (edge->flag & STITCH_STITCHABLE) {
1161
MLoopUV *luv2, *luv1;
1165
l = state->uvs[edge->uv1]->l;
1166
luv1 = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
1167
l = state->uvs[edge->uv2]->l;
1168
luv2 = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
1170
copy_v2_v2(final_position[edge->uv1].uv, luv1->uv);
1171
copy_v2_v2(final_position[edge->uv2].uv, luv2->uv);
1172
final_position[edge->uv1].count = 1;
1173
final_position[edge->uv2].count = 1;
1175
state->uvs[edge->uv1]->flag |= STITCH_STITCHABLE;
1176
state->uvs[edge->uv2]->flag |= STITCH_STITCHABLE;
1178
if (state->snap_islands && edge->element->island == state->static_island && !stitch_midpoints)
1181
for (edge_iter = edge->first; edge_iter; edge_iter = edge_iter->next) {
1182
if (stitch_check_edges_state_stitchable (edge, edge_iter, state)) {
1183
l = state->uvs[edge_iter->uv1]->l;
1184
luv1 = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
1185
l = state->uvs[edge_iter->uv2]->l;
1186
luv2 = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
784
1188
if (stitch_midpoints) {
785
add_v2_v2(final_position[i].uv, luv->uv);
786
final_position[i].count++;
1189
add_v2_v2(final_position[edge->uv1].uv, luv1->uv);
1190
final_position[edge->uv1].count++;
1191
add_v2_v2(final_position[edge->uv2].uv, luv2->uv);
1192
final_position[edge->uv2].count++;
788
else if (element_iter->island == state->static_island) {
789
/* if multiple uvs on the static island exist,
790
* last checked remains. to disambiguate we need to limit or use
792
copy_v2_v2(final_position[i].uv, luv->uv);
1194
else if (edge_iter->element->island == state->static_island) {
1195
copy_v2_v2(final_position[edge->uv1].uv, luv1->uv);
1196
copy_v2_v2(final_position[edge->uv2].uv, luv2->uv);
798
if (stitch_midpoints) {
1204
/* take mean position here. For edge case, this can't be done inside the loop for shared uvverts */
1205
if (state->mode == STITCH_EDGE && stitch_midpoints) {
1206
for (i = 0; i < state->total_separate_uvs; i++) {
799
1207
final_position[i].uv[0] /= final_position[i].count;
800
1208
final_position[i].uv[1] /= final_position[i].count;
804
1212
/* second pass, calculate island rotation and translation before modifying any uvs */
805
1213
if (state->snap_islands) {
806
for (i = 0; i < state->selection_size; i++) {
807
UvElement *element = state->selection_stack[i];
808
if (element->flag & STITCH_STITCHABLE) {
813
luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
815
/* accumulate each islands' translation from stitchable elements. it is important to do here
816
* because in final pass MTFaces get modified and result is zero. */
817
island_stitch_data[element->island].translation[0] += final_position[i].uv[0] - luv->uv[0];
818
island_stitch_data[element->island].translation[1] += final_position[i].uv[1] - luv->uv[1];
819
island_stitch_data[element->island].medianPoint[0] += luv->uv[0];
820
island_stitch_data[element->island].medianPoint[1] += luv->uv[1];
821
island_stitch_data[element->island].numOfElements++;
825
/* only calculate rotation when an edge has been fully selected */
826
for (i = 0; i < state->total_boundary_edges; i++) {
827
UvEdge *edge = state->edges + i;
828
if ((state->uvs[edge->uv1]->flag & STITCH_STITCHABLE) && (state->uvs[edge->uv2]->flag & STITCH_STITCHABLE)) {
829
stitch_island_calculate_edge_rotation(edge, state, final_position, uvfinal_map, island_stitch_data);
830
island_stitch_data[state->uvs[edge->uv1]->island].use_edge_rotation = 1;
834
for (i = 0; i < state->selection_size; i++) {
835
UvElement *element = state->selection_stack[i];
836
if (!island_stitch_data[element->island].use_edge_rotation) {
837
if (element->flag & STITCH_STITCHABLE) {
838
stitch_island_calculate_vert_rotation(element, state, island_stitch_data);
1214
if (state->mode == STITCH_VERT) {
1215
for (i = 0; i < state->selection_size; i++) {
1216
UvElement *element = state->selection_stack[i];
1218
if (element->flag & STITCH_STITCHABLE) {
1223
luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
1225
/* accumulate each islands' translation from stitchable elements. it is important to do here
1226
* because in final pass MTFaces get modified and result is zero. */
1227
island_stitch_data[element->island].translation[0] += final_position[i].uv[0] - luv->uv[0];
1228
island_stitch_data[element->island].translation[1] += final_position[i].uv[1] - luv->uv[1];
1229
island_stitch_data[element->island].medianPoint[0] += luv->uv[0];
1230
island_stitch_data[element->island].medianPoint[1] += luv->uv[1];
1231
island_stitch_data[element->island].numOfElements++;
1235
/* only calculate rotation when an edge has been fully selected */
1236
for (i = 0; i < state->total_separate_edges; i++) {
1237
UvEdge *edge = state->edges + i;
1238
if ((edge->flag & STITCH_BOUNDARY) && (state->uvs[edge->uv1]->flag & STITCH_STITCHABLE) && (state->uvs[edge->uv2]->flag & STITCH_STITCHABLE)) {
1239
stitch_island_calculate_edge_rotation(edge, state, final_position, uvfinal_map, island_stitch_data);
1240
island_stitch_data[state->uvs[edge->uv1]->island].use_edge_rotation = TRUE;
1244
/* clear seams of stitched edges */
1245
if (final && state->clear_seams) {
1246
for (i = 0; i < state->total_separate_edges; i++) {
1247
UvEdge *edge = state->edges + i;
1248
if ((state->uvs[edge->uv1]->flag & STITCH_STITCHABLE) && (state->uvs[edge->uv2]->flag & STITCH_STITCHABLE))
1249
BM_elem_flag_disable(edge->element->l->e, BM_ELEM_SEAM);
1253
for (i = 0; i < state->selection_size; i++) {
1254
UvElement *element = state->selection_stack[i];
1255
if (!island_stitch_data[element->island].use_edge_rotation) {
1256
if (element->flag & STITCH_STITCHABLE) {
1257
stitch_island_calculate_vert_rotation(element, state, island_stitch_data);
1263
for (i = 0; i < state->total_separate_uvs; i++) {
1264
UvElement *element = state->uvs[i];
1266
if (element->flag & STITCH_STITCHABLE) {
1271
luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
1273
/* accumulate each islands' translation from stitchable elements. it is important to do here
1274
* because in final pass MTFaces get modified and result is zero. */
1275
island_stitch_data[element->island].translation[0] += final_position[i].uv[0] - luv->uv[0];
1276
island_stitch_data[element->island].translation[1] += final_position[i].uv[1] - luv->uv[1];
1277
island_stitch_data[element->island].medianPoint[0] += luv->uv[0];
1278
island_stitch_data[element->island].medianPoint[1] += luv->uv[1];
1279
island_stitch_data[element->island].numOfElements++;
1283
for (i = 0; i < state->selection_size; i++) {
1284
UvEdge *edge = state->selection_stack[i];
1286
if (edge->flag & STITCH_STITCHABLE) {
1287
stitch_island_calculate_edge_rotation(edge, state, final_position, NULL, island_stitch_data);
1288
island_stitch_data[state->uvs[edge->uv1]->island].use_edge_rotation = TRUE;
1292
/* clear seams of stitched edges */
1293
if (final && state->clear_seams) {
1294
for (i = 0; i < state->selection_size; i++) {
1295
UvEdge *edge = state->selection_stack[i];
1296
if (edge->flag & STITCH_STITCHABLE) {
1297
BM_elem_flag_disable(edge->element->l->e, BM_ELEM_SEAM);
845
1304
/* third pass, propagate changes to coincident uvs */
846
1305
for (i = 0; i < state->selection_size; i++) {
847
UvElement *element = state->selection_stack[i];
848
if (element->flag & STITCH_STITCHABLE) {
849
UvElement *element_iter = element;
850
/* propagate to coincident uvs */
856
luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
858
element_iter->flag |= STITCH_PROCESSED;
859
/* either flush to preview or to the MTFace, if final */
861
copy_v2_v2(luv->uv, final_position[i].uv);
863
uvedit_uv_select_enable(state->em, scene, l, FALSE);
866
int face_preview_pos = preview_position[BM_elem_index_get(element_iter->face)].data_position;
867
if (face_preview_pos != STITCH_NO_PREVIEW) {
868
copy_v2_v2(preview->preview_polys + face_preview_pos + 2 * element_iter->tfindex,
869
final_position[i].uv);
873
/* end of calculations, keep only the selection flag */
874
if ( (!state->snap_islands) || ((!stitch_midpoints) && (element_iter->island == state->static_island))) {
875
element_iter->flag &= STITCH_SELECTED;
878
element_iter = element_iter->next;
879
} while (element_iter && !element_iter->separate);
1306
if (state->mode == STITCH_VERT) {
1307
UvElement *element = state->selection_stack[i];
1309
stitch_propagate_uv_final_position (element, i, preview_position, final_position, state, final, scene);
1312
UvEdge *edge = state->selection_stack[i];
1314
stitch_propagate_uv_final_position (state->uvs[edge->uv1], edge->uv1, preview_position, final_position, state, final, scene);
1315
stitch_propagate_uv_final_position (state->uvs[edge->uv2], edge->uv2, preview_position, final_position, state, final, scene);
1317
edge->flag &= (STITCH_SELECTED | STITCH_BOUNDARY);
953
static void stitch_calculate_edge_normal(BMEditMesh *em, UvEdge *edge, float *normal)
1421
static void stitch_switch_selection_mode(StitchState *state)
1423
void **old_selection_stack = state->selection_stack;
1424
int old_selection_size = state->selection_size;
1425
state->selection_size = 0;
1427
if (state->mode == STITCH_VERT) {
1429
state->selection_stack = MEM_mallocN(state->total_separate_edges * sizeof(*state->selection_stack),
1430
"stitch_new_edge_selection_stack");
1432
/* check if both elements of an edge are selected */
1433
for (i = 0; i < state->total_separate_edges; i++) {
1434
UvEdge *edge = state->edges + i;
1435
UvElement *element1 = state->uvs[edge->uv1];
1436
UvElement *element2 = state->uvs[edge->uv2];
1438
if ((element1->flag & STITCH_SELECTED) && (element2->flag & STITCH_SELECTED))
1439
stitch_select_edge(edge, state, TRUE);
1442
/* unselect selected uvelements */
1443
for (i = 0; i < old_selection_size; i++) {
1444
UvElement *element = old_selection_stack[i];
1446
element->flag &= ~STITCH_SELECTED;
1448
state->mode = STITCH_EDGE;
1452
state->selection_stack = MEM_mallocN(state->total_separate_uvs * sizeof(*state->selection_stack),
1453
"stitch_new_vert_selection_stack");
1455
for (i = 0; i < old_selection_size; i++) {
1456
UvEdge *edge = old_selection_stack[i];
1457
UvElement *element1 = state->uvs[edge->uv1];
1458
UvElement *element2 = state->uvs[edge->uv2];
1460
stitch_select_uv(element1, state, TRUE);
1461
stitch_select_uv(element2, state, TRUE);
1463
edge->flag &= ~STITCH_SELECTED;
1465
state->mode = STITCH_VERT;
1467
MEM_freeN(old_selection_stack);
1470
static void stitch_calculate_edge_normal(BMEditMesh *em, UvEdge *edge, float *normal, float aspect)
955
1472
BMLoop *l1 = edge->element->l;
956
BMLoop *l2 = l1->next;
957
1473
MLoopUV *luv1, *luv2;
958
1474
float tangent[2];
960
1476
luv1 = CustomData_bmesh_get(&em->bm->ldata, l1->head.data, CD_MLOOPUV);
961
luv2 = CustomData_bmesh_get(&em->bm->ldata, l2->head.data, CD_MLOOPUV);
1477
luv2 = CustomData_bmesh_get(&em->bm->ldata, l1->next->head.data, CD_MLOOPUV);
963
1479
sub_v2_v2v2(tangent, luv2->uv, luv1->uv);
1481
tangent[1] /= aspect;
965
1483
normal[0] = tangent[1];
966
1484
normal[1] = -tangent[0];
968
1486
normalize_v2(normal);
1489
static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
1492
float pointsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
1493
StitchState *state = (StitchState *)arg;
1494
StitchPreviewer *stitch_preview = state->stitch_preview;
1496
glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
1497
glEnableClientState(GL_VERTEX_ARRAY);
1499
glPointSize(pointsize * 2.0f);
1503
UI_ThemeColor4(TH_STITCH_PREVIEW_ACTIVE);
1504
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1505
glVertexPointer(2, GL_FLOAT, 0, stitch_preview->static_tris);
1506
glDrawArrays(GL_TRIANGLES, 0, stitch_preview->num_static_tris * 3);
1508
glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_polys);
1509
for (i = 0; i < stitch_preview->num_polys; i++) {
1510
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1511
UI_ThemeColor4(TH_STITCH_PREVIEW_FACE);
1512
glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]);
1513
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1514
UI_ThemeColor4(TH_STITCH_PREVIEW_EDGE);
1515
glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]);
1517
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
1518
UI_ThemeColor4(TH_STITCH_PREVIEW_VERT);
1519
glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]);
1522
index += stitch_preview->uvs_per_polygon[i];
1524
glDisable(GL_BLEND);
1526
/* draw vert preview */
1527
if (state->mode == STITCH_VERT) {
1528
UI_ThemeColor4(TH_STITCH_PREVIEW_STITCHABLE);
1529
glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_stitchable);
1530
glDrawArrays(GL_POINTS, 0, stitch_preview->num_stitchable);
1532
UI_ThemeColor4(TH_STITCH_PREVIEW_UNSTITCHABLE);
1533
glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_unstitchable);
1534
glDrawArrays(GL_POINTS, 0, stitch_preview->num_unstitchable);
1537
UI_ThemeColor4(TH_STITCH_PREVIEW_STITCHABLE);
1538
glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_stitchable);
1539
glDrawArrays(GL_LINES, 0, 2 * stitch_preview->num_stitchable);
1541
UI_ThemeColor4(TH_STITCH_PREVIEW_UNSTITCHABLE);
1542
glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_unstitchable);
1543
glDrawArrays(GL_LINES, 0, 2 * stitch_preview->num_unstitchable);
1546
glPopClientAttrib();
1547
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1552
static UvEdge *uv_edge_get (BMLoop *l, StitchState *state)
1556
UvElement *element1 = ED_uv_element_get(state->element_map, l->f, l);
1557
UvElement *element2 = ED_uv_element_get(state->element_map, l->f, l->next);
1559
int uv1 = state->map[element1 - state->element_map->buf];
1560
int uv2 = state->map[element2 - state->element_map->buf];
1571
return BLI_ghash_lookup(state->edge_hash, &tmp_edge);
971
1574
static int stitch_init(bContext *C, wmOperator *op)
973
1576
/* for fast edge lookup... */
975
1578
/* ...and actual edge storage */
977
1580
int total_edges;
1002
1611
state->snap_islands = RNA_boolean_get(op->ptr, "snap_islands");
1003
1612
state->static_island = RNA_int_get(op->ptr, "static_island");
1004
1613
state->midpoints = RNA_boolean_get(op->ptr, "midpoint_snap");
1614
state->clear_seams = RNA_boolean_get(op->ptr, "clear_seams");
1615
if (RNA_struct_property_is_set(op->ptr, "mode")) {
1616
state->mode = RNA_enum_get(op->ptr, "mode");
1619
if (ts->uv_flag & UV_SYNC_SELECTION) {
1620
if (ts->selectmode & SCE_SELECT_VERTEX)
1621
state->mode = STITCH_VERT;
1623
state->mode = STITCH_EDGE;
1626
if (ts->uv_selectmode & UV_SELECT_VERTEX) {
1627
state->mode = STITCH_VERT;
1630
state->mode = STITCH_EDGE;
1635
state->draw_handle = ED_region_draw_cb_activate(ar->type, stitch_draw, state, REGION_DRAW_POST_VIEW);
1005
1636
/* in uv synch selection, all uv's are visible */
1006
1637
if (ts->uv_flag & UV_SYNC_SELECTION) {
1007
state->element_map = EDBM_uv_element_map_create(state->em, 0, 1);
1638
state->element_map = EDBM_uv_element_map_create(state->em, FALSE, TRUE);
1010
state->element_map = EDBM_uv_element_map_create(state->em, 1, 1);
1641
state->element_map = EDBM_uv_element_map_create(state->em, TRUE, TRUE);
1012
1643
if (!state->element_map) {
1013
stitch_state_delete(state);
1644
state_delete(state);
1648
uvedit_get_aspect(scene, obedit, em, &aspx, &aspy);
1649
state->aspect = aspx / aspy;
1017
1651
/* Entirely possible if redoing last operator that static island is bigger than total number of islands.
1018
* This ensures we get no hang in the island checking code in stitch_process_data. */
1652
* This ensures we get no hang in the island checking code in stitch_stitch_process_data. */
1019
1653
state->static_island %= state->element_map->totalIslands;
1021
1655
/* Count 'unique' uvs */
1662
/* explicitly set preview to NULL, to avoid deleting an invalid pointer on stitch_process_data */
1663
state->stitch_preview = NULL;
1028
1664
/* Allocate the unique uv buffers */
1029
1665
state->uvs = MEM_mallocN(sizeof(*state->uvs) * counter, "uv_stitch_unique_uvs");
1030
1666
/* internal uvs need no normals but it is hard and slow to keep a map of
1031
1667
* normals only for boundary uvs, so allocating for all uvs */
1032
1668
state->normals = MEM_callocN(sizeof(*state->normals) * counter * 2, "uv_stitch_normals");
1033
1669
state->total_separate_uvs = counter;
1034
/* we can at most have totalUVs edges or uvs selected. Actually they are less, considering we store only
1035
* unique uvs for processing but I am accounting for all bizarre cases, especially for edges, this way */
1036
state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * counter, "uv_stitch_selection_stack");
1037
1670
state->map = map = MEM_mallocN(sizeof(*map) * state->element_map->totalUVs, "uv_stitch_unique_map");
1038
1671
/* Allocate the edge stack */
1039
edgeHash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "stitch_edge_hash");
1672
edge_hash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "stitch_edge_hash");
1040
1673
all_edges = MEM_mallocN(sizeof(*all_edges) * state->element_map->totalUVs, "stitch_all_edges");
1042
if (!state->selection_stack || !state->uvs || !map || !edgeHash || !all_edges) {
1043
stitch_state_delete(state);
1675
if (!state->uvs || !map || !edge_hash || !all_edges) {
1676
state_delete(state);
1102
ghi = BLI_ghashIterator_new(edgeHash);
1104
/* fill the edges with data */
1105
for (; !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)) {
1106
UvEdge *edge = ((UvEdge *)BLI_ghashIterator_getKey(ghi));
1107
if (edge->flag & STITCH_BOUNDARY) {
1737
ghi = BLI_ghashIterator_new(edge_hash);
1738
total_edges = BLI_ghash_size(edge_hash);
1111
1739
state->edges = edges = MEM_mallocN(sizeof(*edges) * total_edges, "stitch_edges");
1112
if (!ghi || !edges) {
1113
MEM_freeN(all_edges);
1114
stitch_state_delete(state);
1741
/* I assume any system will be able to at least allocate an iterator :p */
1743
BLI_ghashIterator_free(ghi);
1744
state_delete(state);
1118
state->total_boundary_edges = total_edges;
1748
state->total_separate_edges = total_edges;
1120
1750
/* fill the edges with data */
1121
for (i = 0, BLI_ghashIterator_init(ghi, edgeHash); !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)) {
1122
UvEdge *edge = ((UvEdge *)BLI_ghashIterator_getKey(ghi));
1123
if (edge->flag & STITCH_BOUNDARY) {
1124
edges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(ghi));
1751
for (i = 0, BLI_ghashIterator_init(ghi, edge_hash); !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)) {
1752
edges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(ghi));
1128
1755
/* cleanup temporary stuff */
1129
1756
BLI_ghashIterator_free(ghi);
1130
1757
MEM_freeN(all_edges);
1132
/* refill hash with new pointers to cleanup duplicates */
1133
BLI_ghash_free(edgeHash, NULL, NULL);
1759
BLI_ghash_free(edge_hash, NULL, NULL);
1761
/* refill an edge hash to create edge connnectivity data */
1762
state->edge_hash = edge_hash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "stitch_edge_hash");
1763
for (i = 0; i < total_edges; i++) {
1764
BLI_ghash_insert(edge_hash, edges + i, edges + i);
1766
stitch_uv_edge_generate_linked_edges(edge_hash, state);
1135
1768
/***** calculate 2D normals for boundary uvs *****/
1137
1770
/* we use boundary edges to calculate 2D normals.
1138
1771
* to disambiguate the direction of the normal, we also need
1139
1772
* a point "inside" the island, that can be provided by
1140
* the opposite uv for a quad, or the next uv for a triangle. */
1773
* the winding of the polygon (assuming counter-clockwise flow). */
1142
1775
for (i = 0; i < total_edges; i++) {
1776
UvEdge *edge = edges + i;
1143
1777
float normal[2];
1144
stitch_calculate_edge_normal(em, edges + i, normal);
1146
add_v2_v2(state->normals + edges[i].uv1 * 2, normal);
1147
add_v2_v2(state->normals + edges[i].uv2 * 2, normal);
1149
normalize_v2(state->normals + edges[i].uv1 * 2);
1150
normalize_v2(state->normals + edges[i].uv2 * 2);
1778
if (edge->flag & STITCH_BOUNDARY) {
1779
stitch_calculate_edge_normal(em, edge, normal, state->aspect);
1781
add_v2_v2(state->normals + edge->uv1 * 2, normal);
1782
add_v2_v2(state->normals + edge->uv2 * 2, normal);
1784
normalize_v2(state->normals + edge->uv1 * 2);
1785
normalize_v2(state->normals + edge->uv2 * 2);
1159
1795
if (RNA_struct_property_is_set(op->ptr, "selection")) {
1160
1796
int faceIndex, elementIndex;
1161
1797
UvElement *element;
1163
EDBM_index_arrays_init(em, 0, 0, 1);
1165
RNA_BEGIN(op->ptr, itemptr, "selection") {
1166
faceIndex = RNA_int_get(&itemptr, "face_index");
1167
elementIndex = RNA_int_get(&itemptr, "element_index");
1168
efa = EDBM_face_at_index(em, faceIndex);
1169
element = ED_uv_element_get(state->element_map, efa, BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, elementIndex));
1170
stitch_select_uv(element, state, 1);
1174
EDBM_index_arrays_free(em);
1798
enum StitchModes stored_mode = RNA_enum_get(op->ptr, "stored_mode");
1800
EDBM_index_arrays_ensure(em, BM_FACE);
1802
if (stored_mode == STITCH_VERT) {
1803
state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * state->total_separate_uvs, "uv_stitch_selection_stack");
1805
RNA_BEGIN (op->ptr, itemptr, "selection")
1807
faceIndex = RNA_int_get(&itemptr, "face_index");
1808
elementIndex = RNA_int_get(&itemptr, "element_index");
1809
efa = EDBM_face_at_index(em, faceIndex);
1810
element = ED_uv_element_get(state->element_map, efa, BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, elementIndex));
1811
stitch_select_uv(element, state, 1);
1816
state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * state->total_separate_edges, "uv_stitch_selection_stack");
1818
RNA_BEGIN (op->ptr, itemptr, "selection")
1820
UvEdge tmp_edge, *edge;
1822
faceIndex = RNA_int_get(&itemptr, "face_index");
1823
elementIndex = RNA_int_get(&itemptr, "element_index");
1824
efa = EDBM_face_at_index(em, faceIndex);
1825
element = ED_uv_element_get(state->element_map, efa, BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, elementIndex));
1826
uv1 = map[element - state->element_map->buf];
1828
element = ED_uv_element_get(state->element_map, efa, BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, (elementIndex + 1) % efa->len));
1829
uv2 = map[element - state->element_map->buf];
1840
edge = BLI_ghash_lookup(edge_hash, &tmp_edge);
1842
stitch_select_edge(edge, state, TRUE);
1846
/* if user has switched the operator mode after operation, we need to convert
1847
* the stored format */
1848
if (state->mode != stored_mode) {
1849
state->mode = stored_mode;
1850
stitch_switch_selection_mode(state);
1175
1852
/* Clear the selection */
1176
1853
RNA_collection_clear(op->ptr, "selection");
1180
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1181
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
1182
if (uvedit_uv_select_test(em, scene, l)) {
1183
UvElement *element = ED_uv_element_get(state->element_map, efa, l);
1185
stitch_select_uv(element, state, 1);
1857
if (state->mode == STITCH_VERT) {
1858
state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * state->total_separate_uvs, "uv_stitch_selection_stack");
1860
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1861
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
1862
if (uvedit_uv_select_test(em, scene, l)) {
1863
UvElement *element = ED_uv_element_get(state->element_map, efa, l);
1865
stitch_select_uv(element, state, 1);
1872
state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * state->total_separate_edges, "uv_stitch_selection_stack");
1874
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1875
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
1876
if (uvedit_edge_select_test(em, scene, l)) {
1877
UvEdge *edge = uv_edge_get(l, state);
1879
stitch_select_edge(edge, state, TRUE);
1237
1933
obedit = CTX_data_edit_object(C);
1238
1934
sima = CTX_wm_space_image(C);
1240
stitch_state = (StitchState *)op->customdata;
1936
state = (StitchState *)op->customdata;
1242
1938
if (finished) {
1245
RNA_float_set(op->ptr, "limit", stitch_state->limit_dist);
1246
RNA_boolean_set(op->ptr, "use_limit", stitch_state->use_limit);
1247
RNA_boolean_set(op->ptr, "snap_islands", stitch_state->snap_islands);
1248
RNA_int_set(op->ptr, "static_island", stitch_state->static_island);
1249
RNA_boolean_set(op->ptr, "midpoint_snap", stitch_state->midpoints);
1941
RNA_float_set(op->ptr, "limit", state->limit_dist);
1942
RNA_boolean_set(op->ptr, "use_limit", state->use_limit);
1943
RNA_boolean_set(op->ptr, "snap_islands", state->snap_islands);
1944
RNA_int_set(op->ptr, "static_island", state->static_island);
1945
RNA_boolean_set(op->ptr, "midpoint_snap", state->midpoints);
1946
RNA_enum_set(op->ptr, "mode", state->mode);
1947
RNA_enum_set(op->ptr, "stored_mode", state->mode);
1251
1949
/* Store selection for re-execution of stitch */
1252
for (i = 0; i < stitch_state->selection_size; i++) {
1950
for (i = 0; i < state->selection_size; i++) {
1253
1952
PointerRNA itemptr;
1254
UvElement *element = stitch_state->selection_stack[i];
1953
if (state->mode == STITCH_VERT) {
1954
element = state->selection_stack[i];
1957
element = ((UvEdge *)state->selection_stack[i])->element;
1256
1959
RNA_collection_add(op->ptr, "selection", &itemptr);
1258
RNA_int_set(&itemptr, "face_index", BM_elem_index_get(element->face));
1961
RNA_int_set(&itemptr, "face_index", BM_elem_index_get(element->l->f));
1260
1962
RNA_int_set(&itemptr, "element_index", element->tfindex);
1264
1965
uvedit_live_unwrap_update(sima, scene, obedit);
1268
1969
ED_area_headerprint(sa, NULL);
1971
ED_region_draw_cb_exit(CTX_wm_region(C)->type, state->draw_handle);
1270
1973
DAG_id_tag_update(obedit->data, 0);
1271
1974
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1273
stitch_state_delete(stitch_state);
1976
state_delete(state);
1274
1977
op->customdata = NULL;
1276
stitch_preview_delete();
1308
2009
Image *ima = CTX_data_edit_image(C);
1310
2011
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
1311
uv_find_nearest_vert(scene, ima, stitch_state->em, co, NULL, &hit);
1314
/* Add vertex to selection, deselect all common uv's of vert other
1315
* than selected and update the preview. This behavior was decided so that
1316
* you can do stuff like deselect the opposite stitchable vertex and the initial still gets deselected */
1318
/* This works due to setting of tmp in find nearest uv vert */
1319
UvElement *element = ED_uv_element_get(stitch_state->element_map, hit.efa, hit.l);
1320
stitch_select_uv(element, stitch_state, 0);
2013
if (state->mode == STITCH_VERT) {
2014
uv_find_nearest_vert(scene, ima, state->em, co, NULL, &hit);
2017
/* Add vertex to selection, deselect all common uv's of vert other
2018
* than selected and update the preview. This behavior was decided so that
2019
* you can do stuff like deselect the opposite stitchable vertex and the initial still gets deselected */
2021
/* This works due to setting of tmp in find nearest uv vert */
2022
UvElement *element = ED_uv_element_get(state->element_map, hit.efa, hit.l);
2023
stitch_select_uv(element, state, FALSE);
2028
uv_find_nearest_edge(scene, ima, state->em, co, &hit);
2031
UvEdge *edge = uv_edge_get(hit.l, state);
2032
stitch_select_edge(edge, state, FALSE);
1325
2037
static int stitch_modal(bContext *C, wmOperator *op, wmEvent *event)
1327
StitchState *stitch_state;
1328
2040
Scene *scene = CTX_data_scene(C);
1330
stitch_state = (StitchState *)op->customdata;
2042
state = (StitchState *)op->customdata;
1332
2044
switch (event->type) {
1333
2045
case MIDDLEMOUSE:
1334
2046
return OPERATOR_PASS_THROUGH;
1338
2050
return stitch_cancel(C, op);
1341
2053
case LEFTMOUSE:
1342
2054
if (event->shift && (U.flag & USER_LMOUSESELECT)) {
1343
if (event->val == KM_RELEASE) {
1344
stitch_select(C, scene, event, stitch_state);
2055
if (event->val == KM_PRESS) {
2056
stitch_select(C, scene, event, state);
1346
if (!stitch_process_data(stitch_state, scene, 0)) {
2058
if (!stitch_process_data(state, scene, FALSE)) {
1347
2059
return stitch_cancel(C, op);
1414
2130
if (event->val == KM_PRESS) {
1415
stitch_state->midpoints = !stitch_state->midpoints;
1416
if (!stitch_process_data(stitch_state, scene, 0)) {
2131
state->midpoints = !state->midpoints;
2132
if (!stitch_process_data(state, scene, FALSE)) {
1417
2133
return stitch_cancel(C, op);
1422
/* Select geometry*/
2138
/* Select geometry*/
1423
2139
case RIGHTMOUSE:
1424
2140
if (!event->shift) {
1425
2141
return stitch_cancel(C, op);
1427
if (event->val == KM_RELEASE && !(U.flag & USER_LMOUSESELECT)) {
1428
stitch_select(C, scene, event, stitch_state);
2143
if (event->val == KM_PRESS && !(U.flag & USER_LMOUSESELECT)) {
2144
stitch_select(C, scene, event, state);
1430
if (!stitch_process_data(stitch_state, scene, 0)) {
2146
if (!stitch_process_data(state, scene, FALSE)) {
1431
2147
return stitch_cancel(C, op);
1435
2151
return OPERATOR_RUNNING_MODAL;
1437
/* snap islands on/off */
2153
/* snap islands on/off */
1439
2155
if (event->val == KM_PRESS) {
1440
stitch_state->snap_islands = !stitch_state->snap_islands;
1441
if (!stitch_process_data(stitch_state, scene, 0)) {
2156
state->snap_islands = !state->snap_islands;
2157
if (!stitch_process_data(state, scene, FALSE)) {
1442
2158
return stitch_cancel(C, op);
1485
2218
"Island that stays in place when stitching islands", 0, INT_MAX);
1486
2219
RNA_def_boolean(ot->srna, "midpoint_snap", 0, "Snap At Midpoint",
1487
2220
"UVs are stitched at midpoint instead of at static island");
2221
RNA_def_boolean(ot->srna, "clear_seams", 1, "Clear Seams",
2222
"Clear seams of stitched edges");
2223
RNA_def_enum(ot->srna, "mode", stitch_modes, STITCH_VERT, "Operation Mode",
2224
"Use vertex or edge stitching");
2225
prop = RNA_def_enum(ot->srna, "stored_mode", stitch_modes, STITCH_VERT, "Stored Operation Mode",
2226
"Use vertex or edge stitching");
2227
RNA_def_property_flag(prop, PROP_HIDDEN);
1488
2228
prop = RNA_def_collection_runtime(ot->srna, "selection", &RNA_SelectedUvElement, "Selection", "");
1489
2229
/* Selection should not be editable or viewed in toolbar */
1490
2230
RNA_def_property_flag(prop, PROP_HIDDEN);