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