code cleanup: dont use function calls like dot_v3v3, pow and sqrt within macros which...
[blender.git] / source / blender / editors / uvedit / uvedit_smart_stitch.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Antony Riakiotakis.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/uvedit/uvedit_smart_stitch.c
29  *  \ingroup eduv
30  */
31
32
33 #include <stdlib.h>
34 #include <string.h>
35 #include <math.h>
36
37 #include "MEM_guardedalloc.h"
38
39 #include "DNA_object_types.h"
40 #include "DNA_mesh_types.h"
41 #include "DNA_meshdata_types.h"
42 #include "DNA_scene_types.h"
43
44 #include "BLI_ghash.h"
45 #include "BLI_math.h"
46 #include "BLI_math_vector.h"
47 #include "BLI_string.h"
48
49 #include "BKE_context.h"
50 #include "BKE_customdata.h"
51 #include "BKE_depsgraph.h"
52 #include "BKE_mesh.h"
53 #include "BKE_tessmesh.h"
54
55 #include "ED_mesh.h"
56 #include "ED_uvedit.h"
57 #include "ED_screen.h"
58
59 #include "RNA_access.h"
60 #include "RNA_define.h"
61
62 #include "WM_api.h"
63 #include "WM_types.h"
64
65 #include "UI_view2d.h"
66
67 #include "uvedit_intern.h"
68
69 /* ********************** smart stitch operator *********************** */
70
71
72 struct IslandStitchData;
73
74 /* This is a straightforward implementation, count the uv's in the island that will move and take the mean displacement/rotation and apply it to all
75  * elements of the island except from the stitchable */
76 typedef struct IslandStitchData {
77         /* rotation can be used only for edges, for vertices there is no such notion */
78         float rotation;
79         float translation[2];
80         /* Used for rotation, the island will rotate around this point */
81         float medianPoint[2];
82         int numOfElements;
83         int num_rot_elements;
84         /* flag to remember if island has been added for preview */
85         char addedForPreview;
86         /* flag an island to be considered for determining static island */
87         char stitchableCandidate;
88         /* if edge rotation is used, flag so that vertex rotation is not used */
89         char use_edge_rotation;
90 } IslandStitchData;
91
92 /* just for averaging UVs */
93 typedef struct UVVertAverage {
94         float uv[2];
95         unsigned short count;
96 } UVVertAverage;
97
98 typedef struct UvEdge {
99         /* index to uv buffer */
100         unsigned int uv1;
101         unsigned int uv2;
102         /* general use flag (Used to check if edge is boundary here, and propagates to adjacency elements) */
103         char flag;
104         /* element that guarantees element->face has the face on element->tfindex and element->tfindex+1 is the second uv */
105         UvElement *element;
106 } UvEdge;
107
108
109 /* stitch state object */
110 typedef struct StitchState {
111         /* use limit flag */
112         char use_limit;
113         /* limit to operator, same as original operator */
114         float limit_dist;
115         /* snap uv islands together during stitching */
116         char snap_islands;
117         /* stich at midpoints or at islands */
118         char midpoints;
119         /* editmesh, cached for use in modal handler */
120         BMEditMesh *em;
121         /* element map for getting info about uv connectivity */
122         UvElementMap *element_map;
123         /* edge container */
124         UvEdge *uvedges;
125         /* container of first of a group of coincident uvs, these will be operated upon */
126         UvElement **uvs;
127         /* maps uvelements to their first coincident uv */
128         int *map;
129         /* 2D normals per uv to calculate rotation for snapping */
130         float *normals;
131         /* edge storage */
132         UvEdge *edges;
133
134         /* count of separate uvs and edges */
135         int total_boundary_edges;
136         int total_separate_uvs;
137         /* hold selection related information */
138         UvElement **selection_stack;
139         int selection_size;
140         /* island that stays in place */
141         int static_island;
142         /* store number of primitives per face so that we can allocate the active island buffer later */
143         unsigned int *tris_per_island;
144 } StitchState;
145
146 typedef struct PreviewPosition {
147         int data_position;
148         int polycount_position;
149 } PreviewPosition;
150 /*
151  * defines for UvElement flags
152  */
153 #define STITCH_SELECTED 1
154 #define STITCH_STITCHABLE 2
155 #define STITCH_PROCESSED 4
156 #define STITCH_BOUNDARY 8
157 #define STITCH_STITCHABLE_CANDIDATE 16
158
159 #define STITCH_NO_PREVIEW -1
160
161 /* previewer stuff (see uvedit_intern.h for more info) */
162 static StitchPreviewer *_stitch_preview;
163
164 /* constructor */
165 static StitchPreviewer *stitch_preview_init(void)
166 {
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;
172
173         _stitch_preview->preview_uvs = 0;
174         _stitch_preview->num_polys = 0;
175         _stitch_preview->num_stitchable = 0;
176         _stitch_preview->num_unstitchable = 0;
177
178         _stitch_preview->static_tris = NULL;
179
180         _stitch_preview->num_static_tris = 0;
181
182         return _stitch_preview;
183 }
184
185 /* destructor...yeah this should be C++ :) */
186 static void stitch_preview_delete(void)
187 {
188         if (_stitch_preview) {
189                 if (_stitch_preview->preview_polys) {
190                         MEM_freeN(_stitch_preview->preview_polys);
191                         _stitch_preview->preview_polys = NULL;
192                 }
193                 if (_stitch_preview->uvs_per_polygon) {
194                         MEM_freeN(_stitch_preview->uvs_per_polygon);
195                         _stitch_preview->uvs_per_polygon = NULL;
196                 }
197                 if (_stitch_preview->preview_stitchable) {
198                         MEM_freeN(_stitch_preview->preview_stitchable);
199                         _stitch_preview->preview_stitchable = NULL;
200                 }
201                 if (_stitch_preview->preview_unstitchable) {
202                         MEM_freeN(_stitch_preview->preview_unstitchable);
203                         _stitch_preview->preview_unstitchable = NULL;
204                 }
205                 if (_stitch_preview->static_tris) {
206                         MEM_freeN(_stitch_preview->static_tris);
207                         _stitch_preview->static_tris = NULL;
208                 }
209
210                 MEM_freeN(_stitch_preview);
211                 _stitch_preview = NULL;
212         }
213 }
214
215
216 /* "getter method" */
217 StitchPreviewer *uv_get_stitch_previewer(void)
218 {
219         return _stitch_preview;
220 }
221
222 #define HEADER_LENGTH 256
223
224 /* 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)
226 {
227         static char str[] = "(S)nap %s, (M)idpoints %s, (L)imit %.2f (Alt Wheel adjust) %s, Switch (I)sland, shift select vertices";
228
229         char msg[HEADER_LENGTH];
230         ScrArea *sa = CTX_wm_area(C);
231
232         if (sa) {
233                 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");
238
239                 ED_area_headerprint(sa, msg);
240         }
241 }
242
243 static int getNumOfIslandUvs(UvElementMap *elementMap, int island)
244 {
245         if (island == elementMap->totalIslands - 1) {
246                 return elementMap->totalUVs - elementMap->islandIndices[island];
247         }
248         else {
249                 return elementMap->islandIndices[island + 1] - elementMap->islandIndices[island];
250         }
251 }
252
253 static void stitch_uv_rotate(float rotation, float medianPoint[2], float uv[2])
254 {
255         float uv_rotation_result[2];
256
257         uv[0] -= medianPoint[0];
258         uv[1] -= medianPoint[1];
259
260         uv_rotation_result[0] = cosf(rotation) * uv[0] - sinf(rotation) * uv[1];
261         uv_rotation_result[1] = sinf(rotation) * uv[0] + cosf(rotation) * uv[1];
262
263         uv[0] = uv_rotation_result[0] + medianPoint[0];
264         uv[1] = uv_rotation_result[1] + medianPoint[1];
265 }
266
267 static int stitch_check_uvs_stitchable(UvElement *element, UvElement *element_iter, StitchState *state)
268 {
269         float limit;
270         int do_limit;
271
272         if (element_iter == element) {
273                 return 0;
274         }
275
276         limit = state->limit_dist;
277         do_limit = state->use_limit;
278
279         if (do_limit) {
280                 MLoopUV *luv_orig, *luv_iter;
281                 BMLoop *l_orig, *l_iter;
282
283
284                 l_orig = element->l;
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);
288
289                 if (fabsf(luv_orig->uv[0] - luv_iter->uv[0]) < limit &&
290                     fabsf(luv_orig->uv[1] - luv_iter->uv[1]) < limit)
291                 {
292                         return 1;
293                 }
294                 else {
295                         return 0;
296                 }
297         }
298         else {
299                 return 1;
300         }
301 }
302
303
304 static int stitch_check_uvs_state_stitchable(UvElement *element, UvElement *element_iter, StitchState *state)
305 {
306         if ((state->snap_islands && element->island == element_iter->island) ||
307             (!state->midpoints && element->island == element_iter->island))
308         {
309                 return 0;
310         }
311
312         return stitch_check_uvs_stitchable(element, element_iter, state);
313 }
314
315
316 /* calculate snapping for islands */
317 static void stitch_calculate_island_snapping(StitchState *state, PreviewPosition *preview_position, StitchPreviewer *preview, IslandStitchData *island_stitch_data, int final)
318 {
319         int i;
320         UvElement *element;
321
322         for (i = 0; i < state->element_map->totalIslands; i++) {
323                 if (island_stitch_data[i].addedForPreview) {
324                         int numOfIslandUVs = 0, j;
325
326                         /* check to avoid divide by 0 */
327                         if (island_stitch_data[i].num_rot_elements > 0) {
328                                 island_stitch_data[i].rotation /= island_stitch_data[i].num_rot_elements;
329                                 island_stitch_data[i].medianPoint[0] /= island_stitch_data[i].numOfElements;
330                                 island_stitch_data[i].medianPoint[1] /= island_stitch_data[i].numOfElements;
331                         }
332                         island_stitch_data[i].translation[0] /= island_stitch_data[i].numOfElements;
333                         island_stitch_data[i].translation[1] /= island_stitch_data[i].numOfElements;
334                         numOfIslandUVs = getNumOfIslandUvs(state->element_map, i);
335                         element = &state->element_map->buf[state->element_map->islandIndices[i]];
336                         for (j = 0; j < numOfIslandUVs; j++, element++) {
337                                 /* stitchable uvs have already been processed, don't process */
338                                 if (!(element->flag & STITCH_PROCESSED)) {
339                                         MLoopUV *luv;
340                                         BMLoop *l;
341
342                                         l = element->l;
343                                         luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
344
345                                         if (final) {
346
347                                                 stitch_uv_rotate(island_stitch_data[i].rotation, island_stitch_data[i].medianPoint, luv->uv);
348
349                                                 add_v2_v2(luv->uv, island_stitch_data[i].translation);
350                                         }
351
352                                         else {
353                                                 int face_preview_pos = preview_position[BM_elem_index_get(element->face)].data_position;
354
355                                                 stitch_uv_rotate(island_stitch_data[i].rotation, island_stitch_data[i].medianPoint,
356                                                                  preview->preview_polys + face_preview_pos + 2 * element->tfindex);
357
358                                                 add_v2_v2(preview->preview_polys + face_preview_pos + 2 * element->tfindex,
359                                                           island_stitch_data[i].translation);
360                                         }
361                                 }
362                                 /* cleanup */
363                                 element->flag &= STITCH_SELECTED;
364                         }
365                 }
366         }
367 }
368
369
370
371 static void stitch_island_calculate_edge_rotation(UvEdge *edge, StitchState *state, UVVertAverage *uv_average, unsigned int *uvfinal_map, IslandStitchData *island_stitch_data)
372 {
373         UvElement *element1, *element2;
374         float uv1[2], uv2[2];
375         float edgecos, edgesin;
376         int index1, index2;
377         float rotation;
378         MLoopUV *luv1, *luv2;
379         BMLoop *l1, *l2;
380
381         element1 = state->uvs[edge->uv1];
382         element2 = state->uvs[edge->uv2];
383
384         l1 = element1->l;
385         luv1 = CustomData_bmesh_get(&state->em->bm->ldata, l1->head.data, CD_MLOOPUV);
386         l2 = element2->l;
387         luv2 = CustomData_bmesh_get(&state->em->bm->ldata, l2->head.data, CD_MLOOPUV);
388
389         index1 = uvfinal_map[element1 - state->element_map->buf];
390         index2 = uvfinal_map[element2 - state->element_map->buf];
391
392         /* the idea here is to take the directions of the edges and find the rotation between final and initial
393          * direction. This, using inner and outer vector products, gives the angle. Directions are differences so... */
394         uv1[0] = luv2->uv[0] - luv1->uv[0];
395         uv1[1] = luv2->uv[1] - luv1->uv[1];
396
397         uv2[0] = uv_average[index2].uv[0] - uv_average[index1].uv[0];
398         uv2[1] = uv_average[index2].uv[1] - uv_average[index1].uv[1];
399
400         normalize_v2(uv1);
401         normalize_v2(uv2);
402
403         edgecos = uv1[0] * uv2[0] + uv1[1] * uv2[1];
404         edgesin = uv1[0] * uv2[1] - uv2[0] * uv1[1];
405
406         rotation = (edgesin > 0.0f) ?
407                     +acosf(maxf(-1.0f, minf(1.0f, edgecos))) :
408                     -acosf(maxf(-1.0f, minf(1.0f, edgecos)));
409
410         island_stitch_data[element1->island].num_rot_elements++;
411         island_stitch_data[element1->island].rotation += rotation;
412 }
413
414
415 static void stitch_island_calculate_vert_rotation(UvElement *element, StitchState *state, IslandStitchData *island_stitch_data)
416 {
417         float edgecos = 1.0f, edgesin = 0.0f;
418         int index;
419         UvElement *element_iter;
420         float rotation = 0;
421         BMLoop *l;
422
423         if (element->island == state->static_island && !state->midpoints)
424                 return;
425
426         l = element->l;
427
428         index = BM_elem_index_get(l->v);
429
430         element_iter = state->element_map->vert[index];
431
432         for (; element_iter; element_iter = element_iter->next) {
433                 if (element_iter->separate && stitch_check_uvs_state_stitchable(element, element_iter, state)) {
434                         int index_tmp1, index_tmp2;
435                         float normal[2];
436                         /* easily possible*/
437
438                         index_tmp1 = element_iter - state->element_map->buf;
439                         index_tmp1 = state->map[index_tmp1];
440                         index_tmp2 = element - state->element_map->buf;
441                         index_tmp2 = state->map[index_tmp2];
442
443                         negate_v2_v2(normal, state->normals + index_tmp2 * 2);
444                         edgecos = dot_v2v2(normal, state->normals + index_tmp1 * 2);
445                         edgesin = cross_v2v2(normal, state->normals + index_tmp1 * 2);
446                         rotation += (edgesin > 0.0f) ? acosf(edgecos) : -acosf(edgecos);
447                 }
448         }
449
450         if (state->midpoints)
451                 rotation /= 2.0f;
452         island_stitch_data[element->island].num_rot_elements++;
453         island_stitch_data[element->island].rotation += rotation;
454 }
455
456
457 static void stitch_state_delete(StitchState *stitch_state)
458 {
459         if (stitch_state) {
460                 if (stitch_state->element_map) {
461                         EDBM_uv_element_map_free(stitch_state->element_map);
462                 }
463                 if (stitch_state->uvs) {
464                         MEM_freeN(stitch_state->uvs);
465                 }
466                 if (stitch_state->selection_stack) {
467                         MEM_freeN(stitch_state->selection_stack);
468                 }
469                 if (stitch_state->tris_per_island) {
470                         MEM_freeN(stitch_state->tris_per_island);
471                 }
472                 if (stitch_state->map) {
473                         MEM_freeN(stitch_state->map);
474                 }
475                 if (stitch_state->normals) {
476                         MEM_freeN(stitch_state->normals);
477                 }
478                 if (stitch_state->edges) {
479                         MEM_freeN(stitch_state->edges);
480                 }
481                 MEM_freeN(stitch_state);
482         }
483 }
484
485
486
487 /* checks for remote uvs that may be stitched with a certain uv, flags them if stitchable. */
488 static void determine_uv_stitchability(UvElement *element, StitchState *state, IslandStitchData *island_stitch_data)
489 {
490         int vert_index;
491         UvElement *element_iter;
492         BMLoop *l;
493
494         l = element->l;
495
496         vert_index = BM_elem_index_get(l->v);
497         element_iter = state->element_map->vert[vert_index];
498
499         for (; element_iter; element_iter = element_iter->next) {
500                 if (element_iter->separate) {
501                         if (element_iter == element) {
502                                 continue;
503                         }
504                         if (stitch_check_uvs_stitchable(element, element_iter, state)) {
505                                 island_stitch_data[element_iter->island].stitchableCandidate = 1;
506                                 island_stitch_data[element->island].stitchableCandidate = 1;
507                                 element->flag |= STITCH_STITCHABLE_CANDIDATE;
508                         }
509                 }
510         }
511 }
512
513
514 /* set preview buffer position of UV face in editface->tmp.l */
515 static void stitch_set_face_preview_buffer_position(BMFace *efa, StitchPreviewer *preview, PreviewPosition *preview_position)
516 {
517         int index = BM_elem_index_get(efa);
518
519         if (preview_position[index].data_position == STITCH_NO_PREVIEW) {
520                 preview_position[index].data_position = preview->preview_uvs * 2;
521                 preview_position[index].polycount_position = preview->num_polys++;
522                 preview->preview_uvs += efa->len;
523         }
524 }
525
526
527 /* setup face preview for all coincident uvs and their faces */
528 static void stitch_setup_face_preview_for_uv_group(UvElement *element, StitchState *state, IslandStitchData *island_stitch_data,
529                                                    PreviewPosition *preview_position) {
530         StitchPreviewer *preview = uv_get_stitch_previewer();
531
532         /* static island does not change so returning immediately */
533         if (state->snap_islands && !state->midpoints && state->static_island == element->island)
534                 return;
535
536         if (state->snap_islands) {
537                 island_stitch_data[element->island].addedForPreview = 1;
538         }
539
540         do {
541                 stitch_set_face_preview_buffer_position(element->face, preview, preview_position);
542                 element = element->next;
543         } while (element && !element->separate);
544 }
545
546
547 /* checks if uvs are indeed stitchable and registers so that they can be shown in preview */
548 static void stitch_validate_stichability(UvElement *element, StitchState *state, IslandStitchData *island_stitch_data,
549                                          PreviewPosition *preview_position) {
550         UvElement *element_iter;
551         StitchPreviewer *preview;
552         int vert_index;
553         BMLoop *l;
554
555         l = element->l;
556
557         vert_index = BM_elem_index_get(l->v);
558
559         preview = uv_get_stitch_previewer();
560         element_iter = state->element_map->vert[vert_index];
561
562         for (; element_iter; element_iter = element_iter->next) {
563                 if (element_iter->separate) {
564                         if (element_iter == element)
565                                 continue;
566                         if (stitch_check_uvs_state_stitchable(element, element_iter, state)) {
567                                 if ((element_iter->island == state->static_island) || (element->island == state->static_island)) {
568                                         element->flag |= STITCH_STITCHABLE;
569                                         preview->num_stitchable++;
570                                         stitch_setup_face_preview_for_uv_group(element, state, island_stitch_data, preview_position);
571                                         return;
572                                 }
573                         }
574                 }
575         }
576
577         /* this can happen if the uvs to be stitched are not on a stitchable island */
578         if (!(element->flag & STITCH_STITCHABLE)) {
579                 preview->num_unstitchable++;
580         }
581 }
582
583 /* main processing function. It calculates preview and final positions. */
584 static int stitch_process_data(StitchState *state, Scene *scene, int final)
585 {
586         int i;
587         StitchPreviewer *preview;
588         IslandStitchData *island_stitch_data = NULL;
589         int previous_island = state->static_island;
590         BMFace *efa;
591         BMIter iter;
592         UVVertAverage *final_position;
593         char stitch_midpoints = state->midpoints;
594         /* used to map uv indices to uvaverage indices for selection */
595         unsigned int *uvfinal_map;
596         /* per face preview position in preview buffer */
597         PreviewPosition *preview_position;
598
599         /* cleanup previous preview */
600         stitch_preview_delete();
601         preview = stitch_preview_init();
602         if (preview == NULL)
603                 return 0;
604
605         preview_position = MEM_mallocN(state->em->bm->totface * sizeof(*preview_position), "stitch_face_preview_position");
606         /* each face holds its position in the preview buffer in tmp. -1 is uninitialized */
607         for (i = 0; i < state->em->bm->totface; i++) {
608                 preview_position[i].data_position = STITCH_NO_PREVIEW;
609         }
610
611         island_stitch_data = MEM_callocN(sizeof(*island_stitch_data) * state->element_map->totalIslands, "stitch_island_data");
612         if (!island_stitch_data) {
613                 return 0;
614         }
615
616         /* store indices to editVerts and Faces. May be unneeded but ensuring anyway */
617         BM_mesh_elem_index_ensure(state->em->bm, BM_VERT | BM_FACE);
618
619         /*****************************************
620          *  First determine stitchability of uvs *
621          *****************************************/
622
623         for (i = 0; i < state->selection_size; i++) {
624                 UvElement *element = state->selection_stack[i];
625                 determine_uv_stitchability(element, state, island_stitch_data);
626         }
627
628         /* set static island to one that is added for preview */
629         state->static_island %= state->element_map->totalIslands;
630         while (!(island_stitch_data[state->static_island].stitchableCandidate)) {
631                 state->static_island++;
632                 state->static_island %= state->element_map->totalIslands;
633                 /* this is entirely possible if for example limit stitching with no stitchable verts or no selection */
634                 if (state->static_island == previous_island)
635                         break;
636         }
637
638         for (i = 0; i < state->selection_size; i++) {
639                 UvElement *element = state->selection_stack[i];
640                 if (element->flag & STITCH_STITCHABLE_CANDIDATE) {
641                         element->flag &= ~STITCH_STITCHABLE_CANDIDATE;
642                         stitch_validate_stichability(element, state, island_stitch_data, preview_position);
643                 }
644                 else {
645                         /* add to preview for unstitchable */
646                         preview->num_unstitchable++;
647                 }
648         }
649
650         /*****************************************
651          *  Setup preview for stitchable islands *
652          *****************************************/
653         if (state->snap_islands) {
654                 for (i = 0; i < state->element_map->totalIslands; i++) {
655                         if (island_stitch_data[i].addedForPreview) {
656                                 int numOfIslandUVs = 0, j;
657                                 UvElement *element;
658                                 numOfIslandUVs = getNumOfIslandUvs(state->element_map, i);
659                                 element = &state->element_map->buf[state->element_map->islandIndices[i]];
660                                 for (j = 0; j < numOfIslandUVs; j++, element++) {
661                                         stitch_set_face_preview_buffer_position(element->face, preview, preview_position);
662                                 }
663                         }
664                 }
665         }
666
667         /*********************************************************************
668          * Setup the preview buffers and fill them with the appropriate data *
669          *********************************************************************/
670         if (!final) {
671                 BMIter liter;
672                 BMLoop *l;
673                 MLoopUV *luv;
674                 unsigned int buffer_index = 0;
675                 int stitchBufferIndex = 0, unstitchBufferIndex = 0;
676                 /* initialize the preview buffers */
677                 preview->preview_polys = (float *)MEM_mallocN(preview->preview_uvs * sizeof(float) * 2, "tri_uv_stitch_prev");
678                 preview->uvs_per_polygon = MEM_mallocN(preview->num_polys * sizeof(*preview->uvs_per_polygon), "tri_uv_stitch_prev");
679                 preview->preview_stitchable = (float *)MEM_mallocN(preview->num_stitchable * sizeof(float) * 2, "stitch_preview_stichable_data");
680                 preview->preview_unstitchable = (float *)MEM_mallocN(preview->num_unstitchable * sizeof(float) * 2, "stitch_preview_unstichable_data");
681
682                 preview->static_tris = (float *)MEM_mallocN(state->tris_per_island[state->static_island] * sizeof(float) * 6, "static_island_preview_tris");
683
684                 preview->num_static_tris = state->tris_per_island[state->static_island];
685                 /* will cause cancel and freeing of all data structures so OK */
686                 if (!preview->preview_polys || !preview->preview_stitchable || !preview->preview_unstitchable) {
687                         return 0;
688                 }
689
690                 /* copy data from MTFaces to the preview display buffers */
691                 BM_ITER_MESH (efa, &iter, state->em->bm, BM_FACES_OF_MESH) {
692                         /* just to test if face was added for processing. uvs of inselected vertices will return NULL */
693                         UvElement *element = ED_uv_element_get(state->element_map, efa, BM_FACE_FIRST_LOOP(efa));
694
695                         if (element) {
696                                 int numoftris = efa->len - 2;
697                                 int index = BM_elem_index_get(efa);
698                                 int face_preview_pos = preview_position[index].data_position;
699                                 if (face_preview_pos != STITCH_NO_PREVIEW) {
700                                         preview->uvs_per_polygon[preview_position[index].polycount_position] = efa->len;
701                                         BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
702                                                 luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
703                                                 copy_v2_v2(preview->preview_polys + face_preview_pos + i * 2, luv->uv);
704                                         }
705                                 }
706
707                                 if (element->island == state->static_island) {
708                                         BMLoop *fl = BM_FACE_FIRST_LOOP(efa);
709                                         MLoopUV *fuv = CustomData_bmesh_get(&state->em->bm->ldata, fl->head.data, CD_MLOOPUV);
710
711                                         BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
712                                                 if (i < numoftris) {
713                                                         /* using next since the first uv is already accounted for */
714                                                         BMLoop *lnext = l->next;
715                                                         MLoopUV *luvnext = CustomData_bmesh_get(&state->em->bm->ldata, lnext->next->head.data, CD_MLOOPUV);
716                                                         luv = CustomData_bmesh_get(&state->em->bm->ldata, lnext->head.data, CD_MLOOPUV);
717
718                                                         memcpy(preview->static_tris + buffer_index, fuv->uv, 2 * sizeof(float));
719                                                         memcpy(preview->static_tris + buffer_index + 2, luv->uv, 2 * sizeof(float));
720                                                         memcpy(preview->static_tris + buffer_index + 4, luvnext->uv, 2 * sizeof(float));
721                                                         buffer_index += 6;
722                                                 }
723                                                 else {
724                                                         break;
725                                                 }
726                                         }
727                                 }
728                         }
729                 }
730
731                 /* fill the appropriate preview buffers */
732                 for (i = 0; i < state->total_separate_uvs; i++) {
733                         UvElement *element = (UvElement *)state->uvs[i];
734                         if (element->flag & STITCH_STITCHABLE) {
735                                 l = element->l;
736                                 luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
737
738                                 copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 2], luv->uv);
739
740                                 stitchBufferIndex++;
741                         }
742                         else if (element->flag & STITCH_SELECTED) {
743                                 l = element->l;
744                                 luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
745
746                                 copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 2], luv->uv);
747                                 unstitchBufferIndex++;
748                         }
749                 }
750         }
751
752         /******************************************************
753          * Here we calculate the final coordinates of the uvs *
754          ******************************************************/
755
756         final_position = MEM_callocN(state->selection_size * sizeof(*final_position), "stitch_uv_average");
757         uvfinal_map = MEM_mallocN(state->element_map->totalUVs * sizeof(*uvfinal_map), "stitch_uv_final_map");
758
759         /* first pass, calculate final position for stitchable uvs of the static island */
760         for (i = 0; i < state->selection_size; i++) {
761                 UvElement *element = state->selection_stack[i];
762                 if (element->flag & STITCH_STITCHABLE) {
763                         BMLoop *l;
764                         MLoopUV *luv;
765                         UvElement *element_iter;
766
767                         l = element->l;
768                         luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
769
770
771                         uvfinal_map[element - state->element_map->buf] = i;
772
773                         copy_v2_v2(final_position[i].uv, luv->uv);
774                         final_position[i].count = 1;
775
776                         if (state->snap_islands && element->island == state->static_island && !stitch_midpoints)
777                                 continue;
778
779                         element_iter = state->element_map->vert[BM_elem_index_get(l->v)];
780
781                         for ( ; element_iter; element_iter = element_iter->next) {
782                                 if (element_iter->separate) {
783                                         if (stitch_check_uvs_state_stitchable(element, element_iter, state)) {
784                                                 l = element_iter->l;
785                                                 luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
786                                                 if (stitch_midpoints) {
787                                                         add_v2_v2(final_position[i].uv, luv->uv);
788                                                         final_position[i].count++;
789                                                 }
790                                                 else if (element_iter->island == state->static_island) {
791                                                         /* if multiple uvs on the static island exist,
792                                                          * last checked remains. to disambiguate we need to limit or use
793                                                          * edge stitch */
794                                                         copy_v2_v2(final_position[i].uv, luv->uv);
795                                                 }
796                                         }
797                                 }
798                         }
799                 }
800                 if (stitch_midpoints) {
801                         final_position[i].uv[0] /= final_position[i].count;
802                         final_position[i].uv[1] /= final_position[i].count;
803                 }
804         }
805
806         /* second pass, calculate island rotation and translation before modifying any uvs */
807         if (state->snap_islands) {
808                 for (i = 0; i < state->selection_size; i++) {
809                         UvElement *element = state->selection_stack[i];
810                         if (element->flag & STITCH_STITCHABLE) {
811                                 BMLoop *l;
812                                 MLoopUV *luv;
813
814                                 l = element->l;
815                                 luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
816
817                                 /* accumulate each islands' translation from stitchable elements. it is important to do here
818                                  * because in final pass MTFaces get modified and result is zero. */
819                                 island_stitch_data[element->island].translation[0] += final_position[i].uv[0] - luv->uv[0];
820                                 island_stitch_data[element->island].translation[1] += final_position[i].uv[1] - luv->uv[1];
821                                 island_stitch_data[element->island].medianPoint[0] += luv->uv[0];
822                                 island_stitch_data[element->island].medianPoint[1] += luv->uv[1];
823                                 island_stitch_data[element->island].numOfElements++;
824                         }
825                 }
826
827                 /* only calculate rotation when an edge has been fully selected */
828                 for (i = 0; i < state->total_boundary_edges; i++) {
829                         UvEdge *edge = state->edges + i;
830                         if ((state->uvs[edge->uv1]->flag & STITCH_STITCHABLE) && (state->uvs[edge->uv2]->flag & STITCH_STITCHABLE)) {
831                                 stitch_island_calculate_edge_rotation(edge, state, final_position, uvfinal_map, island_stitch_data);
832                                 island_stitch_data[state->uvs[edge->uv1]->island].use_edge_rotation = TRUE;
833                         }
834                 }
835
836                 for (i = 0; i < state->selection_size; i++) {
837                         UvElement *element = state->selection_stack[i];
838                         if (!island_stitch_data[element->island].use_edge_rotation) {
839                                 if (element->flag & STITCH_STITCHABLE) {
840                                         stitch_island_calculate_vert_rotation(element, state, island_stitch_data);
841                                 }
842                         }
843                 }
844
845         }
846
847         /* third pass, propagate changes to coincident uvs */
848         for (i = 0; i < state->selection_size; i++) {
849                 UvElement *element = state->selection_stack[i];
850                 if (element->flag & STITCH_STITCHABLE) {
851                         UvElement *element_iter = element;
852                         /* propagate to coincident uvs */
853                         do {
854                                 BMLoop *l;
855                                 MLoopUV *luv;
856
857                                 l = element_iter->l;
858                                 luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
859
860                                 element_iter->flag |= STITCH_PROCESSED;
861                                 /* either flush to preview or to the MTFace, if final */
862                                 if (final) {
863                                         copy_v2_v2(luv->uv, final_position[i].uv);
864
865                                         uvedit_uv_select_enable(state->em, scene, l, FALSE);
866                                 }
867                                 else {
868                                         int face_preview_pos = preview_position[BM_elem_index_get(element_iter->face)].data_position;
869                                         if (face_preview_pos != STITCH_NO_PREVIEW) {
870                                                 copy_v2_v2(preview->preview_polys + face_preview_pos + 2 * element_iter->tfindex,
871                                                            final_position[i].uv);
872                                         }
873                                 }
874
875                                 /* end of calculations, keep only the selection flag */
876                                 if ( (!state->snap_islands) || ((!stitch_midpoints) && (element_iter->island == state->static_island))) {
877                                         element_iter->flag &= STITCH_SELECTED;
878                                 }
879
880                                 element_iter = element_iter->next;
881                         } while (element_iter && !element_iter->separate);
882                 }
883         }
884
885         /* final pass, calculate Island translation/rotation if needed */
886         if (state->snap_islands) {
887                 stitch_calculate_island_snapping(state, preview_position, preview, island_stitch_data, final);
888         }
889
890         MEM_freeN(final_position);
891         MEM_freeN(uvfinal_map);
892         MEM_freeN(island_stitch_data);
893         MEM_freeN(preview_position);
894
895         return 1;
896 }
897
898 /* Stitch hash initialization functions */
899 static unsigned int uv_edge_hash(const void *key)
900 {
901         UvEdge *edge = (UvEdge *)key;
902         return
903             BLI_ghashutil_inthash(SET_INT_IN_POINTER(edge->uv2)) +
904             BLI_ghashutil_inthash(SET_INT_IN_POINTER(edge->uv1));
905 }
906
907 static int uv_edge_compare(const void *a, const void *b)
908 {
909         UvEdge *edge1 = (UvEdge *)a;
910         UvEdge *edge2 = (UvEdge *)b;
911
912         if ((edge1->uv1 == edge2->uv1) && (edge1->uv2 == edge2->uv2)) {
913                 return 0;
914         }
915         return 1;
916 }
917
918
919 /* Select all common uvs */
920 static void stitch_select_uv(UvElement *element, StitchState *state, int always_select)
921 {
922         BMLoop *l;
923         UvElement *element_iter;
924         UvElement **selection_stack = state->selection_stack;
925
926         l = element->l;
927
928         element_iter = state->element_map->vert[BM_elem_index_get(l->v)];
929         /* first deselect all common uvs */
930         for (; element_iter; element_iter = element_iter->next) {
931                 if (element_iter->separate) {
932                         /* only separators go to selection */
933                         if (element_iter->flag & STITCH_SELECTED) {
934                                 int i;
935                                 if (always_select)
936                                         continue;
937
938                                 element_iter->flag &= ~STITCH_SELECTED;
939                                 for (i = 0; i < state->selection_size; i++) {
940                                         if (selection_stack[i] == element_iter) {
941                                                 (state->selection_size)--;
942                                                 selection_stack[i] = selection_stack[state->selection_size];
943                                                 break;
944                                         }
945                                 }
946                         }
947                         else {
948                                 element_iter->flag |= STITCH_SELECTED;
949                                 selection_stack[state->selection_size++] = element_iter;
950                         }
951                 }
952         }
953 }
954
955 static void stitch_calculate_edge_normal(BMEditMesh *em, UvEdge *edge, float *normal)
956 {
957         BMLoop *l1 = edge->element->l;
958         BMLoop *l2 = l1->next;
959         MLoopUV *luv1, *luv2;
960         float tangent[2];
961
962         luv1 = CustomData_bmesh_get(&em->bm->ldata, l1->head.data, CD_MLOOPUV);
963         luv2 = CustomData_bmesh_get(&em->bm->ldata, l2->head.data, CD_MLOOPUV);
964
965         sub_v2_v2v2(tangent, luv2->uv,  luv1->uv);
966
967         normal[0] = tangent[1];
968         normal[1] = -tangent[0];
969
970         normalize_v2(normal);
971 }
972
973 static int stitch_init(bContext *C, wmOperator *op)
974 {
975         /* for fast edge lookup... */
976         GHash *edgeHash;
977         /* ...and actual edge storage */
978         UvEdge *edges;
979         int total_edges;
980         /* maps uvelements to their first coincident uv */
981         int *map;
982         int counter = 0, i;
983         BMFace *efa;
984         BMLoop *l;
985         BMIter iter, liter;
986         BMEditMesh *em;
987         GHashIterator *ghi;
988         UvEdge *all_edges;
989         StitchState *state = MEM_mallocN(sizeof(StitchState), "stitch state");
990         Scene *scene = CTX_data_scene(C);
991         ToolSettings *ts = scene->toolsettings;
992
993         Object *obedit = CTX_data_edit_object(C);
994
995         op->customdata = state;
996
997         if (!state)
998                 return 0;
999
1000         /* initialize state */
1001         state->use_limit = RNA_boolean_get(op->ptr, "use_limit");
1002         state->limit_dist = RNA_float_get(op->ptr, "limit");
1003         state->em = em = BMEdit_FromObject(obedit);
1004         state->snap_islands = RNA_boolean_get(op->ptr, "snap_islands");
1005         state->static_island = RNA_int_get(op->ptr, "static_island");
1006         state->midpoints = RNA_boolean_get(op->ptr, "midpoint_snap");
1007         /* in uv synch selection, all uv's are visible */
1008         if (ts->uv_flag & UV_SYNC_SELECTION) {
1009                 state->element_map = EDBM_uv_element_map_create(state->em, 0, 1);
1010         }
1011         else {
1012                 state->element_map = EDBM_uv_element_map_create(state->em, 1, 1);
1013         }
1014         if (!state->element_map) {
1015                 stitch_state_delete(state);
1016                 return 0;
1017         }
1018
1019         /* Entirely possible if redoing last operator that static island is bigger than total number of islands.
1020          * This ensures we get no hang in the island checking code in stitch_process_data. */
1021         state->static_island %= state->element_map->totalIslands;
1022
1023         /* Count 'unique' uvs */
1024         for (i = 0; i < state->element_map->totalUVs; i++) {
1025                 if (state->element_map->buf[i].separate) {
1026                         counter++;
1027                 }
1028         }
1029
1030         /* Allocate the unique uv buffers */
1031         state->uvs = MEM_mallocN(sizeof(*state->uvs) * counter, "uv_stitch_unique_uvs");
1032         /* internal uvs need no normals but it is hard and slow to keep a map of
1033          * normals only for boundary uvs, so allocating for all uvs */
1034         state->normals = MEM_callocN(sizeof(*state->normals) * counter * 2, "uv_stitch_normals");
1035         state->total_separate_uvs = counter;
1036         /* we can at most have totalUVs edges or uvs selected. Actually they are less, considering we store only
1037          * unique uvs for processing but I am accounting for all bizarre cases, especially for edges, this way */
1038         state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * counter, "uv_stitch_selection_stack");
1039         state->map = map = MEM_mallocN(sizeof(*map) * state->element_map->totalUVs, "uv_stitch_unique_map");
1040         /* Allocate the edge stack */
1041         edgeHash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "stitch_edge_hash");
1042         all_edges = MEM_mallocN(sizeof(*all_edges) * state->element_map->totalUVs, "stitch_all_edges");
1043
1044         if (!state->selection_stack || !state->uvs || !map || !edgeHash || !all_edges) {
1045                 stitch_state_delete(state);
1046                 return 0;
1047         }
1048
1049         /* So that we can use this as index for the UvElements */
1050         counter = -1;
1051         /* initialize the unique UVs and map */
1052         for (i = 0; i < em->bm->totvert; i++) {
1053                 UvElement *element = state->element_map->vert[i];
1054                 for (; element; element = element->next) {
1055                         if (element->separate) {
1056                                 counter++;
1057                                 state->uvs[counter] = element;
1058                         }
1059                         /* pointer arithmetic to the rescue, as always :)*/
1060                         map[element - state->element_map->buf] = counter;
1061                 }
1062         }
1063
1064         counter = 0;
1065         /* Now, on to generate our uv connectivity data */
1066         BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1067                 if (!(ts->uv_flag & UV_SYNC_SELECTION) && ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) || !BM_elem_flag_test(efa, BM_ELEM_SELECT)))
1068                         continue;
1069
1070                 BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1071                         UvElement *element = ED_uv_element_get(state->element_map, efa, l);
1072                         int offset1, itmp1 = element - state->element_map->buf;
1073                         int offset2, itmp2 = ED_uv_element_get(state->element_map, efa, l->next) - state->element_map->buf;
1074
1075                         offset1 = map[itmp1];
1076                         offset2 = map[itmp2];
1077
1078                         all_edges[counter].flag = 0;
1079                         all_edges[counter].element = element;
1080                         /* using an order policy, sort uvs according to address space. This avoids
1081                          * Having two different UvEdges with the same uvs on different positions  */
1082                         if (offset1 < offset2) {
1083                                 all_edges[counter].uv1 = offset1;
1084                                 all_edges[counter].uv2 = offset2;
1085                         }
1086                         else {
1087                                 all_edges[counter].uv1 = offset2;
1088                                 all_edges[counter].uv2 = offset1;
1089                         }
1090
1091                         if (BLI_ghash_haskey(edgeHash, &all_edges[counter])) {
1092                                 char *flag = BLI_ghash_lookup(edgeHash, &all_edges[counter]);
1093                                 *flag = 0;
1094                         }
1095                         else {
1096                                 BLI_ghash_insert(edgeHash, &all_edges[counter], &(all_edges[counter].flag));
1097                                 all_edges[counter].flag = STITCH_BOUNDARY;
1098                         }
1099                         counter++;
1100                 }
1101         }
1102
1103
1104         ghi = BLI_ghashIterator_new(edgeHash);
1105         total_edges = 0;
1106         /* fill the edges with data */
1107         for (; !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)) {
1108                 UvEdge *edge = ((UvEdge *)BLI_ghashIterator_getKey(ghi));
1109                 if (edge->flag & STITCH_BOUNDARY) {
1110                         total_edges++;
1111                 }
1112         }
1113         state->edges = edges = MEM_mallocN(sizeof(*edges) * total_edges, "stitch_edges");
1114         if (!ghi || !edges) {
1115                 MEM_freeN(all_edges);
1116                 stitch_state_delete(state);
1117                 return 0;
1118         }
1119
1120         state->total_boundary_edges = total_edges;
1121
1122         /* fill the edges with data */
1123         for (i = 0, BLI_ghashIterator_init(ghi, edgeHash); !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)) {
1124                 UvEdge *edge = ((UvEdge *)BLI_ghashIterator_getKey(ghi));
1125                 if (edge->flag & STITCH_BOUNDARY) {
1126                         edges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(ghi));
1127                 }
1128         }
1129
1130         /* cleanup temporary stuff */
1131         BLI_ghashIterator_free(ghi);
1132         MEM_freeN(all_edges);
1133
1134         /* refill hash with new pointers to cleanup duplicates */
1135         BLI_ghash_free(edgeHash, NULL, NULL);
1136
1137         /***** calculate 2D normals for boundary uvs *****/
1138
1139         /* we use boundary edges to calculate 2D normals.
1140          * to disambiguate the direction of the normal, we also need
1141          * a point "inside" the island, that can be provided by
1142          * the opposite uv for a quad, or the next uv for a triangle. */
1143
1144         for (i = 0; i < total_edges; i++) {
1145                 float normal[2];
1146                 stitch_calculate_edge_normal(em, edges + i, normal);
1147
1148                 add_v2_v2(state->normals + edges[i].uv1 * 2, normal);
1149                 add_v2_v2(state->normals + edges[i].uv2 * 2, normal);
1150
1151                 normalize_v2(state->normals + edges[i].uv1 * 2);
1152                 normalize_v2(state->normals + edges[i].uv2 * 2);
1153         }
1154
1155
1156         /***** fill selection stack *******/
1157
1158         state->selection_size = 0;
1159
1160         /* Load old selection if redoing operator with different settings */
1161         if (RNA_struct_property_is_set(op->ptr, "selection")) {
1162                 int faceIndex, elementIndex;
1163                 UvElement *element;
1164
1165                 EDBM_index_arrays_init(em, 0, 0, 1);
1166
1167                 RNA_BEGIN (op->ptr, itemptr, "selection")
1168                 {
1169                         faceIndex = RNA_int_get(&itemptr, "face_index");
1170                         elementIndex = RNA_int_get(&itemptr, "element_index");
1171                         efa = EDBM_face_at_index(em, faceIndex);
1172                         element = ED_uv_element_get(state->element_map, efa, BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, elementIndex));
1173                         stitch_select_uv(element, state, 1);
1174                 }
1175                 RNA_END;
1176
1177                 EDBM_index_arrays_free(em);
1178                 /* Clear the selection */
1179                 RNA_collection_clear(op->ptr, "selection");
1180
1181         }
1182         else {
1183                 BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1184                         BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
1185                                 if (uvedit_uv_select_test(em, scene, l)) {
1186                                         UvElement *element = ED_uv_element_get(state->element_map, efa, l);
1187                                         if (element) {
1188                                                 stitch_select_uv(element, state, 1);
1189                                         }
1190                                 }
1191                         }
1192                 }
1193         }
1194
1195         /***** initialize static island preview data *****/
1196
1197         state->tris_per_island = MEM_mallocN(sizeof(*state->tris_per_island) * state->element_map->totalIslands,
1198                                              "stitch island tris");
1199         for (i = 0; i < state->element_map->totalIslands; i++) {
1200                 state->tris_per_island[i] = 0;
1201         }
1202
1203         BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1204                 UvElement *element = ED_uv_element_get(state->element_map, efa, BM_FACE_FIRST_LOOP(efa));
1205
1206                 if (element) {
1207                         state->tris_per_island[element->island] += (efa->len > 2) ? efa->len - 2 : 0;
1208                 }
1209         }
1210
1211         if (!stitch_process_data(state, scene, 0)) {
1212                 stitch_state_delete(state);
1213                 return 0;
1214         }
1215
1216         stitch_update_header(state, C);
1217         return 1;
1218 }
1219
1220 static int stitch_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1221 {
1222         Object *obedit = CTX_data_edit_object(C);
1223         if (!stitch_init(C, op))
1224                 return OPERATOR_CANCELLED;
1225
1226         WM_event_add_modal_handler(C, op);
1227         WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1228         return OPERATOR_RUNNING_MODAL;
1229 }
1230
1231 static void stitch_exit(bContext *C, wmOperator *op, int finished)
1232 {
1233         StitchState *stitch_state;
1234         Scene *scene;
1235         SpaceImage *sima;
1236         ScrArea *sa = CTX_wm_area(C);
1237         Object *obedit;
1238
1239         scene = CTX_data_scene(C);
1240         obedit = CTX_data_edit_object(C);
1241         sima = CTX_wm_space_image(C);
1242
1243         stitch_state = (StitchState *)op->customdata;
1244
1245         if (finished) {
1246                 int i;
1247
1248                 RNA_float_set(op->ptr, "limit", stitch_state->limit_dist);
1249                 RNA_boolean_set(op->ptr, "use_limit", stitch_state->use_limit);
1250                 RNA_boolean_set(op->ptr, "snap_islands", stitch_state->snap_islands);
1251                 RNA_int_set(op->ptr, "static_island", stitch_state->static_island);
1252                 RNA_boolean_set(op->ptr, "midpoint_snap", stitch_state->midpoints);
1253
1254                 /* Store selection for re-execution of stitch */
1255                 for (i = 0; i < stitch_state->selection_size; i++) {
1256                         PointerRNA itemptr;
1257                         UvElement *element = stitch_state->selection_stack[i];
1258
1259                         RNA_collection_add(op->ptr, "selection", &itemptr);
1260
1261                         RNA_int_set(&itemptr, "face_index", BM_elem_index_get(element->face));
1262
1263                         RNA_int_set(&itemptr, "element_index", element->tfindex);
1264                 }
1265
1266
1267                 uvedit_live_unwrap_update(sima, scene, obedit);
1268         }
1269
1270         if (sa)
1271                 ED_area_headerprint(sa, NULL);
1272
1273         DAG_id_tag_update(obedit->data, 0);
1274         WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1275
1276         stitch_state_delete(stitch_state);
1277         op->customdata = NULL;
1278
1279         stitch_preview_delete();
1280 }
1281
1282
1283 static int stitch_cancel(bContext *C, wmOperator *op)
1284 {
1285         stitch_exit(C, op, 0);
1286         return OPERATOR_CANCELLED;
1287 }
1288
1289
1290 static int stitch_exec(bContext *C, wmOperator *op)
1291 {
1292         Scene *scene = CTX_data_scene(C);
1293
1294         if (!stitch_init(C, op))
1295                 return OPERATOR_CANCELLED;
1296         if (stitch_process_data((StitchState *)op->customdata, scene, 1)) {
1297                 stitch_exit(C, op, 1);
1298                 return OPERATOR_FINISHED;
1299         }
1300         else {
1301                 return stitch_cancel(C, op);
1302         }
1303 }
1304
1305 static void stitch_select(bContext *C, Scene *scene, wmEvent *event, StitchState *stitch_state)
1306 {
1307         /* add uv under mouse to processed uv's */
1308         float co[2];
1309         NearestHit hit;
1310         ARegion *ar = CTX_wm_region(C);
1311         Image *ima = CTX_data_edit_image(C);
1312
1313         UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
1314         uv_find_nearest_vert(scene, ima, stitch_state->em, co, NULL, &hit);
1315
1316         if (hit.efa) {
1317                 /* Add vertex to selection, deselect all common uv's of vert other
1318                  * than selected and update the preview. This behavior was decided so that
1319                  * you can do stuff like deselect the opposite stitchable vertex and the initial still gets deselected */
1320
1321                 /* This works due to setting of tmp in find nearest uv vert */
1322                 UvElement *element = ED_uv_element_get(stitch_state->element_map, hit.efa, hit.l);
1323                 stitch_select_uv(element, stitch_state, 0);
1324
1325         }
1326 }
1327
1328 static int stitch_modal(bContext *C, wmOperator *op, wmEvent *event)
1329 {
1330         StitchState *stitch_state;
1331         Scene *scene = CTX_data_scene(C);
1332
1333         stitch_state = (StitchState *)op->customdata;
1334
1335         switch (event->type) {
1336                 case MIDDLEMOUSE:
1337                         return OPERATOR_PASS_THROUGH;
1338
1339                 /* Cancel */
1340                 case ESCKEY:
1341                         return stitch_cancel(C, op);
1342
1343
1344                 case LEFTMOUSE:
1345                         if (event->shift && (U.flag & USER_LMOUSESELECT)) {
1346                                 if (event->val == KM_RELEASE) {
1347                                         stitch_select(C, scene, event, stitch_state);
1348
1349                                         if (!stitch_process_data(stitch_state, scene, 0)) {
1350                                                 return stitch_cancel(C, op);
1351                                         }
1352                                 }
1353                                 break;
1354                         }
1355                 case PADENTER:
1356                 case RETKEY:
1357                         if (stitch_process_data(stitch_state, scene, 1)) {
1358                                 stitch_exit(C, op, 1);
1359                                 return OPERATOR_FINISHED;
1360                         }
1361                         else {
1362                                 return stitch_cancel(C, op);
1363                         }
1364
1365                 /* Increase limit */
1366                 case PADPLUSKEY:
1367                 case WHEELUPMOUSE:
1368                         if (event->alt) {
1369                                 stitch_state->limit_dist += 0.01f;
1370                                 if (!stitch_process_data(stitch_state, scene, 0)) {
1371                                         return stitch_cancel(C, op);
1372                                 }
1373                                 break;
1374                         }
1375                         else {
1376                                 return OPERATOR_PASS_THROUGH;
1377                         }
1378                 /* Decrease limit */
1379                 case PADMINUS:
1380                 case WHEELDOWNMOUSE:
1381                         if (event->alt) {
1382                                 stitch_state->limit_dist -= 0.01f;
1383                                 stitch_state->limit_dist = MAX2(0.01f, stitch_state->limit_dist);
1384                                 if (!stitch_process_data(stitch_state, scene, 0)) {
1385                                         return stitch_cancel(C, op);
1386                                 }
1387                                 break;
1388                         }
1389                         else {
1390                                 return OPERATOR_PASS_THROUGH;
1391                         }
1392
1393                 /* Use Limit (Default off)*/
1394                 case LKEY:
1395                         if (event->val == KM_PRESS) {
1396                                 stitch_state->use_limit = !stitch_state->use_limit;
1397                                 if (!stitch_process_data(stitch_state, scene, 0)) {
1398                                         return stitch_cancel(C, op);
1399                                 }
1400                                 break;
1401                         }
1402                         return OPERATOR_RUNNING_MODAL;
1403
1404                 case IKEY:
1405                         if (event->val == KM_PRESS) {
1406                                 stitch_state->static_island++;
1407                                 stitch_state->static_island %= stitch_state->element_map->totalIslands;
1408
1409                                 if (!stitch_process_data(stitch_state, scene, 0)) {
1410                                         return stitch_cancel(C, op);
1411                                 }
1412                                 break;
1413                         }
1414                         return OPERATOR_RUNNING_MODAL;
1415
1416                 case MKEY:
1417                         if (event->val == KM_PRESS) {
1418                                 stitch_state->midpoints = !stitch_state->midpoints;
1419                                 if (!stitch_process_data(stitch_state, scene, 0)) {
1420                                         return stitch_cancel(C, op);
1421                                 }
1422                         }
1423                         break;
1424
1425                 /* Select geometry*/
1426                 case RIGHTMOUSE:
1427                         if (!event->shift) {
1428                                 return stitch_cancel(C, op);
1429                         }
1430                         if (event->val == KM_RELEASE && !(U.flag & USER_LMOUSESELECT)) {
1431                                 stitch_select(C, scene, event, stitch_state);
1432
1433                                 if (!stitch_process_data(stitch_state, scene, 0)) {
1434                                         return stitch_cancel(C, op);
1435                                 }
1436                                 break;
1437                         }
1438                         return OPERATOR_RUNNING_MODAL;
1439
1440                 /* snap islands on/off */
1441                 case SKEY:
1442                         if (event->val == KM_PRESS) {
1443                                 stitch_state->snap_islands = !stitch_state->snap_islands;
1444                                 if (!stitch_process_data(stitch_state, scene, 0)) {
1445                                         return stitch_cancel(C, op);
1446                                 }
1447                                 break;
1448                         }
1449                         else {
1450                                 return OPERATOR_RUNNING_MODAL;
1451                         }
1452
1453                 default:
1454                         return OPERATOR_RUNNING_MODAL;
1455         }
1456
1457         /* if updated settings, renew feedback message */
1458         stitch_update_header(stitch_state, C);
1459         ED_region_tag_redraw(CTX_wm_region(C));
1460         return OPERATOR_RUNNING_MODAL;
1461 }
1462
1463 void UV_OT_stitch(wmOperatorType *ot)
1464 {
1465         PropertyRNA *prop;
1466
1467         /* identifiers */
1468         ot->name = "Stitch";
1469         ot->description = "Stitch selected UV vertices by proximity";
1470         ot->idname = "UV_OT_stitch";
1471         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1472         
1473         /* api callbacks */
1474         ot->invoke = stitch_invoke;
1475         ot->modal = stitch_modal;
1476         ot->exec = stitch_exec;
1477         ot->cancel = stitch_cancel;
1478         ot->poll = ED_operator_uvedit;
1479
1480         /* properties */
1481         RNA_def_boolean(ot->srna, "use_limit", 0, "Use Limit", "Stitch UVs within a specified limit distance");
1482         RNA_def_boolean(ot->srna, "snap_islands", 1, "Snap Islands",
1483                         "Snap islands together (on edge stitch mode, rotates the islands too)");
1484
1485         RNA_def_float(ot->srna, "limit", 0.01f, 0.0f, FLT_MAX, "Limit",
1486                       "Limit distance in normalized coordinates", 0.0, FLT_MAX);
1487         RNA_def_int(ot->srna, "static_island", 0, 0, INT_MAX, "Static Island",
1488                     "Island that stays in place when stitching islands", 0, INT_MAX);
1489         RNA_def_boolean(ot->srna, "midpoint_snap", 0, "Snap At Midpoint",
1490                         "UVs are stitched at midpoint instead of at static island");
1491         prop = RNA_def_collection_runtime(ot->srna, "selection", &RNA_SelectedUvElement, "Selection", "");
1492         /* Selection should not be editable or viewed in toolbar */
1493         RNA_def_property_flag(prop, PROP_HIDDEN);
1494 }