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