svn merge ^/trunk/blender -r43611:43616
[blender.git] / source / blender / editors / uvedit / uvedit_smart_stitch.c
1
2 #if 0 /* BMESH TODO */
3
4 /*
5  * ***** BEGIN GPL LICENSE BLOCK *****
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
22  * All rights reserved.
23  *
24  * The Original Code is: all of this file.
25  *
26  * Contributor(s): Antony Riakiotakis.
27  *
28  * ***** END GPL LICENSE BLOCK *****
29  */
30
31 /** \file blender/editors/uvedit/uvedit_stitch.c
32  *  \ingroup eduv
33  */
34
35
36 #include <stdlib.h>
37 #include <string.h>
38 #include <math.h>
39
40 #include "MEM_guardedalloc.h"
41
42 #include "DNA_object_types.h"
43 #include "DNA_meshdata_types.h"
44 #include "DNA_scene_types.h"
45
46 #include "BLI_editVert.h"
47 #include "BLI_ghash.h"
48 #include "BLI_math.h"
49 #include "BLI_math_vector.h"
50 #include "BLI_string.h"
51
52 #include "BKE_context.h"
53 #include "BKE_customdata.h"
54 #include "BKE_depsgraph.h"
55 #include "BKE_mesh.h"
56 #include "BKE_tessmesh.h"
57
58 #include "ED_mesh.h"
59 #include "ED_uvedit.h"
60 #include "ED_screen.h"
61
62 #include "RNA_access.h"
63 #include "RNA_define.h"
64
65 #include "WM_api.h"
66 #include "WM_types.h"
67
68 #include "UI_view2d.h"
69
70 #include "uvedit_intern.h"
71
72 /* ********************** smart stitch operator *********************** */
73
74
75 struct IslandStitchData;
76
77 /* 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
78  * elements of the island except from the stitchable */
79 typedef struct IslandStitchData{
80         /* rotation can be used only for edges, for vertices there is no such notion */
81         float rotation;
82         float translation[2];
83         /* Used for rotation, the island will rotate around this point */
84         float medianPoint[2];
85         int numOfElements;
86         int num_rot_elements;
87         /* flag to remember if island has been added for preview */
88         char addedForPreview;
89         /* flag an island to be considered for determining static island */
90         char stitchableCandidate;
91         /* if edge rotation is used, flag so that vertex rotation is not used */
92         char use_edge_rotation;
93 }IslandStitchData;
94
95 /* just for averaging UVs */
96 typedef struct UVVertAverage {
97         float uv[2];
98         unsigned short count;
99 } UVVertAverage;
100
101 typedef struct UvEdge {
102         /* index to uv buffer */
103         unsigned int uv1;
104         unsigned int uv2;
105         /* general use flag (Used to check if edge is boundary here, and propagates to adjacency elements) */
106         char flag;
107         /* element that guarantees element->face has the face on element->tfindex and element->tfindex+1 is the second uv */
108         UvElement *element;
109 }UvEdge;
110
111
112 /* stitch state object */
113 typedef struct StitchState {
114         /* use limit flag */
115         char use_limit;
116         /* limit to operator, same as original operator */
117         float limit_dist;
118         /* snap uv islands together during stitching */
119         char snap_islands;
120         /* stich at midpoints or at islands */
121         char midpoints;
122         /* editmesh, cached for use in modal handler */
123         EditMesh *em;
124         /* element map for getting info about uv connectivity */
125         UvElementMap *element_map;
126         /* edge container */
127         UvEdge *uvedges;
128         /* container of first of a group of coincident uvs, these will be operated upon */
129         UvElement **uvs;
130         /* maps uvelements to their first coincident uv */
131         int *map;
132         /* 2D normals per uv to calculate rotation for snapping */
133         float *normals;
134         /* edge storage */
135         UvEdge *edges;
136
137         /* count of separate uvs and edges */
138         int total_boundary_edges;
139         int total_separate_uvs;
140         /* hold selection related information */
141         UvElement **selection_stack;
142         int selection_size;
143         /* island that stays in place */
144         int static_island;
145         /* store number of primitives per face so that we can allocate the active island buffer later */
146         unsigned int *quads_per_island;
147         unsigned int *tris_per_island;
148 } StitchState;
149
150
151 /*
152  * defines for UvElement flags
153  */
154 #define STITCH_SELECTED 1
155 #define STITCH_STITCHABLE 2
156 #define STITCH_PROCESSED 4
157 #define STITCH_BOUNDARY 8
158 #define STITCH_STITCHABLE_CANDIDATE 16
159
160 #define STITCH_NO_PREVIEW -1
161
162 /* previewer stuff (see uvedit_intern.h for more info) */
163 static StitchPreviewer *_stitch_preview;
164
165 /* constructor */
166 static StitchPreviewer * stitch_preview_init(void)
167 {
168         _stitch_preview = MEM_mallocN(sizeof(StitchPreviewer), "stitch_previewer");
169         _stitch_preview->preview_quads = NULL;
170         _stitch_preview->preview_tris = NULL;
171         _stitch_preview->preview_stitchable = NULL;
172         _stitch_preview->preview_unstitchable = NULL;
173
174         _stitch_preview->num_quads = 0;
175         _stitch_preview->num_tris = 0;
176         _stitch_preview->num_stitchable = 0;
177         _stitch_preview->num_unstitchable = 0;
178
179         _stitch_preview->static_quads = NULL;
180         _stitch_preview->static_tris = NULL;
181
182         _stitch_preview->num_static_tris = 0;
183         _stitch_preview->num_static_quads = 0;
184
185         return _stitch_preview;
186 }
187
188 /* destructor...yeah this should be C++ :) */
189 static void stitch_preview_delete(void)
190 {
191         if(_stitch_preview)
192         {
193                 if(_stitch_preview->preview_quads){
194                         MEM_freeN(_stitch_preview->preview_quads);
195                         _stitch_preview->preview_quads = NULL;
196                 }
197                 if(_stitch_preview->preview_tris){
198                         MEM_freeN(_stitch_preview->preview_tris);
199                         _stitch_preview->preview_tris = NULL;
200                 }
201                 if(_stitch_preview->preview_stitchable){
202                         MEM_freeN(_stitch_preview->preview_stitchable);
203                         _stitch_preview->preview_stitchable = NULL;
204                 }
205                 if(_stitch_preview->preview_unstitchable){
206                         MEM_freeN(_stitch_preview->preview_unstitchable);
207                         _stitch_preview->preview_unstitchable = NULL;
208                 }
209                 if(_stitch_preview->static_quads){
210                         MEM_freeN(_stitch_preview->static_quads);
211                         _stitch_preview->static_quads = NULL;
212                 }
213                 if(_stitch_preview->static_tris){
214                         MEM_freeN(_stitch_preview->static_tris);
215                         _stitch_preview->static_tris = NULL;
216                 }
217                 MEM_freeN(_stitch_preview);
218                 _stitch_preview = NULL;
219         }
220 }
221
222
223 /* "getter method" */
224 StitchPreviewer *uv_get_stitch_previewer(void)
225 {
226         return _stitch_preview;
227 }
228
229 #define HEADER_LENGTH 256
230
231 /* This function updates the header of the UV editor when the stitch tool updates its settings */
232 static void stitch_update_header(StitchState *stitch_state, bContext *C)
233 {
234         static char str[] = "(S)nap %s, (M)idpoints %s, (L)imit %.2f (Alt Wheel adjust) %s, Switch (I)sland, shift select vertices";
235
236         char msg[HEADER_LENGTH];
237         ScrArea *sa= CTX_wm_area(C);
238
239         if(sa) {
240                 BLI_snprintf(msg, HEADER_LENGTH, str,
241                                 stitch_state->snap_islands? "On" : "Off",
242                                 stitch_state->midpoints? "On": "Off",
243                                 stitch_state->limit_dist,
244                                 stitch_state->use_limit? "On" : "Off");
245
246                 ED_area_headerprint(sa, msg);
247         }
248 }
249
250 static int getNumOfIslandUvs(UvElementMap *elementMap, int island){
251         if(island == elementMap->totalIslands-1){
252                 return elementMap->totalUVs - elementMap->islandIndices[island];
253         }else{
254                 return elementMap->islandIndices[island+1] - elementMap->islandIndices[island];
255         }
256 }
257
258 static void stitch_uv_rotate(float rotation, float medianPoint[2], float uv[2]){
259         float uv_rotation_result[2];
260
261         uv[0] -= medianPoint[0];
262         uv[1] -= medianPoint[1];
263
264         uv_rotation_result[0] = cos(rotation)*uv[0] - sin(rotation)*uv[1];
265         uv_rotation_result[1] = sin(rotation)*uv[0] + cos(rotation)*uv[1];
266
267         uv[0] = uv_rotation_result[0] + medianPoint[0];
268         uv[1] = uv_rotation_result[1] + medianPoint[1];
269 }
270
271 static int stitch_check_uvs_stitchable(UvElement *element, UvElement *element_iter, StitchState *state){
272         float limit;
273         int do_limit;
274
275         if(element_iter == element){
276                 return 0;
277         }
278
279         limit = state->limit_dist;
280         do_limit = state->use_limit;
281
282         if(do_limit){
283                 MTFace *mtface_orig = CustomData_em_get(&state->em->fdata, element->face->data, CD_MTFACE);
284                 MTFace *mtface_iter = CustomData_em_get(&state->em->fdata, element_iter->face->data, CD_MTFACE);
285
286                 if(fabs(mtface_orig->uv[element->tfindex][0] - mtface_iter->uv[element_iter->tfindex][0]) < limit
287                         && fabs(mtface_orig->uv[element->tfindex][1] - mtface_iter->uv[element_iter->tfindex][1]) < limit){
288                         return 1;
289                 }else
290                         return 0;
291         }else
292                 return 1;
293 }
294
295
296 static int stitch_check_uvs_state_stitchable(UvElement *element, UvElement *element_iter, StitchState *state){
297         if((state->snap_islands && element->island == element_iter->island) ||
298                         (!state->midpoints && element->island == element_iter->island))
299                 return 0;
300
301         return stitch_check_uvs_stitchable(element, element_iter, state);
302 }
303
304
305 /* calculate snapping for islands */
306 static void stitch_calculate_island_snapping(StitchState *state, StitchPreviewer *preview, IslandStitchData *island_stitch_data, int final){
307         int i;
308         EditFace *efa;
309         MTFace *mt;
310         UvElement *element;
311
312         for(i = 0; i <  state->element_map->totalIslands; i++){
313                 if(island_stitch_data[i].addedForPreview){
314                         int numOfIslandUVs = 0, j;
315
316                         /* check to avoid divide by 0 */
317                         if(island_stitch_data[i].num_rot_elements>0){
318                                 island_stitch_data[i].rotation /= island_stitch_data[i].num_rot_elements;
319                                 island_stitch_data[i].medianPoint[0] /= island_stitch_data[i].numOfElements;
320                                 island_stitch_data[i].medianPoint[1] /= island_stitch_data[i].numOfElements;
321                         }
322                         island_stitch_data[i].translation[0] /= island_stitch_data[i].numOfElements;
323                         island_stitch_data[i].translation[1] /= island_stitch_data[i].numOfElements;
324                         numOfIslandUVs = getNumOfIslandUvs(state->element_map, i);
325                         element = &state->element_map->buf[state->element_map->islandIndices[i]];
326                         for(j = 0; j < numOfIslandUVs; j++, element++){
327                                 /* stitchable uvs have already been processed, don't process */
328                                 if(!(element->flag & STITCH_PROCESSED)){
329                                         efa = element->face;
330                                         mt = CustomData_em_get(&state->em->fdata, efa->data, CD_MTFACE);
331                                         if(final){
332
333                                                 stitch_uv_rotate(island_stitch_data[i].rotation, island_stitch_data[i].medianPoint, mt->uv[element->tfindex]);
334
335                                                 mt->uv[element->tfindex][0] += island_stitch_data[i].translation[0];
336                                                 mt->uv[element->tfindex][1] += island_stitch_data[i].translation[1];
337                                         }
338                                         else if(efa->tmp.l != STITCH_NO_PREVIEW){
339                                                 if(efa->v4){
340
341                                                         stitch_uv_rotate(island_stitch_data[i].rotation, island_stitch_data[i].medianPoint, &preview->preview_quads[efa->tmp.l + 2*element->tfindex]);
342
343                                                         preview->preview_quads[efa->tmp.l + 2*element->tfindex] += island_stitch_data[i].translation[0];
344                                                         preview->preview_quads[efa->tmp.l + 2*element->tfindex + 1] += island_stitch_data[i].translation[1];
345                                                 }
346                                                 else {
347
348                                                         stitch_uv_rotate(island_stitch_data[i].rotation, island_stitch_data[i].medianPoint, &preview->preview_tris[efa->tmp.l + 2*element->tfindex]);
349
350                                                         preview->preview_tris[efa->tmp.l + 2*element->tfindex]  += island_stitch_data[i].translation[0];
351                                                         preview->preview_tris[efa->tmp.l + 2*element->tfindex + 1] += island_stitch_data[i].translation[1];
352                                                 }
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         EditFace *efa1;
368         EditFace *efa2;
369         MTFace *mt1;
370         MTFace *mt2;
371         float uv1[2], uv2[2];
372         float edgecos, edgesin;
373         int index1, index2;
374         float rotation;
375
376         element1 = state->uvs[edge->uv1];
377         element2 = state->uvs[edge->uv2];
378
379         efa1 = element1->face;
380         mt1 = CustomData_em_get(&state->em->fdata, efa1->data, CD_MTFACE);
381         efa2 = element2->face;
382         mt2 = CustomData_em_get(&state->em->fdata, efa2->data, CD_MTFACE);
383
384         index1 = uvfinal_map[element1 - state->element_map->buf];
385         index2 = uvfinal_map[element2 - state->element_map->buf];
386
387         /* the idea here is to take the directions of the edges and find the rotation between final and initial
388         * direction. This, using inner and outer vector products, gives the angle. Directions are differences so... */
389         uv1[0] = mt2->uv[element2->tfindex][0] - mt1->uv[element1->tfindex][0];
390         uv1[1] = mt2->uv[element2->tfindex][1] - mt1->uv[element1->tfindex][1];
391
392         uv2[0] = uv_average[index2].uv[0] - uv_average[index1].uv[0];
393         uv2[1] = uv_average[index2].uv[1] - uv_average[index1].uv[1];
394
395         normalize_v2(uv1);
396         normalize_v2(uv2);
397
398         edgecos = uv1[0]*uv2[0] + uv1[1]*uv2[1];
399         edgesin = uv1[0]*uv2[1] - uv2[0]*uv1[1];
400
401         rotation = (edgesin > 0)? acos(MAX2(-1.0, MIN2(1.0, edgecos))): -acos(MAX2(-1.0, MIN2(1.0, edgecos)));
402
403         island_stitch_data[element1->island].num_rot_elements++;
404         island_stitch_data[element1->island].rotation += rotation;
405 }
406
407
408 static void stitch_island_calculate_vert_rotation(UvElement *element, StitchState *state, IslandStitchData *island_stitch_data)
409 {
410         float edgecos = 1, edgesin = 0;
411         int index;
412         UvElement *element_iter;
413         float rotation = 0;
414
415         if(element->island == state->static_island && !state->midpoints)
416                 return;
417
418         index = (*(&element->face->v1 + element->tfindex))->tmp.l;
419
420         element_iter = state->element_map->vert[index];
421
422         for(; element_iter; element_iter = element_iter->next){
423                 if(element_iter->separate && stitch_check_uvs_state_stitchable(element, element_iter, state)){
424                         int index_tmp1, index_tmp2;
425                         float normal[2];
426                         /* easily possible*/
427
428                         index_tmp1 = element_iter - state->element_map->buf;
429                         index_tmp1 = state->map[index_tmp1];
430                         index_tmp2 = element - state->element_map->buf;
431                         index_tmp2 = state->map[index_tmp2];
432
433                         negate_v2_v2(normal, state->normals + index_tmp2*2);
434                         edgecos = dot_v2v2(normal, state->normals + index_tmp1*2);
435                         edgesin = cross_v2v2(normal, state->normals + index_tmp1*2);
436                         rotation += (edgesin > 0)? acos(edgecos): -acos(edgecos);
437                 }
438         }
439
440         if(state->midpoints)
441                 rotation /= 2.0;
442         island_stitch_data[element->island].num_rot_elements++;
443         island_stitch_data[element->island].rotation += rotation;
444 }
445
446
447 static void stitch_state_delete(StitchState *stitch_state)
448 {
449         if(stitch_state){
450                 if(stitch_state->element_map){
451                         EDBM_free_uv_element_map(stitch_state->element_map);
452                 }
453                 if(stitch_state->uvs){
454                         MEM_freeN(stitch_state->uvs);
455                 }
456                 if(stitch_state->selection_stack){
457                         MEM_freeN(stitch_state->selection_stack);
458                 }
459                 if(stitch_state->quads_per_island){
460                         MEM_freeN(stitch_state->quads_per_island);
461                 }
462                 if(stitch_state->tris_per_island){
463                         MEM_freeN(stitch_state->tris_per_island);
464                 }
465                 if(stitch_state->map){
466                         MEM_freeN(stitch_state->map);
467                 }
468                 if(stitch_state->normals){
469                         MEM_freeN(stitch_state->normals);
470                 }
471                 if(stitch_state->edges){
472                         MEM_freeN(stitch_state->edges);
473                 }
474                 MEM_freeN(stitch_state);
475         }
476 }
477
478
479
480 /* checks for remote uvs that may be stitched with a certain uv, flags them if stitchable. */
481 static void determine_uv_stitchability(UvElement *element, StitchState *state, IslandStitchData *island_stitch_data){
482         int vert_index;
483         UvElement *element_iter;
484
485         vert_index = (*(&element->face->v1 + element->tfindex))->tmp.l;
486         element_iter = state->element_map->vert[vert_index];
487
488         for(; element_iter; element_iter = element_iter->next){
489                 if(element_iter->separate){
490                         if(element_iter == element){
491                                 continue;
492                         }
493                         if(stitch_check_uvs_stitchable(element, element_iter, state)){
494                                 island_stitch_data[element_iter->island].stitchableCandidate = 1;
495                                 island_stitch_data[element->island].stitchableCandidate = 1;
496                                 element->flag |= STITCH_STITCHABLE_CANDIDATE;
497                         }
498                 }
499         }
500 }
501
502
503 /* set preview buffer position of UV face in editface->tmp.l */
504 static void stitch_set_face_preview_buffer_position(EditFace *efa, StitchPreviewer *preview)
505 {
506         if(efa->tmp.l == STITCH_NO_PREVIEW)
507         {
508                 if(efa->v4)
509                 {
510                         efa->tmp.l = preview->num_quads*8;
511                         preview->num_quads++;
512                 } else {
513                         efa->tmp.l = preview->num_tris*6;
514                         preview->num_tris++;
515                 }
516         }
517 }
518
519
520 /* setup face preview for all coincident uvs and their faces */
521 static void stitch_setup_face_preview_for_uv_group(UvElement *element, StitchState *state, IslandStitchData *island_stitch_data){
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);
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         UvElement *element_iter;
542         StitchPreviewer *preview;
543
544         preview = uv_get_stitch_previewer();
545         element_iter = state->element_map->vert[(*(&element->face->v1 + element->tfindex))->tmp.l];
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);
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 = uv_get_stitch_previewer();
573         IslandStitchData *island_stitch_data = NULL;
574         int previous_island = state->static_island;
575         EditFace *efa;
576         EditVert *ev;
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
582         /* cleanup previous preview */
583         stitch_preview_delete();
584         preview = stitch_preview_init();
585         if(preview == NULL)
586                 return 0;
587         /* each face holds its position in the preview buffer in tmp. -1 is uninitialized */
588         for(efa = state->em->faces.first; efa; efa = efa->next){
589                 efa->tmp.l = STITCH_NO_PREVIEW;
590         }
591
592         island_stitch_data = MEM_callocN(sizeof(*island_stitch_data)*state->element_map->totalIslands, "stitch_island_data");
593         if(!island_stitch_data){
594                 return 0;
595         }
596
597         /* store indices to editVerts. */
598         for(ev = state->em->verts.first, i = 0; ev; ev = ev->next, i++){
599                 ev->tmp.l = i;
600         }
601
602         /*****************************************
603          *  First determine stitchability of uvs *
604          *****************************************/
605
606         for(i = 0; i < state->selection_size; i++){
607                 UvElement *element = state->selection_stack[i];
608                 determine_uv_stitchability(element, state, island_stitch_data);
609         }
610
611         /* set static island to one that is added for preview */
612         state->static_island %= state->element_map->totalIslands;
613         while(!(island_stitch_data[state->static_island].stitchableCandidate)){
614                 state->static_island++;
615                 state->static_island %= state->element_map->totalIslands;
616                 /* this is entirely possible if for example limit stitching with no stitchable verts or no selection */
617                 if(state->static_island == previous_island)
618                         break;
619         }
620
621         for(i = 0; i < state->selection_size; i++){
622                 UvElement *element = state->selection_stack[i];
623                 if(element->flag & STITCH_STITCHABLE_CANDIDATE){
624                         element->flag &= ~STITCH_STITCHABLE_CANDIDATE;
625                         stitch_validate_stichability(element, state, island_stitch_data);
626                 }else{
627                         /* add to preview for unstitchable */
628                         preview->num_unstitchable++;
629                 }
630         }
631
632         /*****************************************
633          *  Setup preview for stitchable islands *
634          *****************************************/
635         if(state->snap_islands){
636                 for(i = 0; i <  state->element_map->totalIslands; i++){
637                         if(island_stitch_data[i].addedForPreview){
638                                 int numOfIslandUVs = 0, j;
639                                 UvElement *element;
640                                 numOfIslandUVs = getNumOfIslandUvs(state->element_map, i);
641                                 element = &state->element_map->buf[state->element_map->islandIndices[i]];
642                                 for(j = 0; j < numOfIslandUVs; j++, element++){
643                                         stitch_set_face_preview_buffer_position(element->face, preview);
644                                 }
645                         }
646                 }
647         }
648
649         /*********************************************************************
650          * Setup the preview buffers and fill them with the appropriate data *
651          *********************************************************************/
652         if(!final){
653                 unsigned int tricount = 0, quadcount = 0;
654                 int stitchBufferIndex = 0, unstitchBufferIndex = 0;
655                 /* initialize the preview buffers */
656                 preview->preview_quads = (float *)MEM_mallocN(preview->num_quads*sizeof(float)*8, "quad_uv_stitch_prev");
657                 preview->preview_tris = (float *)MEM_mallocN(preview->num_tris*sizeof(float)*6, "tri_uv_stitch_prev");
658
659                 preview->preview_stitchable = (float *)MEM_mallocN(preview->num_stitchable*sizeof(float)*2, "stitch_preview_stichable_data");
660                 preview->preview_unstitchable = (float *)MEM_mallocN(preview->num_unstitchable*sizeof(float)*2, "stitch_preview_unstichable_data");
661
662                 preview->static_quads = (float *)MEM_mallocN(state->quads_per_island[state->static_island]*sizeof(float)*8, "static_island_preview_quads");
663                 preview->static_tris = (float *)MEM_mallocN(state->tris_per_island[state->static_island]*sizeof(float)*6, "static_island_preview_tris");
664
665                 preview->num_static_quads = state->quads_per_island[state->static_island];
666                 preview->num_static_tris = state->tris_per_island[state->static_island];
667                 /* will cause cancel and freeing of all data structures so OK */
668                 if(!preview->preview_quads || !preview->preview_tris || !preview->preview_stitchable || !preview->preview_unstitchable){
669                         return 0;
670                 }
671
672                 /* copy data from MTFaces to the preview display buffers */
673                 for(efa = state->em->faces.first; efa; efa = efa->next){
674                         MTFace *mt = CustomData_em_get(&state->em->fdata, efa->data, CD_MTFACE);
675                         UvElement *element = ED_get_uv_element(state->element_map, efa, 0);
676
677                         if(element){
678                                 if(efa->tmp.l != STITCH_NO_PREVIEW){
679                                         if(efa->v4) {
680                                                 memcpy(preview->preview_quads+efa->tmp.l, &mt->uv[0][0], 8*sizeof(float));
681                                         } else {
682                                                 memcpy(preview->preview_tris+efa->tmp.l, &mt->uv[0][0], 6*sizeof(float));
683                                         }
684                                 }
685
686                                 if(element->island == state->static_island){
687                                         if(efa->v4) {
688                                                 memcpy(preview->static_quads + quadcount*8, &mt->uv[0][0], 8*sizeof(float));
689                                                 quadcount++;
690                                         } else {
691                                                 memcpy(preview->static_tris + tricount*6, &mt->uv[0][0], 6*sizeof(float));
692                                                 tricount++;
693                                         }
694                                 }
695                         }
696                 }
697
698                 /* fill the appropriate preview buffers */
699                 for(i = 0; i < state->total_separate_uvs; i++){
700                         UvElement *element = (UvElement *)state->uvs[i];
701                         if(element->flag & STITCH_STITCHABLE){
702                                 MTFace *mt;
703                                 efa = element->face;
704                                 mt = CustomData_em_get(&state->em->fdata, efa->data, CD_MTFACE);
705
706                                 preview->preview_stitchable[stitchBufferIndex*2] = mt->uv[element->tfindex][0];
707                                 preview->preview_stitchable[stitchBufferIndex*2 + 1] = mt->uv[element->tfindex][1];
708                                 stitchBufferIndex++;
709                         }
710                         else if(element->flag & STITCH_SELECTED){
711                                 MTFace *mt;
712                                 efa = element->face;
713                                 mt = CustomData_em_get(&state->em->fdata, efa->data, CD_MTFACE);
714
715                                 preview->preview_unstitchable[unstitchBufferIndex*2] = mt->uv[element->tfindex][0];
716                                 preview->preview_unstitchable[unstitchBufferIndex*2 + 1] = mt->uv[element->tfindex][1];
717                                 unstitchBufferIndex++;
718                         }
719                 }
720         }
721
722         /******************************************************
723          * Here we calculate the final coordinates of the uvs *
724          ******************************************************/
725
726         final_position = MEM_callocN(state->selection_size*sizeof(*final_position), "stitch_uv_average");
727         uvfinal_map = MEM_mallocN(state->element_map->totalUVs*sizeof(*uvfinal_map), "stitch_uv_final_map");
728
729         /* first pass, calculate final position for stitchable uvs of the static island */
730         for(i = 0; i < state->selection_size; i++){
731                 UvElement *element = state->selection_stack[i];
732                 if(element->flag & STITCH_STITCHABLE){
733                         MTFace *mt;
734
735                         UvElement *element_iter;
736
737                         uvfinal_map[element - state->element_map->buf] = i;
738
739                         efa = element->face;
740                         mt = CustomData_em_get(&state->em->fdata, efa->data, CD_MTFACE);
741
742                         final_position[i].uv[0] = mt->uv[element->tfindex][0];
743                         final_position[i].uv[1] = mt->uv[element->tfindex][1];
744                         final_position[i].count = 1;
745
746                         if(state->snap_islands && element->island == state->static_island && !stitch_midpoints)
747                                 continue;
748
749                         element_iter = state->element_map->vert[(*(&element->face->v1 + element->tfindex))->tmp.l];
750
751                         for(;element_iter; element_iter = element_iter->next){
752                                 if(element_iter->separate){
753                                         if(stitch_check_uvs_state_stitchable(element, element_iter, state)){
754                                                 efa = element_iter->face;
755                                                 mt = CustomData_em_get(&state->em->fdata, efa->data, CD_MTFACE);
756                                                 if(stitch_midpoints){
757                                                         final_position[i].uv[0] += mt->uv[element_iter->tfindex][0];
758                                                         final_position[i].uv[1] += mt->uv[element_iter->tfindex][1];
759                                                         final_position[i].count++;
760                                                 }else if(element_iter->island == state->static_island){
761                                                         /* if multiple uvs on the static island exist,
762                                                          * last checked remains. to disambiguate we need to limit or use
763                                                          * edge stitch */
764                                                         final_position[i].uv[0] = mt->uv[element_iter->tfindex][0];
765                                                         final_position[i].uv[1] = mt->uv[element_iter->tfindex][1];
766                                                 }
767                                         }
768                                 }
769                         }
770                 }
771                 if(stitch_midpoints){
772                         final_position[i].uv[0] /= final_position[i].count;
773                         final_position[i].uv[1] /= final_position[i].count;
774                 }
775         }
776
777         /* second pass, calculate island rotation and translation before modifying any uvs */
778         if(state->snap_islands){
779                 for(i = 0; i < state->selection_size; i++){
780                         UvElement *element = state->selection_stack[i];
781                         if(element->flag & STITCH_STITCHABLE){
782                                 MTFace *mt;
783                                 efa = element->face;
784                                 mt = CustomData_em_get(&state->em->fdata, efa->data, CD_MTFACE);
785
786                                 /* accumulate each islands' translation from stitchable elements. it is important to do here
787                                  * because in final pass MTFaces get modified and result is zero. */
788                                 island_stitch_data[element->island].translation[0] += final_position[i].uv[0] - mt->uv[element->tfindex][0];
789                                 island_stitch_data[element->island].translation[1] += final_position[i].uv[1] - mt->uv[element->tfindex][1];
790                                 island_stitch_data[element->island].medianPoint[0] += mt->uv[element->tfindex][0];
791                                 island_stitch_data[element->island].medianPoint[1] += mt->uv[element->tfindex][1];
792                                 island_stitch_data[element->island].numOfElements++;
793                         }
794                 }
795
796                 /* only calculate rotation when an edge has been fully selected */
797                 for(i = 0; i < state->total_boundary_edges; i++){
798                         UvEdge *edge = state->edges+i;
799                         if((state->uvs[edge->uv1]->flag & STITCH_STITCHABLE) && (state->uvs[edge->uv2]->flag & STITCH_STITCHABLE)){
800                                 stitch_island_calculate_edge_rotation(edge, state, final_position, uvfinal_map, island_stitch_data);
801                                 island_stitch_data[state->uvs[edge->uv1]->island].use_edge_rotation = 1;
802                         }
803                 }
804
805                 for(i = 0; i < state->selection_size; i++){
806                         UvElement *element = state->selection_stack[i];
807                         if(!island_stitch_data[element->island].use_edge_rotation){
808                                 if(element->flag & STITCH_STITCHABLE){
809                                         stitch_island_calculate_vert_rotation(element, state, island_stitch_data);
810                                 }
811                         }
812                 }
813
814         }
815
816         /* third pass, propagate changes to coincident uvs */
817         for(i = 0; i < state->selection_size; i++){
818                 UvElement *element = state->selection_stack[i];
819                 if(element->flag & STITCH_STITCHABLE){
820                         UvElement *element_iter = element;
821                         /* propagate to coincident uvs */
822                         do{
823                                 MTFace *mt;
824
825                                 efa = element_iter->face;
826                                 mt = CustomData_em_get(&state->em->fdata, efa->data, CD_MTFACE);
827
828                                 element_iter->flag |= STITCH_PROCESSED;
829                                 /* either flush to preview or to the MTFace, if final */
830                                 if(final){
831                                         mt->uv[element_iter->tfindex][0] = final_position[i].uv[0];
832                                         mt->uv[element_iter->tfindex][1] = final_position[i].uv[1];
833
834                                         uvedit_uv_select(scene, efa, mt, element_iter->tfindex);
835                                 }else if(efa->tmp.l != STITCH_NO_PREVIEW){
836                                         if(efa->v4){
837                                                 *(preview->preview_quads+efa->tmp.l + element_iter->tfindex*2) = final_position[i].uv[0];
838                                                 *(preview->preview_quads+efa->tmp.l + element_iter->tfindex*2 + 1) = final_position[i].uv[1];
839                                         }else{
840                                                 *(preview->preview_tris+efa->tmp.l + element_iter->tfindex*2) = final_position[i].uv[0];
841                                                 *(preview->preview_tris+efa->tmp.l + element_iter->tfindex*2 + 1) = final_position[i].uv[1];
842                                         }
843                                 }
844
845                                 /* end of calculations, keep only the selection flag */
846                                 if( (!state->snap_islands) || ((!stitch_midpoints) && (element_iter->island == state->static_island))) {
847                                         element_iter->flag &= STITCH_SELECTED;
848                                 }
849
850                                 element_iter = element_iter->next;
851                         }while(element_iter && !element_iter->separate);
852                 }
853         }
854
855         /* final pass, calculate Island translation/rotation if needed */
856         if(state->snap_islands){
857                 stitch_calculate_island_snapping(state, preview, island_stitch_data, final);
858         }
859
860         MEM_freeN(final_position);
861         MEM_freeN(uvfinal_map);
862         MEM_freeN(island_stitch_data);
863
864         return 1;
865 }
866
867 /* Stitch hash initialisation functions */
868 static unsigned int     uv_edge_hash(const void *key){
869         UvEdge *edge = (UvEdge *)key;
870         return
871                 BLI_ghashutil_inthash(SET_INT_IN_POINTER(edge->uv2)) +
872                 BLI_ghashutil_inthash(SET_INT_IN_POINTER(edge->uv1));
873 }
874
875 static int uv_edge_compare(const void *a, const void *b){
876         UvEdge *edge1 = (UvEdge *)a;
877         UvEdge *edge2 = (UvEdge *)b;
878
879         if((edge1->uv1 == edge2->uv1) && (edge1->uv2 == edge2->uv2)){
880                 return 0;
881         }
882         return 1;
883 }
884
885
886 /* Select all common uvs */
887 static void stitch_select_uv(UvElement *element, StitchState *stitch_state, int always_select)
888 {
889         /* This works due to setting of tmp in find nearest uv vert */
890         UvElement *element_iter;
891         UvElement **selection_stack = stitch_state->selection_stack;
892
893         element_iter = stitch_state->element_map->vert[(*(&element->face->v1 + element->tfindex))->tmp.l];
894         /* first deselect all common uvs */
895         for(; element_iter; element_iter = element_iter->next){
896                 if(element_iter->separate){
897                         /* only separators go to selection */
898                         if(element_iter->flag & STITCH_SELECTED){
899                                 int i;
900                                 if(always_select)
901                                         continue;
902
903                                 element_iter->flag &= ~STITCH_SELECTED;
904                                 for(i = 0; i < stitch_state->selection_size; i++){
905                                         if(selection_stack[i] == element_iter){
906                                                 (stitch_state->selection_size)--;
907                                                 selection_stack[i] = selection_stack[stitch_state->selection_size];
908                                                 break;
909                                         }
910                                 }
911                         }else{
912                                 element_iter->flag |= STITCH_SELECTED;
913                                 selection_stack[(stitch_state->selection_size)++] = element_iter;
914                         }
915                 }
916         }
917 }
918
919 static void stitch_calculate_edge_normal(EditMesh *em, UvEdge *edge, float *normal)
920 {
921         UvElement *element = edge->element;
922         EditFace *efa = element->face;
923         MTFace *mt = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
924         int nverts = efa->v4?4 : 3;
925         int index = (element->tfindex + 2)%nverts;
926         float tangent[2], internal[2];
927
928         sub_v2_v2v2(tangent, mt->uv[(element->tfindex + 1)%nverts],  mt->uv[element->tfindex]);
929         sub_v2_v2v2(internal, mt->uv[index],  mt->uv[element->tfindex]);
930
931         /* choose one of the normals */
932         normal[0] = tangent[1];
933         normal[1] = -tangent[0];
934
935         /* if normal points inside the face, invert */
936         if(dot_v2v2(normal, internal) > 0){
937                 normal[0] = -tangent[1];
938                 normal[1] = tangent[0];
939         }
940
941         normalize_v2(normal);
942 }
943
944 static int stitch_init(bContext *C, wmOperator *op)
945 {
946         /* for fast edge lookup... */
947         GHash *edgeHash;
948         /* ...and actual edge storage */
949         UvEdge *edges;
950         int total_edges;
951         /* maps uvelements to their first coincident uv */
952         int *map;
953         int counter = 0, i;
954         EditFace *efa;
955         EditMesh *em;
956         GHashIterator* ghi;
957         UvEdge *all_edges;
958         StitchState *state = MEM_mallocN(sizeof(StitchState), "stitch state");
959         Scene *scene = CTX_data_scene(C);
960         ToolSettings *ts = scene->toolsettings;
961
962         Object *obedit = CTX_data_edit_object(C);
963
964         op->customdata = state;
965
966         if(!state)
967                 return 0;
968
969         /* initialize state */
970         state->use_limit = RNA_boolean_get(op->ptr, "use_limit");
971         state->limit_dist = RNA_float_get(op->ptr, "limit");
972         state->em = em = BKE_mesh_get_editmesh((Mesh*)obedit->data);
973         state->snap_islands = RNA_boolean_get(op->ptr, "snap_islands");
974         state->static_island = RNA_int_get(op->ptr, "static_island");
975         state->midpoints = RNA_boolean_get(op->ptr, "midpoint_snap");
976         /* in uv synch selection, all uv's are visible */
977         if(ts->uv_flag & UV_SYNC_SELECTION){
978                 state->element_map = EDBM_make_uv_element_map(state->em, 0, 1);
979         }else{
980                 state->element_map = EDBM_make_uv_element_map(state->em, 1, 1);
981         }
982         if(!state->element_map){
983                 stitch_state_delete(state);
984                 return 0;
985         }
986
987         /* Entirely possible if redoing last operator that static island is bigger than total number of islands.
988          * This ensures we get no hang in the island checking code in stitch_process_data. */
989         state->static_island %= state->element_map->totalIslands;
990
991         /* Count 'unique' uvs */
992         for(i = 0; i < state->element_map->totalUVs; i++){
993                 if(state->element_map->buf[i].separate){
994                         counter++;
995                 }
996         }
997
998         /* Allocate the unique uv buffers */
999         state->uvs = MEM_mallocN(sizeof(*state->uvs)*counter, "uv_stitch_unique_uvs");
1000         /* internal uvs need no normals but it is hard and slow to keep a map of
1001          * normals only for boundary uvs, so allocating for all uvs */
1002         state->normals = MEM_callocN(sizeof(*state->normals)*counter*2, "uv_stitch_normals");
1003         state->total_separate_uvs = counter;
1004         /* we can at most have totalUVs edges or uvs selected. Actually they are less, considering we store only
1005          * unique uvs for processing but I am accounting for all bizarre cases, especially for edges, this way */
1006         state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack)*counter, "uv_stitch_selection_stack");
1007         state->map = map = MEM_mallocN(sizeof(*map)*state->element_map->totalUVs, "uv_stitch_unique_map");
1008         /* Allocate the edge stack */
1009         edgeHash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "stitch_edge_hash");
1010         all_edges = MEM_mallocN(sizeof(*all_edges)*state->element_map->totalUVs, "stitch_all_edges");
1011
1012         if(!state->selection_stack || !state->uvs || !map || !edgeHash || !all_edges){
1013                 stitch_state_delete(state);
1014                 return 0;
1015         }
1016
1017         /* So that we can use this as index for the UvElements */
1018         counter = -1;
1019         /* initialize the unique UVs and map */
1020         for(i = 0; i < state->em->totvert; i++){
1021                 UvElement *element = state->element_map->vert[i];
1022                 for(; element; element = element->next){
1023                         if(element->separate){
1024                                 counter++;
1025                                 state->uvs[counter] = element;
1026                         }
1027                         /* pointer arithmetic to the rescue, as always :)*/
1028                         map[element - state->element_map->buf] = counter;
1029                 }
1030         }
1031
1032         /* Now, on to generate our uv connectivity data */
1033         for(efa = state->em->faces.first, counter = 0; efa; efa = efa->next){
1034                 if((ts->uv_flag & UV_SYNC_SELECTION) || (!efa->h && efa->f & SELECT)){
1035                         int nverts = efa->v4 ? 4 : 3;
1036
1037                         for(i = 0; i < nverts; i++){
1038                                 UvElement *element = ED_get_uv_element(state->element_map, efa, i);
1039                                 int offset1, itmp1 = element - state->element_map->buf;
1040                                 int offset2, itmp2 = ED_get_uv_element(state->element_map, efa, (i+1)%nverts) - state->element_map->buf;
1041
1042                                 offset1 = map[itmp1];
1043                                 offset2 = map[itmp2];
1044
1045                                 all_edges[counter].flag = 0;
1046                                 all_edges[counter].element = element;
1047                                 /* using an order policy, sort uvs according to address space. This avoids
1048                                  * Having two different UvEdges with the same uvs on different positions  */
1049                                 if(offset1 < offset2){
1050                                         all_edges[counter].uv1 = offset1;
1051                                         all_edges[counter].uv2 = offset2;
1052                                 }
1053                                 else{
1054                                         all_edges[counter].uv1 = offset2;
1055                                         all_edges[counter].uv2 = offset1;
1056                                 }
1057
1058                                 if(BLI_ghash_haskey(edgeHash, &all_edges[counter])){
1059                                         char *flag = BLI_ghash_lookup(edgeHash, &all_edges[counter]);
1060                                         *flag = 0;
1061                                 }
1062                                 else{
1063                                         BLI_ghash_insert(edgeHash, &all_edges[counter], &(all_edges[counter].flag));
1064                                         all_edges[counter].flag = STITCH_BOUNDARY;
1065                                 }
1066                                 counter++;
1067                         }
1068                 }
1069         }
1070
1071
1072         ghi = BLI_ghashIterator_new(edgeHash);
1073         total_edges = 0;
1074         /* fill the edges with data */
1075         for(; !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)){
1076                 UvEdge *edge = ((UvEdge *)BLI_ghashIterator_getKey(ghi));
1077                 if(edge->flag & STITCH_BOUNDARY){
1078                         total_edges++;
1079                 }
1080         }
1081         state->edges = edges = MEM_mallocN(sizeof(*edges)*total_edges, "stitch_edges");
1082         if(!ghi || !edges){
1083                 MEM_freeN(all_edges);
1084                 stitch_state_delete(state);
1085                 return 0;
1086         }
1087
1088         state->total_boundary_edges = total_edges;
1089
1090         /* fill the edges with data */
1091         for(i = 0, BLI_ghashIterator_init(ghi, edgeHash); !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)){
1092                 UvEdge *edge = ((UvEdge *)BLI_ghashIterator_getKey(ghi));
1093                 if(edge->flag & STITCH_BOUNDARY){
1094                         edges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(ghi));
1095                 }
1096         }
1097
1098         /* cleanup temporary stuff */
1099         BLI_ghashIterator_free(ghi);
1100         MEM_freeN(all_edges);
1101
1102         /* refill hash with new pointers to cleanup duplicates */
1103         BLI_ghash_free(edgeHash, NULL, NULL);
1104
1105         /***** calculate 2D normals for boundary uvs *****/
1106
1107         /* we use boundary edges to calculate 2D normals.
1108          * to disambiguate the direction of the normal, we also need
1109          * a point "inside" the island, that can be provided by
1110          * the opposite uv for a quad, or the next uv for a triangle. */
1111
1112         for(i = 0; i < total_edges; i++){
1113                 float normal[2];
1114                 stitch_calculate_edge_normal(em, edges + i, normal);
1115
1116                 add_v2_v2(state->normals + edges[i].uv1*2, normal);
1117                 add_v2_v2(state->normals + edges[i].uv2*2, normal);
1118
1119                 normalize_v2(state->normals + edges[i].uv1*2);
1120                 normalize_v2(state->normals + edges[i].uv2*2);
1121         }
1122
1123
1124         /***** fill selection stack *******/
1125
1126         state->selection_size = 0;
1127
1128         /* Load old selection if redoing operator with different settings */
1129         if(RNA_struct_property_is_set(op->ptr, "selection")){
1130                 int faceIndex, elementIndex;
1131                 UvElement *element;
1132
1133                 EM_init_index_arrays(em, 0, 0, 1);
1134
1135
1136                         RNA_BEGIN(op->ptr, itemptr, "selection") {
1137                                 faceIndex = RNA_int_get(&itemptr, "face_index");
1138                                 elementIndex = RNA_int_get(&itemptr, "element_index");
1139                                 efa = EM_get_face_for_index(faceIndex);
1140                                 element = ED_get_uv_element(state->element_map, efa, elementIndex);
1141                                 stitch_select_uv(element, state, 1);
1142                         }
1143                         RNA_END;
1144
1145                 EM_free_index_arrays();
1146                 /* Clear the selection */
1147                 RNA_collection_clear(op->ptr, "selection");
1148
1149         } else {
1150                 for(efa = state->em->faces.first ; efa; efa = efa->next){
1151                         int numOfVerts;
1152                         MTFace *mt;
1153                         mt = CustomData_em_get(&state->em->fdata, efa->data, CD_MTFACE);
1154                         numOfVerts = efa->v4 ? 4 : 3;
1155
1156                         for(i = 0; i < numOfVerts; i++){
1157                                 if(uvedit_uv_selected(scene, efa, mt, i)){
1158                                         UvElement *element = ED_get_uv_element(state->element_map, efa, i);
1159                                         stitch_select_uv(element, state, 1);
1160                                 }
1161                         }
1162                 }
1163         }
1164
1165         /***** initialise static island preview data *****/
1166
1167         state->quads_per_island = MEM_mallocN(sizeof(*state->quads_per_island)*state->element_map->totalIslands,
1168                         "stitch island quads");
1169         state->tris_per_island = MEM_mallocN(sizeof(*state->tris_per_island)*state->element_map->totalIslands,
1170                         "stitch island tris");
1171         for(i = 0; i < state->element_map->totalIslands; i++){
1172                 state->quads_per_island[i] = 0;
1173                 state->tris_per_island[i] = 0;
1174         }
1175
1176         for(efa = state->em->faces.first; efa; efa = efa->next){
1177                 UvElement *element = ED_get_uv_element(state->element_map, efa, 0);
1178
1179                 if(element){
1180                         if(efa->v4){
1181                                 state->quads_per_island[element->island]++;
1182                         }
1183                         else {
1184                                 state->tris_per_island[element->island]++;
1185                         }
1186                 }
1187         }
1188
1189         if(!stitch_process_data(state, scene, 0)){
1190                 stitch_state_delete(state);
1191                 return 0;
1192         }
1193
1194         stitch_update_header(state, C);
1195         return 1;
1196 }
1197
1198 static int stitch_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1199 {
1200         Object *obedit = CTX_data_edit_object(C);
1201         if(!stitch_init(C, op))
1202                 return OPERATOR_CANCELLED;
1203
1204         WM_event_add_modal_handler(C, op);
1205         WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
1206         return OPERATOR_RUNNING_MODAL;
1207 }
1208
1209 static void stitch_exit(bContext *C, wmOperator *op, int finished)
1210 {
1211         StitchState *stitch_state;
1212         Scene *scene;
1213         SpaceImage *sima;
1214         ScrArea *sa= CTX_wm_area(C);
1215         Object *obedit;
1216
1217         scene= CTX_data_scene(C);
1218         obedit= CTX_data_edit_object(C);
1219         sima= CTX_wm_space_image(C);
1220
1221         stitch_state = (StitchState *)op->customdata;
1222
1223         if(finished){
1224                 EditFace *efa;
1225                 int i;
1226
1227                 RNA_float_set(op->ptr, "limit", stitch_state->limit_dist);
1228                 RNA_boolean_set(op->ptr, "use_limit", stitch_state->use_limit);
1229                 RNA_boolean_set(op->ptr, "snap_islands", stitch_state->snap_islands);
1230                 RNA_int_set(op->ptr, "static_island", stitch_state->static_island);
1231                 RNA_boolean_set(op->ptr, "midpoint_snap", stitch_state->midpoints);
1232
1233                 for(i = 0, efa = stitch_state->em->faces.first; efa; efa = efa->next, i++){
1234                         efa->tmp.l = i;
1235                 }
1236
1237                 /* Store selection for re-execution of stitch */
1238                 for(i = 0; i < stitch_state->selection_size; i++){
1239                         PointerRNA itemptr;
1240                         UvElement *element = stitch_state->selection_stack[i];
1241
1242                         RNA_collection_add(op->ptr, "selection", &itemptr);
1243
1244                         RNA_int_set(&itemptr, "face_index", element->face->tmp.l);
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         BKE_mesh_end_editmesh(obedit->data, stitch_state->em);
1258
1259         stitch_state_delete(stitch_state);
1260         op->customdata = NULL;
1261
1262         stitch_preview_delete();
1263 }
1264
1265
1266 static int stitch_cancel(bContext *C, wmOperator *op)
1267 {
1268         stitch_exit(C, op, 0);
1269         return OPERATOR_CANCELLED;
1270 }
1271
1272
1273 static int stitch_exec(bContext *C, wmOperator *op)
1274 {
1275         Scene *scene = CTX_data_scene(C);
1276
1277         if(!stitch_init(C, op))
1278                 return OPERATOR_CANCELLED;
1279         if(stitch_process_data((StitchState *)op->customdata, scene, 1)){
1280                 stitch_exit(C, op, 1);
1281                 return OPERATOR_FINISHED;
1282         }else {
1283                 return stitch_cancel(C, op);
1284         }
1285 }
1286
1287 static void stitch_select(bContext *C, Scene *scene, wmEvent *event, StitchState *stitch_state){
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.uv);
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", "Snap islands together. On edge stitch mode, rotates the islands too");
1462
1463         RNA_def_float(ot->srna, "limit", 0.01f, 0.0f, FLT_MAX, "Limit", "Limit distance in normalized coordinates", 0.0, FLT_MAX);
1464         RNA_def_int(ot->srna, "static_island", 0, 0, INT_MAX, "Static Island",  "Island that stays in place when stitching islands", 0, INT_MAX);
1465         RNA_def_boolean(ot->srna, "midpoint_snap", 0, "Snap At Midpoint", "Uv's are stitched at midpoint instead of at static island");
1466         prop = RNA_def_collection_runtime(ot->srna, "selection", &RNA_SelectedUvElement, "Selection", "");
1467         /* Selection should not be editable or viewed in toolbar */
1468         RNA_def_property_flag(prop, PROP_HIDDEN);
1469 }
1470
1471 #endif /* BMESH TODO */