Separate proportional edit setting between edit and object mode. They are now used...
[blender-staging.git] / source / blender / editors / uvedit / uvedit_ops.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <math.h>
33
34 #include "MEM_guardedalloc.h"
35
36 #include "DNA_object_types.h"
37 #include "DNA_meshdata_types.h"
38 #include "DNA_scene_types.h"
39
40 #include "BLI_math.h"
41 #include "BLI_blenlib.h"
42 #include "BLI_editVert.h"
43
44 #include "BKE_context.h"
45 #include "BKE_customdata.h"
46 #include "BKE_depsgraph.h"
47 #include "BKE_image.h"
48 #include "BKE_library.h"
49 #include "BKE_mesh.h"
50 #include "BKE_report.h"
51 #include "BKE_utildefines.h"
52
53 #include "ED_image.h"
54 #include "ED_mesh.h"
55 #include "ED_object.h"
56 #include "ED_screen.h"
57 #include "ED_transform.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 /************************* state testing ************************/
70
71 int ED_uvedit_test(Object *obedit)
72 {
73         EditMesh *em;
74         int ret;
75
76         if(!obedit || obedit->type != OB_MESH)
77                 return 0;
78
79         em = BKE_mesh_get_editmesh(obedit->data);
80         ret = EM_texFaceCheck(em);
81         BKE_mesh_end_editmesh(obedit->data, em);
82         
83         return ret;
84 }
85
86 /************************* assign image ************************/
87
88 void ED_uvedit_assign_image(Scene *scene, Object *obedit, Image *ima, Image *previma)
89 {
90         EditMesh *em;
91         EditFace *efa;
92         MTFace *tf;
93         int update= 0;
94         
95         /* skip assigning these procedural images... */
96         if(ima && (ima->type==IMA_TYPE_R_RESULT || ima->type==IMA_TYPE_COMPOSITE))
97                 return;
98
99         /* verify we have a mesh we can work with */
100         if(!obedit || (obedit->type != OB_MESH))
101                 return;
102
103         em= BKE_mesh_get_editmesh(((Mesh*)obedit->data));
104         if(!em || !em->faces.first) {
105                 BKE_mesh_end_editmesh(obedit->data, em);
106                 return;
107         }
108         
109         /* ensure we have a uv layer */
110         if(!CustomData_has_layer(&em->fdata, CD_MTFACE)) {
111                 EM_add_data_layer(em, &em->fdata, CD_MTFACE);
112                 update= 1;
113         }
114
115         /* now assign to all visible faces */
116         for(efa= em->faces.first; efa; efa= efa->next) {
117                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
118
119                 if(uvedit_face_visible(scene, previma, efa, tf)) {
120                         if(ima) {
121                                 tf->tpage= ima;
122                                 tf->mode |= TF_TEX;
123                                 
124                                 if(ima->id.us==0) id_us_plus(&ima->id);
125                                 else id_lib_extern(&ima->id);
126                         }
127                         else {
128                                 tf->tpage= NULL;
129                                 tf->mode &= ~TF_TEX;
130                         }
131
132                         update = 1;
133                 }
134         }
135
136         /* and update depdency graph */
137         if(update)
138                 DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
139
140         BKE_mesh_end_editmesh(obedit->data, em);
141 }
142
143 /* dotile -     1, set the tile flag (from the space image)
144  *                      2, set the tile index for the faces. */
145 void ED_uvedit_set_tile(bContext *C, Scene *scene, Object *obedit, Image *ima, int curtile)
146 {
147         EditMesh *em;
148         EditFace *efa;
149         MTFace *tf;
150         
151         /* verify if we have something to do */
152         if(!ima || !ED_uvedit_test(obedit))
153                 return;
154         
155         /* skip assigning these procedural images... */
156         if(ima->type==IMA_TYPE_R_RESULT || ima->type==IMA_TYPE_COMPOSITE)
157                 return;
158         
159         em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
160
161         for(efa= em->faces.first; efa; efa= efa->next) {
162                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
163
164                 if(efa->h==0 && efa->f & SELECT)
165                         tf->tile= curtile; /* set tile index */
166         }
167
168         DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
169         WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
170         BKE_mesh_end_editmesh(obedit->data, em);
171 }
172
173 /*********************** space conversion *********************/
174
175 static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist)
176 {
177         int width, height;
178
179         if(sima) {
180                 ED_space_image_size(sima, &width, &height);
181         }
182         else {
183                 width= 256;
184                 height= 256;
185         }
186
187         dist[0]= pixeldist/width;
188         dist[1]= pixeldist/height;
189 }
190
191 /*************** visibility and selection utilities **************/
192
193 int uvedit_face_visible_nolocal(Scene *scene, EditFace *efa)
194 {
195         ToolSettings *ts= scene->toolsettings;
196
197         if(ts->uv_flag & UV_SYNC_SELECTION)
198                 return (efa->h==0);
199         else
200                 return (efa->h==0 && (efa->f & SELECT));
201 }
202
203 int uvedit_face_visible(Scene *scene, Image *ima, EditFace *efa, MTFace *tf)
204 {
205         ToolSettings *ts= scene->toolsettings;
206
207         if(ts->uv_flag & UV_SHOW_SAME_IMAGE)
208                 return (tf->tpage==ima)? uvedit_face_visible_nolocal(scene, efa): 0;
209         else
210                 return uvedit_face_visible_nolocal(scene, efa);
211 }
212
213 int uvedit_face_selected(Scene *scene, EditFace *efa, MTFace *tf)
214 {
215         ToolSettings *ts= scene->toolsettings;
216
217         if(ts->uv_flag & UV_SYNC_SELECTION)
218                 return (efa->f & SELECT);
219         else
220                 return (!(~tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) &&(!efa->v4 || tf->flag & TF_SEL4));
221 }
222
223 void uvedit_face_select(Scene *scene, EditFace *efa, MTFace *tf)
224 {
225         ToolSettings *ts= scene->toolsettings;
226
227         if(ts->uv_flag & UV_SYNC_SELECTION)
228                 EM_select_face(efa, 1);
229         else
230                 tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
231 }
232
233 void uvedit_face_deselect(Scene *scene, EditFace *efa, MTFace *tf)
234 {
235         ToolSettings *ts= scene->toolsettings;
236
237         if(ts->uv_flag & UV_SYNC_SELECTION)
238                 EM_select_face(efa, 0);
239         else
240                 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
241 }
242
243 int uvedit_edge_selected(Scene *scene, EditFace *efa, MTFace *tf, int i)
244 {
245         ToolSettings *ts= scene->toolsettings;
246         int nvert= (efa->v4)? 4: 3;
247
248         if(ts->uv_flag & UV_SYNC_SELECTION) {
249                 if(ts->selectmode == SCE_SELECT_FACE)
250                         return (efa->f & SELECT);
251                 else if(ts->selectmode == SCE_SELECT_EDGE)
252                         return (*(&efa->e1 + i))->f & SELECT;
253                 else
254                         return (((efa->v1 + i)->f & SELECT) && ((efa->v1 + (i+1)%nvert)->f & SELECT));
255         }
256         else
257                 return (tf->flag & TF_SEL_MASK(i)) && (tf->flag & TF_SEL_MASK((i+1)%nvert));
258 }
259
260 void uvedit_edge_select(Scene *scene, EditFace *efa, MTFace *tf, int i)
261 {
262         ToolSettings *ts= scene->toolsettings;
263         int nvert= (efa->v4)? 4: 3;
264
265         if(ts->uv_flag & UV_SYNC_SELECTION) {
266                 if(ts->selectmode == SCE_SELECT_FACE)
267                         EM_select_face(efa, 1);
268                 else if(ts->selectmode == SCE_SELECT_EDGE)
269                         EM_select_edge((*(&efa->e1 + i)), 1);
270                 else {
271                         (efa->v1 + i)->f |= SELECT;
272                         (efa->v1 + (i+1)%nvert)->f |= SELECT;
273                 }
274         }
275         else
276                 tf->flag |= TF_SEL_MASK(i)|TF_SEL_MASK((i+1)%nvert);
277 }
278
279 void uvedit_edge_deselect(Scene *scene, EditFace *efa, MTFace *tf, int i)
280 {
281         ToolSettings *ts= scene->toolsettings;
282         int nvert= (efa->v4)? 4: 3;
283
284         if(ts->uv_flag & UV_SYNC_SELECTION) {
285                 if(ts->selectmode == SCE_SELECT_FACE)
286                         EM_select_face(efa, 0);
287                 else if(ts->selectmode == SCE_SELECT_EDGE)
288                         EM_select_edge((*(&efa->e1 + i)), 0);
289                 else {
290                         (efa->v1 + i)->f &= ~SELECT;
291                         (efa->v1 + (i+1)%nvert)->f &= ~SELECT;
292                 }
293         }
294         else
295                 tf->flag &= ~(TF_SEL_MASK(i)|TF_SEL_MASK((i+1)%nvert));
296 }
297
298 int uvedit_uv_selected(Scene *scene, EditFace *efa, MTFace *tf, int i)
299 {
300         ToolSettings *ts= scene->toolsettings;
301
302         if(ts->uv_flag & UV_SYNC_SELECTION) {
303                 if(ts->selectmode == SCE_SELECT_FACE)
304                         return (efa->f & SELECT);
305                 else
306                         return (*(&efa->v1 + i))->f & SELECT;
307         }
308         else
309                 return tf->flag & TF_SEL_MASK(i);
310 }
311
312 void uvedit_uv_select(Scene *scene, EditFace *efa, MTFace *tf, int i)
313 {
314         ToolSettings *ts= scene->toolsettings;
315
316         if(ts->uv_flag & UV_SYNC_SELECTION) {
317                 if(ts->selectmode == SCE_SELECT_FACE)
318                         EM_select_face(efa, 1);
319                 else
320                         (*(&efa->v1 + i))->f |= SELECT;
321         }
322         else
323                 tf->flag |= TF_SEL_MASK(i);
324 }
325
326 void uvedit_uv_deselect(Scene *scene, EditFace *efa, MTFace *tf, int i)
327 {
328         ToolSettings *ts= scene->toolsettings;
329
330         if(ts->uv_flag & UV_SYNC_SELECTION) {
331                 if(ts->selectmode == SCE_SELECT_FACE)
332                         EM_select_face(efa, 0);
333                 else
334                         (*(&efa->v1 + i))->f &= ~SELECT;
335         }
336         else
337                 tf->flag &= ~TF_SEL_MASK(i);
338 }
339
340 /*********************** geometric utilities ***********************/
341
342 void uv_center(float uv[][2], float cent[2], int quad)
343 {
344         if(quad) {
345                 cent[0] = (uv[0][0] + uv[1][0] + uv[2][0] + uv[3][0]) / 4.0;
346                 cent[1] = (uv[0][1] + uv[1][1] + uv[2][1] + uv[3][1]) / 4.0;            
347         }
348         else {
349                 cent[0] = (uv[0][0] + uv[1][0] + uv[2][0]) / 3.0;
350                 cent[1] = (uv[0][1] + uv[1][1] + uv[2][1]) / 3.0;               
351         }
352 }
353
354 float uv_area(float uv[][2], int quad)
355 {
356         if(quad)
357                 return area_tri_v2(uv[0], uv[1], uv[2]) + area_tri_v2(uv[0], uv[2], uv[3]); 
358         else
359                 return area_tri_v2(uv[0], uv[1], uv[2]); 
360 }
361
362 void uv_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy)
363 {
364         uv[0][0] = uv_orig[0][0]*aspx;
365         uv[0][1] = uv_orig[0][1]*aspy;
366         
367         uv[1][0] = uv_orig[1][0]*aspx;
368         uv[1][1] = uv_orig[1][1]*aspy;
369         
370         uv[2][0] = uv_orig[2][0]*aspx;
371         uv[2][1] = uv_orig[2][1]*aspy;
372         
373         uv[3][0] = uv_orig[3][0]*aspx;
374         uv[3][1] = uv_orig[3][1]*aspy;
375 }
376
377 int ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float *min, float *max)
378 {
379         EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
380         EditFace *efa;
381         MTFace *tf;
382         int sel;
383
384         INIT_MINMAX2(min, max);
385
386         sel= 0;
387         for(efa= em->faces.first; efa; efa= efa->next) {
388                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
389                 if(uvedit_face_visible(scene, ima, efa, tf)) {
390                         if(uvedit_uv_selected(scene, efa, tf, 0))                               { DO_MINMAX2(tf->uv[0], min, max); sel = 1; }
391                         if(uvedit_uv_selected(scene, efa, tf, 1))                               { DO_MINMAX2(tf->uv[1], min, max); sel = 1; }
392                         if(uvedit_uv_selected(scene, efa, tf, 2))                               { DO_MINMAX2(tf->uv[2], min, max); sel = 1; }
393                         if(efa->v4 && (uvedit_uv_selected(scene, efa, tf, 3)))  { DO_MINMAX2(tf->uv[3], min, max); sel = 1; }
394                 }
395         }
396         
397         BKE_mesh_end_editmesh(obedit->data, em);
398         return sel;
399 }
400
401 int uvedit_center(Scene *scene, Image *ima, Object *obedit, float *cent, int mode)
402 {
403         EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
404         EditFace *efa;
405         MTFace *tf;
406         float min[2], max[2];
407         int change= 0;
408         
409         if(mode==0) {
410                 if(ED_uvedit_minmax(scene, ima, obedit, min, max))
411                         change = 1;
412         }
413         else if(mode==1) {
414                 INIT_MINMAX2(min, max);
415                 
416                 for(efa= em->faces.first; efa; efa= efa->next) {
417                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
418
419                         if(uvedit_face_visible(scene, ima, efa, tf)) {
420                                 if(uvedit_uv_selected(scene, efa, tf, 0))                               { DO_MINMAX2(tf->uv[0], min, max);      change= 1;}
421                                 if(uvedit_uv_selected(scene, efa, tf, 1))                               { DO_MINMAX2(tf->uv[1], min, max);      change= 1;}
422                                 if(uvedit_uv_selected(scene, efa, tf, 2))                               { DO_MINMAX2(tf->uv[2], min, max);      change= 1;}
423                                 if(efa->v4 && (uvedit_uv_selected(scene, efa, tf, 3)))  { DO_MINMAX2(tf->uv[3], min, max);      change= 1;}
424                         }
425                 }
426         }
427         
428         if(change) {
429                 cent[0]= (min[0]+max[0])/2.0;
430                 cent[1]= (min[1]+max[1])/2.0;
431                 
432                 BKE_mesh_end_editmesh(obedit->data, em);
433                 return 1;
434         }
435
436         BKE_mesh_end_editmesh(obedit->data, em);
437         return 0;
438 }
439
440 /************************** find nearest ****************************/
441
442 typedef struct NearestHit {
443         EditFace *efa;
444         MTFace *tf;
445
446         int vert, uv;
447         int edge, vert2;
448 } NearestHit;
449
450 static void find_nearest_uv_edge(Scene *scene, Image *ima, EditMesh *em, float co[2], NearestHit *hit)
451 {
452         MTFace *tf;
453         EditFace *efa;
454         EditVert *eve;
455         float mindist, dist;
456         int i, nverts;
457
458         mindist= 1e10f;
459         memset(hit, 0, sizeof(*hit));
460
461         for(i=0, eve=em->verts.first; eve; eve=eve->next, i++)
462                 eve->tmp.l = i;
463         
464         for(efa= em->faces.first; efa; efa= efa->next) {
465                 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
466
467                 if(uvedit_face_visible(scene, ima, efa, tf)) {
468                         nverts= efa->v4? 4: 3;
469
470                         for(i=0; i<nverts; i++) {
471                                 dist= dist_to_line_segment_v2(co, tf->uv[i], tf->uv[(i+1)%nverts]);
472
473                                 if(dist < mindist) {
474                                         hit->tf= tf;
475                                         hit->efa= efa;
476                                         hit->edge= i;
477                                         mindist= dist;
478
479                                         hit->vert= (*(&efa->v1 + i))->tmp.l;
480                                         hit->vert2= (*(&efa->v1 + ((i+1)%nverts)))->tmp.l;
481                                 }
482                         }
483                 }
484         }
485 }
486
487 static void find_nearest_uv_face(Scene *scene, Image *ima, EditMesh *em, float co[2], NearestHit *hit)
488 {
489         MTFace *tf;
490         EditFace *efa;
491         float mindist, dist, cent[2];
492         int i, nverts;
493
494         mindist= 1e10f;
495         memset(hit, 0, sizeof(*hit));
496         
497         for(efa= em->faces.first; efa; efa= efa->next) {
498                 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
499
500                 if(uvedit_face_visible(scene, ima, efa, tf)) {
501                         nverts= efa->v4? 4: 3;
502                         cent[0]= cent[1]= 0.0f;
503
504                         for(i=0; i<nverts; i++) {
505                                 cent[0] += tf->uv[i][0];
506                                 cent[1] += tf->uv[i][1];
507                         }
508
509                         cent[0] /= nverts;
510                         cent[1] /= nverts;
511                         dist= fabs(co[0]- cent[0]) + fabs(co[1]- cent[1]);
512
513                         if(dist < mindist) {
514                                 hit->tf= tf;
515                                 hit->efa= efa;
516                                 mindist= dist;
517                         }
518                 }
519         }
520 }
521
522 static int nearest_uv_between(MTFace *tf, int nverts, int id, float co[2], float uv[2])
523 {
524         float m[3], v1[3], v2[3], c1, c2;
525         int id1, id2;
526
527         id1= (id+nverts-1)%nverts;
528         id2= (id+nverts+1)%nverts;
529
530         m[0]= co[0]-uv[0];
531         m[1]= co[1]-uv[1];
532         sub_v2_v2v2(v1, tf->uv[id1], tf->uv[id]);
533         sub_v2_v2v2(v2, tf->uv[id2], tf->uv[id]);
534
535         /* m and v2 on same side of v-v1? */
536         c1= v1[0]*m[1] - v1[1]*m[0];
537         c2= v1[0]*v2[1] - v1[1]*v2[0];
538
539         if(c1*c2 < 0.0f)
540                 return 0;
541
542         /* m and v1 on same side of v-v2? */
543         c1= v2[0]*m[1] - v2[1]*m[0];
544         c2= v2[0]*v1[1] - v2[1]*v1[0];
545
546         return (c1*c2 >= 0.0f);
547 }
548
549 static void find_nearest_uv_vert(Scene *scene, Image *ima, EditMesh *em, float co[2], float penalty[2], NearestHit *hit)
550 {
551         EditFace *efa;
552         EditVert *eve;
553         MTFace *tf;
554         float mindist, dist;
555         int i, nverts;
556
557         mindist= 1e10f;
558         memset(hit, 0, sizeof(*hit));
559         
560         for(i=0, eve=em->verts.first; eve; eve=eve->next, i++)
561                 eve->tmp.l = i;
562         
563         for(efa= em->faces.first; efa; efa= efa->next) {
564                 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
565
566                 if(uvedit_face_visible(scene, ima, efa, tf)) {
567                         nverts= efa->v4? 4: 3;
568
569                         for(i=0; i<nverts; i++) {
570                                 if(penalty && uvedit_uv_selected(scene, efa, tf, i))
571                                         dist= fabs(co[0]-tf->uv[i][0])+penalty[0] + fabs(co[1]-tf->uv[i][1])+penalty[1];
572                                 else
573                                         dist= fabs(co[0]-tf->uv[i][0]) + fabs(co[1]-tf->uv[i][1]);
574
575                                 if(dist<=mindist) {
576                                         if(dist==mindist)
577                                                 if(!nearest_uv_between(tf, nverts, i, co, tf->uv[i]))
578                                                         continue;
579
580                                         mindist= dist;
581
582                                         hit->uv= i;
583                                         hit->tf= tf;
584                                         hit->efa= efa;
585
586                                         hit->vert= (*(&efa->v1 + i))->tmp.l;
587                                 }
588                         }
589                 }
590         }
591 }
592
593 int ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, float co[2], float uv[2])
594 {
595         EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
596         EditFace *efa;
597         MTFace *tf;
598         float mindist, dist;
599         int i, nverts, found= 0;
600
601         mindist= 1e10f;
602         uv[0]= co[0];
603         uv[1]= co[1];
604         
605         for(efa= em->faces.first; efa; efa= efa->next) {
606                 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
607
608                 if(uvedit_face_visible(scene, ima, efa, tf)) {
609                         nverts= efa->v4? 4: 3;
610
611                         for(i=0; i<nverts; i++) {
612                                 dist= fabs(co[0]-tf->uv[i][0]) + fabs(co[1]-tf->uv[i][1]);
613
614                                 if(dist<=mindist) {
615                                         mindist= dist;
616
617                                         uv[0]= tf->uv[i][0];
618                                         uv[1]= tf->uv[i][1];
619                                         found= 1;
620                                 }
621                         }
622                 }
623         }
624
625         BKE_mesh_end_editmesh(obedit->data, em);
626         return found;
627 }
628
629 /*********************** loop select ***********************/
630
631 static void uv_vertex_loop_flag(UvMapVert *first)
632 {
633         UvMapVert *iterv;
634         int count= 0;
635
636         for(iterv=first; iterv; iterv=iterv->next) {
637                 if(iterv->separate && iterv!=first)
638                         break;
639
640                 count++;
641         }
642         
643         if(count < 5)
644                 first->flag= 1;
645 }
646
647 static UvMapVert *uv_vertex_map_get(UvVertMap *vmap, EditFace *efa, int a)
648 {
649         UvMapVert *iterv, *first;
650         
651         first= EM_get_uv_map_vert(vmap, (*(&efa->v1 + a))->tmp.l);
652
653         for(iterv=first; iterv; iterv=iterv->next) {
654                 if(iterv->separate)
655                         first= iterv;
656                 if(iterv->f == efa->tmp.l)
657                         return first;
658         }
659         
660         return NULL;
661 }
662
663 static int uv_edge_tag_faces(UvMapVert *first1, UvMapVert *first2, int *totface)
664 {
665         UvMapVert *iterv1, *iterv2;
666         EditFace *efa;
667         int tot = 0;
668
669         /* count number of faces this edge has */
670         for(iterv1=first1; iterv1; iterv1=iterv1->next) {
671                 if(iterv1->separate && iterv1 != first1)
672                         break;
673
674                 for(iterv2=first2; iterv2; iterv2=iterv2->next) {
675                         if(iterv2->separate && iterv2 != first2)
676                                 break;
677
678                         if(iterv1->f == iterv2->f) {
679                                 /* if face already tagged, don't do this edge */
680                                 efa= EM_get_face_for_index(iterv1->f);
681                                 if(efa->f1)
682                                         return 0;
683
684                                 tot++;
685                                 break;
686                         }
687                 }
688         }
689
690         if(*totface == 0) /* start edge */
691                 *totface= tot;
692         else if(tot != *totface) /* check for same number of faces as start edge */
693                 return 0;
694
695         /* tag the faces */
696         for(iterv1=first1; iterv1; iterv1=iterv1->next) {
697                 if(iterv1->separate && iterv1 != first1)
698                         break;
699
700                 for(iterv2=first2; iterv2; iterv2=iterv2->next) {
701                         if(iterv2->separate && iterv2 != first2)
702                                 break;
703
704                         if(iterv1->f == iterv2->f) {
705                                 efa= EM_get_face_for_index(iterv1->f);
706                                 efa->f1= 1;
707                                 break;
708                         }
709                 }
710         }
711
712         return 1;
713 }
714
715 static int select_edgeloop(Scene *scene, Image *ima, EditMesh *em, NearestHit *hit, float limit[2], int extend)
716 {
717         EditVert *eve;
718         EditFace *efa;
719         MTFace *tf;
720         UvVertMap *vmap;
721         UvMapVert *iterv1, *iterv2;
722         int a, count, looking, nverts, starttotf, select;
723
724         /* setup */
725         EM_init_index_arrays(em, 0, 0, 1);
726         vmap= EM_make_uv_vert_map(em, 0, 0, limit);
727
728         for(count=0, eve=em->verts.first; eve; count++, eve= eve->next)
729                 eve->tmp.l = count;
730
731         for(count=0, efa= em->faces.first; efa; count++, efa= efa->next) {
732                 if(!extend) {
733                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
734                         uvedit_face_deselect(scene, efa, tf);
735                 }
736
737                 efa->tmp.l= count;
738                 efa->f1= 0;
739         }
740         
741         /* set flags for first face and verts */
742         nverts= (hit->efa->v4)? 4: 3;
743         iterv1= uv_vertex_map_get(vmap, hit->efa, hit->edge);
744         iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->edge+1)%nverts);
745         uv_vertex_loop_flag(iterv1);
746         uv_vertex_loop_flag(iterv2);
747
748         starttotf= 0;
749         uv_edge_tag_faces(iterv1, iterv2, &starttotf);
750
751         /* sorry, first edge isnt even ok */
752         if(iterv1->flag==0 && iterv2->flag==0) looking= 0;
753         else looking= 1;
754
755         /* iterate */
756         while(looking) {
757                 looking= 0;
758
759                 /* find correct valence edges which are not tagged yet, but connect to tagged one */
760                 for(efa= em->faces.first; efa; efa=efa->next) {
761                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
762
763                         if(!efa->f1 && uvedit_face_visible(scene, ima, efa, tf)) {
764                                 nverts= (efa->v4)? 4: 3;
765                                 for(a=0; a<nverts; a++) {
766                                         /* check face not hidden and not tagged */
767                                         iterv1= uv_vertex_map_get(vmap, efa, a);
768                                         iterv2= uv_vertex_map_get(vmap, efa, (a+1)%nverts);
769
770                                         /* check if vertex is tagged and has right valence */
771                                         if(iterv1->flag || iterv2->flag) {
772                                                 if(uv_edge_tag_faces(iterv1, iterv2, &starttotf)) {
773                                                         looking= 1;
774                                                         efa->f1= 1;
775
776                                                         uv_vertex_loop_flag(iterv1);
777                                                         uv_vertex_loop_flag(iterv2);
778                                                         break;
779                                                 }
780                                         }
781                                 }
782                         }
783                 }
784         }
785
786         /* do the actual select/deselect */
787         nverts= (hit->efa->v4)? 4: 3;
788         iterv1= uv_vertex_map_get(vmap, hit->efa, hit->edge);
789         iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->edge+1)%nverts);
790         iterv1->flag= 1;
791         iterv2->flag= 1;
792
793         if(extend) {
794                 tf= CustomData_em_get(&em->fdata, hit->efa->data, CD_MTFACE);
795
796                 if(uvedit_uv_selected(scene, hit->efa, tf, hit->edge) && uvedit_uv_selected(scene, hit->efa, tf, hit->edge))
797                         select= 0;
798                 else
799                         select= 1;
800         }
801         else
802                 select= 1;
803         
804         for(efa= em->faces.first; efa; efa=efa->next) {
805                 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
806
807                 nverts= (efa->v4)? 4: 3;
808                 for(a=0; a<nverts; a++) {
809                         iterv1= uv_vertex_map_get(vmap, efa, a);
810
811                         if(iterv1->flag) {
812                                 if(select) uvedit_uv_select(scene, efa, tf, a);
813                                 else uvedit_uv_deselect(scene, efa, tf, a);
814                         }
815                 }
816         }
817
818         /* cleanup */
819         EM_free_uv_vert_map(vmap);
820         EM_free_index_arrays();
821
822         return (select)? 1: -1;
823 }
824
825 /*********************** linked select ***********************/
826
827 static void select_linked(Scene *scene, Image *ima, EditMesh *em, float limit[2], NearestHit *hit, int extend)
828 {
829         EditFace *efa;
830         MTFace *tf;
831         UvVertMap *vmap;
832         UvMapVert *vlist, *iterv, *startv;
833         int a, i, nverts, stacksize= 0, *stack;
834         char *flag;
835
836         EM_init_index_arrays(em, 0, 0, 1); /* we can use this too */
837         vmap= EM_make_uv_vert_map(em, 1, 0, limit);
838         if(vmap == NULL)
839                 return;
840
841         stack= MEM_mallocN(sizeof(*stack) * em->totface, "UvLinkStack");
842         flag= MEM_callocN(sizeof(*flag) * em->totface, "UvLinkFlag");
843
844         if(!hit) {
845                 for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
846                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
847
848                         if(uvedit_face_visible(scene, ima, efa, tf)) {
849                                 if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) {
850                                         stack[stacksize]= a;
851                                         stacksize++;
852                                         flag[a]= 1;
853                                 }
854                         }
855                 }
856         }
857         else {
858                 for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
859                         if(efa == hit->efa) {
860                                 stack[stacksize]= a;
861                                 stacksize++;
862                                 flag[a]= 1;
863                                 break;
864                         }
865                 }
866         }
867
868         while(stacksize > 0) {
869                 stacksize--;
870                 a= stack[stacksize];
871
872                 efa = EM_get_face_for_index(a);
873
874                 nverts= efa->v4? 4: 3;
875
876                 for(i=0; i<nverts; i++) {
877                         /* make_uv_vert_map_EM sets verts tmp.l to the indicies */
878                         vlist= EM_get_uv_map_vert(vmap, (*(&efa->v1 + i))->tmp.l);
879                         
880                         startv= vlist;
881
882                         for(iterv=vlist; iterv; iterv=iterv->next) {
883                                 if(iterv->separate)
884                                         startv= iterv;
885                                 if(iterv->f == a)
886                                         break;
887                         }
888
889                         for(iterv=startv; iterv; iterv=iterv->next) {
890                                 if((startv != iterv) && (iterv->separate))
891                                         break;
892                                 else if(!flag[iterv->f]) {
893                                         flag[iterv->f]= 1;
894                                         stack[stacksize]= iterv->f;
895                                         stacksize++;
896                                 }
897                         }
898                 }
899         }
900
901         if(!extend) {
902                 for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
903                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
904                         if(flag[a])
905                                 tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
906                         else
907                                 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
908                 }
909         }
910         else {
911                 for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
912                         if(flag[a]) {
913                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
914                                 if(efa->v4) {
915                                         if((tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)))
916                                                 break;
917                                 }
918                                 else if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
919                                         break;
920                         }
921                 }
922
923                 if(efa) {
924                         for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
925                                 if(flag[a]) {
926                                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
927                                         tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
928                                 }
929                         }
930                 }
931                 else {
932                         for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
933                                 if(flag[a]) {
934                                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
935                                         tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
936                                 }
937                         }
938                 }
939         }
940         
941         MEM_freeN(stack);
942         MEM_freeN(flag);
943         EM_free_uv_vert_map(vmap);
944         EM_free_index_arrays();
945 }
946
947 /* ******************** align operator **************** */
948
949 static void weld_align_uv(bContext *C, int tool)
950 {
951         Scene *scene;
952         Object *obedit;
953         Image *ima;
954         EditMesh *em;
955         EditFace *efa;
956         MTFace *tf;
957         float cent[2], min[2], max[2];
958         
959         scene= CTX_data_scene(C);
960         obedit= CTX_data_edit_object(C);
961         em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
962         ima= CTX_data_edit_image(C);
963
964         INIT_MINMAX2(min, max);
965
966         if(tool == 'a') {
967                 for(efa= em->faces.first; efa; efa= efa->next) {
968                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
969
970                         if(uvedit_face_visible(scene, ima, efa, tf)) {
971                                 if(uvedit_uv_selected(scene, efa, tf, 0))
972                                         DO_MINMAX2(tf->uv[0], min, max)
973                                 if(uvedit_uv_selected(scene, efa, tf, 1))
974                                         DO_MINMAX2(tf->uv[1], min, max)
975                                 if(uvedit_uv_selected(scene, efa, tf, 2))
976                                         DO_MINMAX2(tf->uv[2], min, max)
977                                 if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3))
978                                         DO_MINMAX2(tf->uv[3], min, max)
979                         }
980                 }
981
982                 tool= (max[0]-min[0] >= max[1]-min[1])? 'y': 'x';
983         }
984
985         uvedit_center(scene, ima, obedit, cent, 0);
986
987         if(tool == 'x' || tool == 'w') {
988                 for(efa= em->faces.first; efa; efa= efa->next) {
989                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
990                         if(uvedit_face_visible(scene, ima, efa, tf)) {
991                                 if(uvedit_uv_selected(scene, efa, tf, 0))
992                                         tf->uv[0][0]= cent[0];
993                                 if(uvedit_uv_selected(scene, efa, tf, 1))
994                                         tf->uv[1][0]= cent[0];
995                                 if(uvedit_uv_selected(scene, efa, tf, 2))
996                                         tf->uv[2][0]= cent[0];
997                                 if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3))
998                                         tf->uv[3][0]= cent[0];
999                         }
1000                 }
1001         }
1002
1003         if(tool == 'y' || tool == 'w') {
1004                 for(efa= em->faces.first; efa; efa= efa->next) {
1005                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1006                         if(uvedit_face_visible(scene, ima, efa, tf)) {
1007                                 if(uvedit_uv_selected(scene, efa, tf, 0))
1008                                         tf->uv[0][1]= cent[1];
1009                                 if(uvedit_uv_selected(scene, efa, tf, 1))
1010                                         tf->uv[1][1]= cent[1];
1011                                 if(uvedit_uv_selected(scene, efa, tf, 2))
1012                                         tf->uv[2][1]= cent[1];
1013                                 if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3))
1014                                         tf->uv[3][1]= cent[1];
1015                         }
1016                 }
1017         }
1018
1019         DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
1020         WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
1021
1022         BKE_mesh_end_editmesh(obedit->data, em);
1023 }
1024
1025 static int align_exec(bContext *C, wmOperator *op)
1026 {
1027         weld_align_uv(C, RNA_enum_get(op->ptr, "axis"));
1028
1029         return OPERATOR_FINISHED;
1030 }
1031
1032 void UV_OT_align(wmOperatorType *ot)
1033 {
1034         static EnumPropertyItem axis_items[] = {
1035                 {'a', "ALIGN_AUTO", 0, "Align Auto", "Automatically choose the axis on which there is most alignment already"},
1036                 {'x', "ALIGN_X", 0, "Align X", "Align UVs on X axis"},
1037                 {'y', "ALIGN_Y", 0, "Align Y", "Align UVs on Y axis"},
1038                 {0, NULL, 0, NULL, NULL}};
1039
1040         /* identifiers */
1041         ot->name= "Align";
1042         ot->description= "Align selected UV vertices to an axis";
1043         ot->idname= "UV_OT_align";
1044         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1045         
1046         /* api callbacks */
1047         ot->exec= align_exec;
1048         ot->poll= ED_operator_uvedit;
1049
1050         /* properties */
1051         RNA_def_enum(ot->srna, "axis", axis_items, 'a', "Axis", "Axis to align UV locations on.");
1052 }
1053
1054 /* ******************** weld operator **************** */
1055
1056 static int weld_exec(bContext *C, wmOperator *op)
1057 {
1058         weld_align_uv(C, 'w');
1059
1060         return OPERATOR_FINISHED;
1061 }
1062
1063 void UV_OT_weld(wmOperatorType *ot)
1064 {
1065         /* identifiers */
1066         ot->name= "Weld";
1067         ot->description= "Weld selected UV vertices together";
1068         ot->idname= "UV_OT_weld";
1069         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1070         
1071         /* api callbacks */
1072         ot->exec= weld_exec;
1073         ot->poll= ED_operator_uvedit;
1074 }
1075
1076 /* ******************** stitch operator **************** */
1077
1078 /* just for averaging UVs */
1079 typedef struct UVVertAverage {
1080         float uv[2];
1081         int count;
1082 } UVVertAverage;
1083
1084 static int stitch_exec(bContext *C, wmOperator *op)
1085 {
1086         SpaceImage *sima;
1087         Scene *scene;
1088         Object *obedit;
1089         EditMesh *em;
1090         EditFace *efa;
1091         EditVert *eve;
1092         Image *ima;
1093         MTFace *tf;
1094         
1095         sima= CTX_wm_space_image(C);
1096         scene= CTX_data_scene(C);
1097         obedit= CTX_data_edit_object(C);
1098         em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
1099         ima= CTX_data_edit_image(C);
1100         
1101         if(RNA_boolean_get(op->ptr, "use_limit")) {
1102                 UvVertMap *vmap;
1103                 UvMapVert *vlist, *iterv;
1104                 float newuv[2], limit[2];
1105                 int a, vtot;
1106
1107                 limit[0]= RNA_float_get(op->ptr, "limit");
1108                 limit[1]= limit[0];
1109
1110                 EM_init_index_arrays(em, 0, 0, 1);
1111                 vmap= EM_make_uv_vert_map(em, 1, 0, limit);
1112
1113                 if(vmap == NULL) {
1114                         BKE_mesh_end_editmesh(obedit->data, em);
1115                         return OPERATOR_CANCELLED;
1116                 }
1117
1118                 for(a=0, eve= em->verts.first; eve; a++, eve= eve->next) {
1119                         vlist= EM_get_uv_map_vert(vmap, a);
1120
1121                         while(vlist) {
1122                                 newuv[0]= 0; newuv[1]= 0;
1123                                 vtot= 0;
1124
1125                                 for(iterv=vlist; iterv; iterv=iterv->next) {
1126                                         if((iterv != vlist) && iterv->separate)
1127                                                 break;
1128
1129                                         efa = EM_get_face_for_index(iterv->f);
1130                                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1131                                         
1132                                         if(uvedit_uv_selected(scene, efa, tf, iterv->tfindex)) {
1133                                                 newuv[0] += tf->uv[iterv->tfindex][0];
1134                                                 newuv[1] += tf->uv[iterv->tfindex][1];
1135                                                 vtot++;
1136                                         }
1137                                 }
1138
1139                                 if(vtot > 1) {
1140                                         newuv[0] /= vtot; newuv[1] /= vtot;
1141
1142                                         for(iterv=vlist; iterv; iterv=iterv->next) {
1143                                                 if((iterv != vlist) && iterv->separate)
1144                                                         break;
1145
1146                                                 efa = EM_get_face_for_index(iterv->f);
1147                                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1148
1149                                                 if(uvedit_uv_selected(scene, efa, tf, iterv->tfindex)) {
1150                                                         tf->uv[iterv->tfindex][0]= newuv[0];
1151                                                         tf->uv[iterv->tfindex][1]= newuv[1];
1152                                                 }
1153                                         }
1154                                 }
1155
1156                                 vlist= iterv;
1157                         }
1158                 }
1159
1160                 EM_free_uv_vert_map(vmap);
1161                 EM_free_index_arrays();
1162         }
1163         else {
1164                 UVVertAverage *uv_average, *uvav;
1165                 int count;
1166
1167                 // index and count verts
1168                 for(count=0, eve=em->verts.first; eve; count++, eve= eve->next)
1169                         eve->tmp.l = count;
1170                 
1171                 uv_average= MEM_callocN(sizeof(UVVertAverage)*count, "Stitch");
1172                 
1173                 // gather uv averages per vert
1174                 for(efa= em->faces.first; efa; efa= efa->next) {
1175                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1176
1177                         if(uvedit_face_visible(scene, ima, efa, tf)) {
1178                                 if(uvedit_uv_selected(scene, efa, tf, 0)) {
1179                                         uvav = uv_average + efa->v1->tmp.l;
1180                                         uvav->count++;
1181                                         uvav->uv[0] += tf->uv[0][0];
1182                                         uvav->uv[1] += tf->uv[0][1];
1183                                 }
1184
1185                                 if(uvedit_uv_selected(scene, efa, tf, 1)) {
1186                                         uvav = uv_average + efa->v2->tmp.l;
1187                                         uvav->count++;
1188                                         uvav->uv[0] += tf->uv[1][0];
1189                                         uvav->uv[1] += tf->uv[1][1];
1190                                 }
1191
1192                                 if(uvedit_uv_selected(scene, efa, tf, 2)) {
1193                                         uvav = uv_average + efa->v3->tmp.l;
1194                                         uvav->count++;
1195                                         uvav->uv[0] += tf->uv[2][0];
1196                                         uvav->uv[1] += tf->uv[2][1];
1197                                 }
1198
1199                                 if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) {
1200                                         uvav = uv_average + efa->v4->tmp.l;
1201                                         uvav->count++;
1202                                         uvav->uv[0] += tf->uv[3][0];
1203                                         uvav->uv[1] += tf->uv[3][1];
1204                                 }
1205                         }
1206                 }
1207                 
1208                 // apply uv welding
1209                 for(efa= em->faces.first; efa; efa= efa->next) {
1210                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1211
1212                         if(uvedit_face_visible(scene, ima, efa, tf)) {
1213                                 if(uvedit_uv_selected(scene, efa, tf, 0)) {
1214                                         uvav = uv_average + efa->v1->tmp.l;
1215                                         tf->uv[0][0] = uvav->uv[0]/uvav->count;
1216                                         tf->uv[0][1] = uvav->uv[1]/uvav->count;
1217                                 }
1218
1219                                 if(uvedit_uv_selected(scene, efa, tf, 1)) {
1220                                         uvav = uv_average + efa->v2->tmp.l;
1221                                         tf->uv[1][0] = uvav->uv[0]/uvav->count;
1222                                         tf->uv[1][1] = uvav->uv[1]/uvav->count;
1223                                 }
1224
1225                                 if(uvedit_uv_selected(scene, efa, tf, 2)) {
1226                                         uvav = uv_average + efa->v3->tmp.l;
1227                                         tf->uv[2][0] = uvav->uv[0]/uvav->count;
1228                                         tf->uv[2][1] = uvav->uv[1]/uvav->count;
1229                                 }
1230
1231                                 if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) {
1232                                         uvav = uv_average + efa->v4->tmp.l;
1233                                         tf->uv[3][0] = uvav->uv[0]/uvav->count;
1234                                         tf->uv[3][1] = uvav->uv[1]/uvav->count;
1235                                 }
1236                         }
1237                 }
1238
1239                 MEM_freeN(uv_average);
1240         }
1241
1242         DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
1243         WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
1244
1245         BKE_mesh_end_editmesh(obedit->data, em);
1246         return OPERATOR_FINISHED;
1247 }
1248
1249 void UV_OT_stitch(wmOperatorType *ot)
1250 {
1251         /* identifiers */
1252         ot->name= "Stitch";
1253         ot->description= "Stitch selected UV vertices by proximity";
1254         ot->idname= "UV_OT_stitch";
1255         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1256         
1257         /* api callbacks */
1258         ot->exec= stitch_exec;
1259         ot->poll= ED_operator_uvedit;
1260
1261         /* properties */
1262         RNA_def_boolean(ot->srna, "use_limit", 1, "Use Limit", "Stitch UVs within a specified limit distance.");
1263         RNA_def_float(ot->srna, "limit", 0.01f, 0.0f, FLT_MAX, "Limit", "Limit distance in normalized coordinates.", -FLT_MAX, FLT_MAX);
1264 }
1265
1266 /* ******************** (de)select all operator **************** */
1267
1268 static int select_inverse_exec(bContext *C, wmOperator *op)
1269 {
1270         Scene *scene;
1271         ToolSettings *ts;
1272         Object *obedit;
1273         EditMesh *em;
1274         EditFace *efa;
1275         Image *ima;
1276         MTFace *tf;
1277         
1278         scene= CTX_data_scene(C);
1279         ts= CTX_data_tool_settings(C);
1280         obedit= CTX_data_edit_object(C);
1281         em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
1282         ima= CTX_data_edit_image(C);
1283
1284         if(ts->uv_flag & UV_SYNC_SELECTION) {
1285                 EM_select_swap(em);
1286         }
1287         else {
1288                 for(efa= em->faces.first; efa; efa= efa->next) {
1289                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1290
1291                         if(uvedit_face_visible(scene, ima, efa, tf)) {
1292                                 tf->flag ^= TF_SEL1;
1293                                 tf->flag ^= TF_SEL2;
1294                                 tf->flag ^= TF_SEL3;
1295                                 if(efa->v4) tf->flag ^= TF_SEL4;
1296                         }
1297                 }
1298         }
1299
1300         WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
1301
1302         BKE_mesh_end_editmesh(obedit->data, em);
1303         return OPERATOR_FINISHED;
1304 }
1305
1306 void UV_OT_select_inverse(wmOperatorType *ot)
1307 {
1308         /* identifiers */
1309         ot->name= "Select Inverse";
1310         ot->description= "Select inverse of (un)selected UV vertices";
1311         ot->idname= "UV_OT_select_inverse";
1312         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1313         
1314         /* api callbacks */
1315         ot->exec= select_inverse_exec;
1316         ot->poll= ED_operator_uvedit;
1317 }
1318
1319 /* ******************** (de)select all operator **************** */
1320
1321 static int select_all_exec(bContext *C, wmOperator *op)
1322 {
1323         Scene *scene;
1324         ToolSettings *ts;
1325         Object *obedit;
1326         EditMesh *em;
1327         EditFace *efa;
1328         Image *ima;
1329         MTFace *tf;
1330         int action = RNA_enum_get(op->ptr, "action");
1331         
1332         scene= CTX_data_scene(C);
1333         ts= CTX_data_tool_settings(C);
1334         obedit= CTX_data_edit_object(C);
1335         em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
1336         ima= CTX_data_edit_image(C);
1337         
1338         if(ts->uv_flag & UV_SYNC_SELECTION) {
1339                 switch (action) {
1340                 case SEL_TOGGLE:
1341                         EM_toggle_select_all(em);
1342                         break;
1343                 case SEL_SELECT:
1344                         EM_select_all(em);
1345                         break;
1346                 case SEL_DESELECT:
1347                         EM_deselect_all(em);
1348                         break;
1349                 case SEL_INVERT:
1350                         EM_select_swap(em);
1351                         break;
1352                 }
1353         }
1354         else {
1355
1356                 if (action == SEL_TOGGLE) {
1357                         action = SEL_SELECT;
1358                         for(efa= em->faces.first; efa; efa= efa->next) {
1359                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1360
1361                                 if(uvedit_face_visible(scene, ima, efa, tf)) {
1362                                         if(tf->flag & (TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4)) {
1363                                                 action = SEL_DESELECT;
1364                                                 break;
1365                                         }
1366                                 }
1367                         }
1368                 }
1369         
1370                 for(efa= em->faces.first; efa; efa= efa->next) {
1371                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1372
1373                         if(uvedit_face_visible(scene, ima, efa, tf)) {
1374                                 char select_flag;
1375
1376                                 if(efa->v4)
1377                                         select_flag = (TF_SEL1+TF_SEL2+TF_SEL3+TF_SEL4);
1378                                 else
1379                                         select_flag = (TF_SEL1+TF_SEL2+TF_SEL3);
1380
1381                                 switch (action) {
1382                                 case SEL_SELECT:
1383                                         tf->flag |= select_flag;
1384                                         break;
1385                                 case SEL_DESELECT:
1386                                         tf->flag &= ~select_flag;
1387                                         break;
1388                                 case SEL_INVERT:
1389                                         if ((tf->flag & select_flag) == select_flag) {
1390                                                 tf->flag &= ~select_flag;
1391                                         } else {
1392                                                 tf->flag &= ~select_flag;
1393                                         }
1394                                         break;
1395                                 }
1396                         }
1397                 }
1398         }
1399
1400         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
1401
1402         BKE_mesh_end_editmesh(obedit->data, em);
1403         return OPERATOR_FINISHED;
1404 }
1405
1406 void UV_OT_select_all(wmOperatorType *ot)
1407 {
1408         /* identifiers */
1409         ot->name= "Select or Deselect All";
1410         ot->description= "Change selection of all UV vertices";
1411         ot->idname= "UV_OT_select_all";
1412         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1413         
1414         /* api callbacks */
1415         ot->exec= select_all_exec;
1416         ot->poll= ED_operator_uvedit;
1417
1418         WM_operator_properties_select_all(ot);
1419 }
1420
1421 /* ******************** mouse select operator **************** */
1422
1423 static int sticky_select(float *limit, int hitv[4], int v, float *hituv[4], float *uv, int sticky)
1424 {
1425         int i;
1426
1427         /* this function test if some vertex needs to selected
1428          * in addition to the existing ones due to sticky select */
1429         if(sticky == SI_STICKY_DISABLE)
1430                 return 0;
1431
1432         for(i=0; i<4; i++) {
1433                 if(hitv[i] == v) {
1434                         if(sticky == SI_STICKY_LOC) {
1435                                 if(fabs(hituv[i][0]-uv[0]) < limit[0] && fabs(hituv[i][1]-uv[1]) < limit[1])
1436                                         return 1;
1437                         }
1438                         else if(sticky == SI_STICKY_VERTEX)
1439                                 return 1;
1440                 }
1441         }
1442
1443         return 0;
1444 }
1445
1446 static int mouse_select(bContext *C, float co[2], int extend, int loop)
1447 {
1448         SpaceImage *sima= CTX_wm_space_image(C);
1449         Scene *scene= CTX_data_scene(C);
1450         ToolSettings *ts= CTX_data_tool_settings(C);
1451         Object *obedit= CTX_data_edit_object(C);
1452         Image *ima= CTX_data_edit_image(C);
1453         EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
1454         EditFace *efa;
1455         MTFace *tf;
1456         NearestHit hit;
1457         int a, i, select = 1, selectmode, sticky, sync, hitv[4], nvert;
1458         int flush = 0; /* 0 == dont flush, 1 == sel, -1 == desel;  only use when selection sync is enabled */
1459         float limit[2], *hituv[4], penalty[2];
1460         
1461         uvedit_pixel_to_float(sima, limit, 0.05f);
1462         uvedit_pixel_to_float(sima, penalty, 5.0f);
1463
1464         /* retrieve operation mode */
1465         if(ts->uv_flag & UV_SYNC_SELECTION) {
1466                 sync= 1;
1467
1468                 if(ts->selectmode & SCE_SELECT_FACE)
1469                         selectmode= UV_SELECT_FACE;
1470                 else if(ts->selectmode & SCE_SELECT_EDGE)
1471                         selectmode= UV_SELECT_EDGE;
1472                 else
1473                         selectmode= UV_SELECT_VERTEX;
1474
1475                 sticky= SI_STICKY_DISABLE;
1476         }
1477         else {
1478                 sync= 0;
1479                 selectmode= ts->uv_selectmode;
1480                 sticky= (sima)? sima->sticky: 1;
1481         }
1482
1483         /* find nearest element */
1484         if(loop) {
1485                 /* find edge */
1486                 find_nearest_uv_edge(scene, ima, em, co, &hit);
1487                 if(hit.efa == NULL) {
1488                         BKE_mesh_end_editmesh(obedit->data, em);
1489                         return OPERATOR_CANCELLED;
1490                 }
1491         }
1492         else if(selectmode == UV_SELECT_VERTEX) {
1493                 /* find vertex */
1494                 find_nearest_uv_vert(scene, ima, em, co, penalty, &hit);
1495                 if(hit.efa == NULL) {
1496                         BKE_mesh_end_editmesh(obedit->data, em);
1497                         return OPERATOR_CANCELLED;
1498                 }
1499
1500                 /* mark 1 vertex as being hit */
1501                 for(i=0; i<4; i++)
1502                         hitv[i]= 0xFFFFFFFF;
1503
1504                 hitv[hit.uv]= hit.vert;
1505                 hituv[hit.uv]= hit.tf->uv[hit.uv];
1506         }
1507         else if(selectmode == UV_SELECT_EDGE) {
1508                 /* find edge */
1509                 find_nearest_uv_edge(scene, ima, em, co, &hit);
1510                 if(hit.efa == NULL) {
1511                         BKE_mesh_end_editmesh(obedit->data, em);
1512                         return OPERATOR_CANCELLED;
1513                 }
1514
1515                 /* mark 2 edge vertices as being hit */
1516                 for(i=0; i<4; i++)
1517                         hitv[i]= 0xFFFFFFFF;
1518
1519                 nvert= (hit.efa->v4)? 4: 3;
1520
1521                 hitv[hit.edge]= hit.vert;
1522                 hitv[(hit.edge+1)%nvert]= hit.vert2;
1523                 hituv[hit.edge]= hit.tf->uv[hit.edge];
1524                 hituv[(hit.edge+1)%nvert]= hit.tf->uv[(hit.edge+1)%nvert];
1525         }
1526         else if(selectmode == UV_SELECT_FACE) {
1527                 /* find face */
1528                 find_nearest_uv_face(scene, ima, em, co, &hit);
1529                 if(hit.efa == NULL) {
1530                         BKE_mesh_end_editmesh(obedit->data, em);
1531                         return OPERATOR_CANCELLED;
1532                 }
1533                 
1534                 /* make active */
1535                 EM_set_actFace(em, hit.efa);
1536
1537                 /* mark all face vertices as being hit */
1538                 for(i=0; i<4; i++)
1539                         hituv[i]= hit.tf->uv[i];
1540
1541                 hitv[0]= hit.efa->v1->tmp.l;
1542                 hitv[1]= hit.efa->v2->tmp.l;
1543                 hitv[2]= hit.efa->v3->tmp.l;
1544                 
1545                 if(hit.efa->v4) hitv[3]= hit.efa->v4->tmp.l;
1546                 else hitv[3]= 0xFFFFFFFF;
1547         }
1548         else if(selectmode == UV_SELECT_ISLAND) {
1549                 find_nearest_uv_vert(scene, ima, em, co, NULL, &hit);
1550
1551                 if(hit.efa==NULL) {
1552                         BKE_mesh_end_editmesh(obedit->data, em);
1553                         return OPERATOR_CANCELLED;
1554                 }
1555         }
1556         else {
1557                 BKE_mesh_end_editmesh(obedit->data, em);
1558                 return OPERATOR_CANCELLED;
1559         }
1560
1561         /* do selection */
1562         if(loop) {
1563                 flush= select_edgeloop(scene, ima, em, &hit, limit, extend);
1564         }
1565         else if(selectmode == UV_SELECT_ISLAND) {
1566                 select_linked(scene, ima, em, limit, &hit, extend);
1567         }
1568         else if(extend) {
1569                 if(selectmode == UV_SELECT_VERTEX) {
1570                         /* (de)select uv vertex */
1571                         if(uvedit_uv_selected(scene, hit.efa, hit.tf, hit.uv)) {
1572                                 uvedit_uv_deselect(scene, hit.efa, hit.tf, hit.uv);
1573                                 select= 0;
1574                         }
1575                         else {
1576                                 uvedit_uv_select(scene, hit.efa, hit.tf, hit.uv);
1577                                 select= 1;
1578                         }
1579                         flush = 1;
1580                 }
1581                 else if(selectmode == UV_SELECT_EDGE) {
1582                         /* (de)select edge */
1583                         if(uvedit_edge_selected(scene, hit.efa, hit.tf, hit.edge)) {
1584                                 uvedit_edge_deselect(scene, hit.efa, hit.tf, hit.edge);
1585                                 select= 0;
1586                         }
1587                         else {
1588                                 uvedit_edge_select(scene, hit.efa, hit.tf, hit.edge);
1589                                 select= 1;
1590                         }
1591                         flush = 1;
1592                 }
1593                 else if(selectmode == UV_SELECT_FACE) {
1594                         /* (de)select face */
1595                         if(uvedit_face_selected(scene, hit.efa, hit.tf)) {
1596                                 uvedit_face_deselect(scene, hit.efa, hit.tf);
1597                                 select= 0;
1598                         }
1599                         else {
1600                                 uvedit_face_select(scene, hit.efa, hit.tf);
1601                                 select= 1;
1602                         }
1603                         flush = -1;
1604                 }
1605
1606                 /* (de)select sticky uv nodes */
1607                 if(sticky != SI_STICKY_DISABLE) {
1608                         EditVert *ev;
1609                         
1610                         for(a=0, ev=em->verts.first; ev; ev = ev->next, a++)
1611                                 ev->tmp.l = a;
1612                         
1613                         /* deselect */
1614                         if(select==0) {
1615                                 for(efa= em->faces.first; efa; efa= efa->next) {
1616                                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1617
1618                                         if(uvedit_face_visible(scene, ima, efa, tf)) {
1619                                                 if(sticky_select(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
1620                                                         uvedit_uv_deselect(scene, efa, tf, 0);
1621                                                 if(sticky_select(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
1622                                                         uvedit_uv_deselect(scene, efa, tf, 1);
1623                                                 if(sticky_select(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
1624                                                         uvedit_uv_deselect(scene, efa, tf, 2);
1625                                                 if(efa->v4)
1626                                                         if(sticky_select(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
1627                                                                 uvedit_uv_deselect(scene, efa, tf, 3);
1628                                         }
1629                                 }
1630                                 flush = -1;
1631                         }
1632                         /* select */
1633                         else {
1634                                 for(efa= em->faces.first; efa; efa= efa->next) {
1635                                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1636
1637                                         if(uvedit_face_visible(scene, ima, efa, tf)) {
1638                                                 if(sticky_select(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
1639                                                         uvedit_uv_select(scene, efa, tf, 0);
1640                                                 if(sticky_select(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
1641                                                         uvedit_uv_select(scene, efa, tf, 1);
1642                                                 if(sticky_select(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
1643                                                         uvedit_uv_select(scene, efa, tf, 2);
1644                                                 if(efa->v4)
1645                                                         if(sticky_select(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
1646                                                                 uvedit_uv_select(scene, efa, tf, 3);
1647                                         }
1648                                 }
1649                                 
1650                                 flush = 1;
1651                         }                       
1652                 }
1653         }
1654         else {
1655                 /* deselect all */
1656                 for(efa= em->faces.first; efa; efa= efa->next) {
1657                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1658                         uvedit_face_deselect(scene, efa, tf);
1659                 }
1660
1661                 if(selectmode == UV_SELECT_VERTEX) {
1662                         /* select vertex */
1663                         uvedit_uv_select(scene, hit.efa, hit.tf, hit.uv);
1664                         flush= 1;
1665                 }
1666                 else if(selectmode == UV_SELECT_EDGE) {
1667                         /* select edge */
1668                         uvedit_edge_select(scene, hit.efa, hit.tf, hit.edge);
1669                         flush= 1;
1670                 }
1671                 else if(selectmode == UV_SELECT_FACE) {
1672                         /* select face */
1673                         uvedit_face_select(scene, hit.efa, hit.tf);
1674                 }
1675
1676                 /* select sticky uvs */
1677                 if(sticky != SI_STICKY_DISABLE) {
1678                         for(efa= em->faces.first; efa; efa= efa->next) {
1679                                 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1680                                 if(uvedit_face_visible(scene, ima, efa, tf)) {
1681                                         if(sticky == SI_STICKY_DISABLE) continue;
1682
1683                                         if(sticky_select(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
1684                                                 uvedit_uv_select(scene, efa, tf, 0);
1685                                         if(sticky_select(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
1686                                                 uvedit_uv_select(scene, efa, tf, 1);
1687                                         if(sticky_select(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
1688                                                 uvedit_uv_select(scene, efa, tf, 2);
1689                                         if(efa->v4)
1690                                                 if(sticky_select(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
1691                                                         uvedit_uv_select(scene, efa, tf, 3);
1692
1693                                         flush= 1;
1694                                 }
1695                         }
1696                 }
1697         }
1698         
1699         if(sync) {
1700                 /* flush for mesh selection */
1701                 if(ts->selectmode != SCE_SELECT_FACE) {
1702                         if(flush==1)            EM_select_flush(em);
1703                         else if(flush==-1)      EM_deselect_flush(em);
1704                 }
1705         }
1706         
1707         DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
1708         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
1709         
1710         BKE_mesh_end_editmesh(obedit->data, em);
1711         return OPERATOR_PASS_THROUGH|OPERATOR_FINISHED;
1712 }
1713
1714 static int select_exec(bContext *C, wmOperator *op)
1715 {
1716         float co[2];
1717         int extend, loop;
1718
1719         RNA_float_get_array(op->ptr, "location", co);
1720         extend= RNA_boolean_get(op->ptr, "extend");
1721         loop= 0;
1722
1723         return mouse_select(C, co, extend, loop);
1724 }
1725
1726 static int select_invoke(bContext *C, wmOperator *op, wmEvent *event)
1727 {
1728         ARegion *ar= CTX_wm_region(C);
1729         float co[2];
1730         int x, y;
1731
1732         x= event->x - ar->winrct.xmin;
1733         y= event->y - ar->winrct.ymin;
1734
1735         UI_view2d_region_to_view(&ar->v2d, x, y, &co[0], &co[1]);
1736         RNA_float_set_array(op->ptr, "location", co);
1737
1738         return select_exec(C, op);
1739 }
1740
1741 void UV_OT_select(wmOperatorType *ot)
1742 {
1743         /* identifiers */
1744         ot->name= "Select";
1745         ot->description= "Select UV vertice";
1746         ot->idname= "UV_OT_select";
1747         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1748         
1749         /* api callbacks */
1750         ot->exec= select_exec;
1751         ot->invoke= select_invoke;
1752         ot->poll= ED_operator_uvedit;
1753
1754         /* properties */
1755         RNA_def_boolean(ot->srna, "extend", 0,
1756                 "Extend", "Extend selection rather than clearing the existing selection.");
1757         RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
1758                 "Location", "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds.", -100.0f, 100.0f);
1759 }
1760
1761 /* ******************** loop select operator **************** */
1762
1763 static int select_loop_exec(bContext *C, wmOperator *op)
1764 {
1765         float co[2];
1766         int extend, loop;
1767
1768         RNA_float_get_array(op->ptr, "location", co);
1769         extend= RNA_boolean_get(op->ptr, "extend");
1770         loop= 1;
1771
1772         return mouse_select(C, co, extend, loop);
1773 }
1774
1775 static int select_loop_invoke(bContext *C, wmOperator *op, wmEvent *event)
1776 {
1777         ARegion *ar= CTX_wm_region(C);
1778         float co[2];
1779         int x, y;
1780
1781         x= event->x - ar->winrct.xmin;
1782         y= event->y - ar->winrct.ymin;
1783
1784         UI_view2d_region_to_view(&ar->v2d, x, y, &co[0], &co[1]);
1785         RNA_float_set_array(op->ptr, "location", co);
1786
1787         return select_loop_exec(C, op);
1788 }
1789
1790 void UV_OT_select_loop(wmOperatorType *ot)
1791 {
1792         /* identifiers */
1793         ot->name= "Loop Select";
1794         ot->description= "Select a loop of connected UV vertices";
1795         ot->idname= "UV_OT_select_loop";
1796         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1797         
1798         /* api callbacks */
1799         ot->exec= select_loop_exec;
1800         ot->invoke= select_loop_invoke;
1801         ot->poll= ED_operator_uvedit;
1802
1803         /* properties */
1804         RNA_def_boolean(ot->srna, "extend", 0,
1805                 "Extend", "Extend selection rather than clearing the existing selection.");
1806         RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
1807                 "Location", "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds.", -100.0f, 100.0f);
1808 }
1809
1810 /* ******************** linked select operator **************** */
1811
1812 static int select_linked_internal(bContext *C, wmOperator *op, wmEvent *event, int pick)
1813 {
1814         SpaceImage *sima= CTX_wm_space_image(C);
1815         Scene *scene= CTX_data_scene(C);
1816         ToolSettings *ts= CTX_data_tool_settings(C);
1817         Object *obedit= CTX_data_edit_object(C);
1818         Image *ima= CTX_data_edit_image(C);
1819         EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
1820         float limit[2];
1821         int extend;
1822
1823         NearestHit hit, *hit_p= NULL;
1824
1825         if(ts->uv_flag & UV_SYNC_SELECTION) {
1826                 BKE_report(op->reports, RPT_ERROR, "Can't select linked when sync selection is enabled.");
1827                 BKE_mesh_end_editmesh(obedit->data, em);
1828                 return OPERATOR_CANCELLED;
1829         }
1830
1831         extend= RNA_boolean_get(op->ptr, "extend");
1832         uvedit_pixel_to_float(sima, limit, 0.05f);
1833
1834         if(pick) {
1835                 float co[2];
1836
1837                 if(event) {
1838                         /* invoke */
1839                         ARegion *ar= CTX_wm_region(C);
1840                         int x, y;
1841
1842                         x= event->x - ar->winrct.xmin;
1843                         y= event->y - ar->winrct.ymin;
1844
1845                         UI_view2d_region_to_view(&ar->v2d, x, y, &co[0], &co[1]);
1846                         RNA_float_set_array(op->ptr, "location", co);
1847                 }
1848                 else {
1849                         /* exec */
1850                         RNA_float_get_array(op->ptr, "location", co);
1851                 }
1852
1853                 find_nearest_uv_vert(scene, ima, em, co, NULL, &hit);
1854                 hit_p= &hit;
1855         }
1856
1857         select_linked(scene, ima, em, limit, hit_p, extend);
1858
1859         DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
1860         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
1861
1862         BKE_mesh_end_editmesh(obedit->data, em);
1863         return OPERATOR_FINISHED;
1864 }
1865
1866 static int select_linked_exec(bContext *C, wmOperator *op)
1867 {
1868         return select_linked_internal(C, op, NULL, 0);
1869 }
1870
1871 void UV_OT_select_linked(wmOperatorType *ot)
1872 {
1873         /* identifiers */
1874         ot->name= "Select Linked";
1875         ot->description= "Select all UV vertices linked to the active UV map";
1876         ot->idname= "UV_OT_select_linked";
1877         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1878         
1879         /* api callbacks */
1880         ot->exec= select_linked_exec;
1881         ot->poll= ED_operator_uvedit;
1882
1883         /* properties */
1884         RNA_def_boolean(ot->srna, "extend", 0,
1885                 "Extend", "Extend selection rather than clearing the existing selection.");
1886 }
1887
1888 static int select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
1889 {
1890         return select_linked_internal(C, op, event, 1);
1891 }
1892
1893 static int select_linked_pick_exec(bContext *C, wmOperator *op)
1894 {
1895         return select_linked_internal(C, op, NULL, 1);
1896 }
1897
1898 void UV_OT_select_linked_pick(wmOperatorType *ot)
1899 {
1900         /* identifiers */
1901         ot->name= "Select Linked Pick";
1902         ot->description= "Select all UV vertices linked under the mouse";
1903         ot->idname= "UV_OT_select_linked_pick";
1904         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1905
1906         /* api callbacks */
1907         ot->invoke= select_linked_pick_invoke;
1908         ot->exec= select_linked_pick_exec;
1909         ot->poll= ED_operator_uvedit;
1910
1911         /* properties */
1912         RNA_def_boolean(ot->srna, "extend", 0,
1913                 "Extend", "Extend selection rather than clearing the existing selection.");
1914
1915         RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
1916                 "Location", "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds.", -100.0f, 100.0f);
1917 }
1918
1919 /* ******************** unlink selection operator **************** */
1920
1921 static int unlink_selection_exec(bContext *C, wmOperator *op)
1922 {
1923         Scene *scene= CTX_data_scene(C);
1924         ToolSettings *ts= CTX_data_tool_settings(C);
1925         Object *obedit= CTX_data_edit_object(C);
1926         Image *ima= CTX_data_edit_image(C);
1927         EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
1928         EditFace *efa;
1929         MTFace *tf;
1930
1931         if(ts->uv_flag & UV_SYNC_SELECTION) {
1932                 BKE_report(op->reports, RPT_ERROR, "Can't unlink selection when sync selection is enabled.");
1933                 BKE_mesh_end_editmesh(obedit->data, em);
1934                 return OPERATOR_CANCELLED;
1935         }
1936         
1937         for(efa= em->faces.first; efa; efa= efa->next) {
1938                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1939
1940                 if(uvedit_face_visible(scene, ima, efa, tf)) {
1941                         if(efa->v4) {
1942                                 if(~tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4))
1943                                         tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
1944                         }
1945                         else {
1946                                 if(~tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
1947                                         tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3);
1948                         }
1949                 }
1950         }
1951         
1952         DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
1953         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
1954
1955         BKE_mesh_end_editmesh(obedit->data, em);
1956         return OPERATOR_FINISHED;
1957 }
1958
1959 void UV_OT_unlink_selection(wmOperatorType *ot)
1960 {
1961         /* identifiers */
1962         ot->name= "Unlink Selection";
1963         ot->description= "Unlink selected UV vertices from active UV map";
1964         ot->idname= "UV_OT_unlink_selection";
1965         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1966         
1967         /* api callbacks */
1968         ot->exec= unlink_selection_exec;
1969         ot->poll= ED_operator_uvedit;
1970 }
1971
1972 /* ******************** border select operator **************** */
1973
1974 /* This function sets the selection on tagged faces, need because settings the
1975  * selection a face is done in a number of places but it also needs to respect
1976  * the sticky modes for the UV verts, so dealing with the sticky modes is best
1977  * done in a separate function.
1978  * 
1979  * De-selects faces that have been tagged on efa->tmp.l.  */
1980
1981 static void uv_faces_do_sticky(bContext *C, SpaceImage *sima, Scene *scene, Object *obedit, short select)
1982 {
1983         /* Selecting UV Faces with some modes requires us to change 
1984          * the selection in other faces (depending on the sticky mode).
1985          * 
1986          * This only needs to be done when the Mesh is not used for
1987          * selection (so for sticky modes, vertex or location based). */
1988         
1989         ToolSettings *ts= CTX_data_tool_settings(C);
1990         EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
1991         EditFace *efa;
1992         MTFace *tf;
1993         int nverts, i;
1994         
1995         if((ts->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_VERTEX) {
1996                 /* Tag all verts as untouched, then touch the ones that have a face center
1997                  * in the loop and select all MTFace UV's that use a touched vert. */
1998                 EditVert *eve;
1999                 
2000                 for(eve= em->verts.first; eve; eve= eve->next)
2001                         eve->tmp.l = 0;
2002                 
2003                 for(efa= em->faces.first; efa; efa= efa->next) {
2004                         if(efa->tmp.l) {
2005                                 if(efa->v4)
2006                                         efa->v1->tmp.l= efa->v2->tmp.l= efa->v3->tmp.l= efa->v4->tmp.l=1;
2007                                 else
2008                                         efa->v1->tmp.l= efa->v2->tmp.l= efa->v3->tmp.l= 1;
2009                         }
2010                 }
2011
2012                 /* now select tagged verts */
2013                 for(efa= em->faces.first; efa; efa= efa->next) {
2014                         tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);               
2015                         nverts= efa->v4? 4: 3;
2016                         for(i=0; i<nverts; i++) {
2017                                 if((*(&efa->v1 + i))->tmp.l) {
2018                                         if(select)
2019                                                 uvedit_uv_select(scene, efa, tf, i);
2020                                         else
2021                                                 uvedit_uv_deselect(scene, efa, tf, i);
2022                                 }
2023                         }
2024                 }
2025         }
2026         else if((ts->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_LOC) {
2027                 EditFace *efa_vlist;
2028                 MTFace *tf_vlist;
2029                 UvMapVert *start_vlist=NULL, *vlist_iter;
2030                 struct UvVertMap *vmap;
2031                 float limit[2];
2032                 int efa_index;
2033                 //EditVert *eve; /* removed vert counting for now */ 
2034                 //int a;
2035                 
2036                 uvedit_pixel_to_float(sima, limit, 0.05);
2037                 
2038                 EM_init_index_arrays(em, 0, 0, 1);
2039                 vmap= EM_make_uv_vert_map(em, 0, 0, limit);
2040                 
2041                 /* verts are numbered above in make_uv_vert_map_EM, make sure this stays true! */
2042                 /*for(a=0, eve= em->verts.first; eve; a++, eve= eve->next)
2043                         eve->tmp.l = a; */
2044                 
2045                 if(vmap == NULL) {
2046                         BKE_mesh_end_editmesh(obedit->data, em);
2047                         return;
2048                 }
2049                 
2050                 for(efa_index=0, efa= em->faces.first; efa; efa_index++, efa= efa->next) {
2051                         if(efa->tmp.l) {
2052                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2053                                 nverts= efa->v4? 4: 3;
2054
2055                                 for(i=0; i<nverts; i++) {
2056                                         if(select)
2057                                                 uvedit_uv_select(scene, efa, tf, i);
2058                                         else
2059                                                 uvedit_uv_deselect(scene, efa, tf, i);
2060                                         
2061                                         vlist_iter= EM_get_uv_map_vert(vmap, (*(&efa->v1 + i))->tmp.l);
2062                                         
2063                                         while (vlist_iter) {
2064                                                 if(vlist_iter->separate)
2065                                                         start_vlist = vlist_iter;
2066                                                 
2067                                                 if(efa_index == vlist_iter->f)
2068                                                         break;
2069
2070                                                 vlist_iter = vlist_iter->next;
2071                                         }
2072                                 
2073                                         vlist_iter = start_vlist;
2074                                         while (vlist_iter) {
2075                                                 
2076                                                 if(vlist_iter != start_vlist && vlist_iter->separate)
2077                                                         break;
2078                                                 
2079                                                 if(efa_index != vlist_iter->f) {
2080                                                         efa_vlist = EM_get_face_for_index(vlist_iter->f);
2081                                                         tf_vlist = CustomData_em_get(&em->fdata, efa_vlist->data, CD_MTFACE);
2082                                                         
2083                                                         if(select)
2084                                                                 uvedit_uv_select(scene, efa_vlist, tf_vlist, vlist_iter->tfindex);
2085                                                         else
2086                                                                 uvedit_uv_deselect(scene, efa_vlist, tf_vlist, vlist_iter->tfindex);
2087                                                 }
2088                                                 vlist_iter = vlist_iter->next;
2089                                         }
2090                                 }
2091                         }
2092                 }
2093                 EM_free_index_arrays();
2094                 EM_free_uv_vert_map(vmap);
2095                 
2096         }
2097         else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */
2098                 for(efa= em->faces.first; efa; efa= efa->next) {
2099                         if(efa->tmp.l) {
2100                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2101                                 if(select)
2102                                         uvedit_face_select(scene, efa, tf);
2103                                 else
2104                                         uvedit_face_deselect(scene, efa, tf);
2105                         }
2106                 }
2107         }
2108         BKE_mesh_end_editmesh(obedit->data, em);
2109 }
2110
2111 static int border_select_exec(bContext *C, wmOperator *op)
2112 {
2113         SpaceImage *sima= CTX_wm_space_image(C);
2114         Scene *scene= CTX_data_scene(C);
2115         ToolSettings *ts= CTX_data_tool_settings(C);
2116         Object *obedit= CTX_data_edit_object(C);
2117         Image *ima= CTX_data_edit_image(C);
2118         ARegion *ar= CTX_wm_region(C);
2119         EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
2120         EditFace *efa;
2121         MTFace *tface;
2122         rcti rect;
2123         rctf rectf;
2124         int change, pinned, select, faces;
2125
2126         /* get rectangle from operator */
2127         rect.xmin= RNA_int_get(op->ptr, "xmin");
2128         rect.ymin= RNA_int_get(op->ptr, "ymin");
2129         rect.xmax= RNA_int_get(op->ptr, "xmax");
2130         rect.ymax= RNA_int_get(op->ptr, "ymax");
2131                 
2132         UI_view2d_region_to_view(&ar->v2d, rect.xmin, rect.ymin, &rectf.xmin, &rectf.ymin);
2133         UI_view2d_region_to_view(&ar->v2d, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax);
2134
2135         /* figure out what to select/deselect */
2136         select= (RNA_int_get(op->ptr, "gesture_mode") == GESTURE_MODAL_SELECT);
2137         pinned= RNA_boolean_get(op->ptr, "pinned");
2138         
2139         if(ts->uv_flag & UV_SYNC_SELECTION)
2140                 faces= (ts->selectmode == SCE_SELECT_FACE);
2141         else
2142                 faces= (ts->uv_selectmode == UV_SELECT_FACE);
2143
2144         /* do actual selection */
2145         if(faces && !pinned) {
2146                 /* handle face selection mode */
2147                 float cent[2];
2148
2149                 change= 0;
2150
2151                 for(efa= em->faces.first; efa; efa= efa->next) {
2152                         /* assume not touched */
2153                         efa->tmp.l = 0;
2154                         tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2155                         if(uvedit_face_visible(scene, ima, efa, tface)) {
2156                                 uv_center(tface->uv, cent, efa->v4 != NULL);
2157                                 if(BLI_in_rctf(&rectf, cent[0], cent[1])) {
2158                                         efa->tmp.l = change = 1;
2159                                 }
2160                         }
2161                 }
2162
2163                 /* (de)selects all tagged faces and deals with sticky modes */
2164                 if(change)
2165                         uv_faces_do_sticky(C, sima, scene, obedit, select);
2166         }
2167         else {
2168                 /* other selection modes */
2169                 change= 1;
2170
2171                 for(efa= em->faces.first; efa; efa= efa->next) {
2172                         tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2173                         if(uvedit_face_visible(scene, ima, efa, tface)) {
2174                                 if(!pinned || (ts->uv_flag & UV_SYNC_SELECTION) ) {
2175                                         /* UV_SYNC_SELECTION - can't do pinned selection */
2176                                         if(BLI_in_rctf(&rectf, tface->uv[0][0], tface->uv[0][1])) {
2177                                                 if(select)      uvedit_uv_select(scene, efa, tface, 0);
2178                                                 else            uvedit_uv_deselect(scene, efa, tface, 0);
2179                                         }
2180                                         if(BLI_in_rctf(&rectf, tface->uv[1][0], tface->uv[1][1])) {
2181                                                 if(select)      uvedit_uv_select(scene, efa, tface, 1);
2182                                                 else            uvedit_uv_deselect(scene, efa, tface, 1);
2183                                         }
2184                                         if(BLI_in_rctf(&rectf, tface->uv[2][0], tface->uv[2][1])) {
2185                                                 if(select)      uvedit_uv_select(scene, efa, tface, 2);
2186                                                 else            uvedit_uv_deselect(scene, efa, tface, 2);
2187                                         }
2188                                         if(efa->v4 && BLI_in_rctf(&rectf, tface->uv[3][0], tface->uv[3][1])) {
2189                                                 if(select)      uvedit_uv_select(scene, efa, tface, 3);
2190                                                 else            uvedit_uv_deselect(scene, efa, tface, 3);
2191                                         }
2192                                 }
2193                                 else if(pinned) {
2194                                         if((tface->unwrap & TF_PIN1) && 
2195                                                 BLI_in_rctf(&rectf, tface->uv[0][0], tface->uv[0][1])) {
2196                                                 
2197                                                 if(select)      uvedit_uv_select(scene, efa, tface, 0);
2198                                                 else            uvedit_uv_deselect(scene, efa, tface, 0);
2199                                         }
2200                                         if((tface->unwrap & TF_PIN2) && 
2201                                                 BLI_in_rctf(&rectf, tface->uv[1][0], tface->uv[1][1])) {
2202                                                 
2203                                                 if(select)      uvedit_uv_select(scene, efa, tface, 1);
2204                                                 else            uvedit_uv_deselect(scene, efa, tface, 1);
2205                                         }
2206                                         if((tface->unwrap & TF_PIN3) && 
2207                                                 BLI_in_rctf(&rectf, tface->uv[2][0], tface->uv[2][1])) {
2208                                                 
2209                                                 if(select)      uvedit_uv_select(scene, efa, tface, 2);
2210                                                 else            uvedit_uv_deselect(scene, efa, tface, 2);
2211                                         }
2212                                         if((efa->v4) && (tface->unwrap & TF_PIN4) && BLI_in_rctf(&rectf, tface->uv[3][0], tface->uv[3][1])) {
2213                                                 if(select)      uvedit_uv_select(scene, efa, tface, 3);
2214                                                 else            uvedit_uv_deselect(scene, efa, tface, 3);
2215                                         }
2216                                 }
2217                         }
2218                 }
2219         }
2220
2221         if(change) {
2222                 /* make sure newly selected vert selection is updated*/
2223                 if(ts->uv_flag & UV_SYNC_SELECTION) {
2224                         if(ts->selectmode != SCE_SELECT_FACE) {
2225                                 if(select)      EM_select_flush(em);
2226                                 else            EM_deselect_flush(em);
2227                         }
2228                 }
2229
2230                 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
2231                 
2232                 BKE_mesh_end_editmesh(obedit->data, em);
2233                 return OPERATOR_FINISHED;
2234         }
2235         
2236         BKE_mesh_end_editmesh(obedit->data, em);
2237         return OPERATOR_CANCELLED;
2238
2239
2240 void UV_OT_select_border(wmOperatorType *ot)
2241 {
2242         /* identifiers */
2243         ot->name= "Border Select";
2244         ot->description= "Select UV vertices using border selection";
2245         ot->idname= "UV_OT_select_border";
2246         
2247         /* api callbacks */
2248         ot->invoke= WM_border_select_invoke;
2249         ot->exec= border_select_exec;
2250         ot->modal= WM_border_select_modal;
2251         ot->poll= ED_operator_uvedit;
2252         
2253         /* flags */
2254         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2255         
2256         /* properties */
2257         RNA_def_boolean(ot->srna, "pinned", 0, "Pinned", "Border select pinned UVs only.");
2258
2259         WM_operator_properties_gesture_border(ot, FALSE);
2260 }
2261
2262 /* ******************** circle select operator **************** */
2263
2264 static void select_uv_inside_ellipse(SpaceImage *sima, Scene *scene, int select, EditFace *efa, MTFace *tface, int index, float *offset, float *ell, int select_index)
2265 {
2266         /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */
2267         float x, y, r2, *uv;
2268         
2269         uv= tface->uv[index];
2270
2271         x= (uv[0] - offset[0])*ell[0];
2272         y= (uv[1] - offset[1])*ell[1];
2273
2274         r2 = x*x + y*y;
2275         if(r2 < 1.0) {
2276                 if(select)      uvedit_uv_select(scene, efa, tface, select_index);
2277                 else uvedit_uv_deselect(scene, efa, tface, select_index);
2278         }
2279 }
2280
2281 int circle_select_exec(bContext *C, wmOperator *op)
2282 {
2283         SpaceImage *sima= CTX_wm_space_image(C);
2284         Scene *scene= CTX_data_scene(C);
2285         Object *obedit= CTX_data_edit_object(C);
2286         EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
2287         ARegion *ar= CTX_wm_region(C);
2288         EditFace *efa;
2289         MTFace *tface;
2290         int x, y, radius, width, height, select;
2291         float zoomx, zoomy, offset[2], ellipse[2];
2292         int gesture_mode= RNA_int_get(op->ptr, "gesture_mode");
2293     
2294         /* get operator properties */
2295         select= (gesture_mode == GESTURE_MODAL_SELECT);
2296         x= RNA_int_get(op->ptr, "x");
2297         y= RNA_int_get(op->ptr, "y");
2298         radius= RNA_int_get(op->ptr, "radius");
2299
2300         /* compute ellipse size and location, not a circle since we deal
2301          * with non square image. ellipse is normalized, r = 1.0. */
2302         ED_space_image_size(sima, &width, &height);
2303         ED_space_image_zoom(sima, ar, &zoomx, &zoomy);
2304
2305         ellipse[0]= width*zoomx/radius;
2306         ellipse[1]= height*zoomy/radius;
2307
2308         UI_view2d_region_to_view(&ar->v2d, x, y, &offset[0], &offset[1]);
2309         
2310         /* do selection */
2311         for(efa= em->faces.first; efa; efa= efa->next) {
2312                 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2313                 select_uv_inside_ellipse(sima, scene, select, efa, tface, 0, offset, ellipse, 0);
2314                 select_uv_inside_ellipse(sima, scene, select, efa, tface, 1, offset, ellipse, 1);
2315                 select_uv_inside_ellipse(sima, scene, select, efa, tface, 2, offset, ellipse, 2);
2316                 if(efa->v4)
2317                         select_uv_inside_ellipse(sima, scene, select, efa, tface, 3, offset, ellipse, 3);
2318         }
2319
2320         if(select) EM_select_flush(em);
2321         else EM_deselect_flush(em);
2322
2323         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
2324
2325         BKE_mesh_end_editmesh(obedit->data, em);
2326         return OPERATOR_FINISHED;
2327 }
2328
2329 void UV_OT_circle_select(wmOperatorType *ot)
2330 {
2331         /* identifiers */
2332         ot->name= "Circle Select";
2333         ot->description= "Select UV vertices using circle selection";
2334         ot->idname= "UV_OT_circle_select";
2335         
2336         /* api callbacks */
2337         ot->invoke= WM_gesture_circle_invoke;
2338         ot->modal= WM_gesture_circle_modal;
2339         ot->exec= circle_select_exec;
2340         ot->poll= ED_operator_uvedit;
2341         
2342         /* flags */
2343         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2344         
2345         /* properties */
2346         RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX);
2347         RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX);
2348         RNA_def_int(ot->srna, "radius", 0, INT_MIN, INT_MAX, "Radius", "", INT_MIN, INT_MAX);
2349         RNA_def_int(ot->srna, "gesture_mode", 0, INT_MIN, INT_MAX, "Gesture Mode", "", INT_MIN, INT_MAX);
2350 }
2351
2352 /* ******************** snap cursor operator **************** */
2353
2354 static void snap_uv_to_pixel(float *uvco, float w, float h)
2355 {
2356         uvco[0] = ((float)((int)((uvco[0]*w) + 0.5f)))/w;
2357         uvco[1] = ((float)((int)((uvco[1]*h) + 0.5f)))/h;
2358 }
2359
2360 static void snap_cursor_to_pixels(SpaceImage *sima)
2361 {
2362         int width= 0, height= 0;
2363
2364         ED_space_image_size(sima, &width, &height);
2365         snap_uv_to_pixel(sima->cursor, width, height);
2366 }
2367
2368 static int snap_cursor_to_selection(Scene *scene, Image *ima, Object *obedit, SpaceImage *sima)
2369 {
2370         return uvedit_center(scene, ima, obedit, sima->cursor, 0);
2371 }
2372
2373 static int snap_cursor_exec(bContext *C, wmOperator *op)
2374 {
2375         SpaceImage *sima= CTX_wm_space_image(C);
2376         Scene *scene= CTX_data_scene(C);
2377         Object *obedit= CTX_data_edit_object(C);
2378         Image *ima= CTX_data_edit_image(C);
2379         int change= 0;
2380
2381         switch(RNA_boolean_get(op->ptr, "target")) {
2382                 case 0:
2383                         snap_cursor_to_pixels(sima);
2384                         change= 1;
2385                         break;
2386                 case 1:
2387                         change= snap_cursor_to_selection(scene, ima, obedit, sima);
2388                         break;
2389         }
2390
2391         if(!change)
2392                 return OPERATOR_CANCELLED;
2393         
2394         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_IMAGE, sima);
2395
2396         return OPERATOR_FINISHED;
2397 }
2398
2399 void UV_OT_snap_cursor(wmOperatorType *ot)
2400 {
2401         static EnumPropertyItem target_items[] = {
2402                 {0, "PIXELS", 0, "Pixels", ""},
2403                 {1, "SELECTION", 0, "Selection", ""},
2404                 {0, NULL, 0, NULL, NULL}};
2405
2406         /* identifiers */
2407         ot->name= "Snap Cursor";
2408         ot->description= "Snap cursor to target type";
2409         ot->idname= "UV_OT_snap_cursor";
2410         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2411         
2412         /* api callbacks */
2413         ot->exec= snap_cursor_exec;
2414         ot->poll= ED_operator_uvedit;
2415
2416         /* properties */
2417         RNA_def_enum(ot->srna, "target", target_items, 0, "Target", "Target to snap the selected UV's to.");
2418 }
2419
2420 /* ******************** snap selection operator **************** */
2421
2422 static int snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, SpaceImage *sima)
2423 {
2424         EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
2425         EditFace *efa;
2426         MTFace *tface;
2427         short change= 0;
2428
2429         for(efa= em->faces.first; efa; efa= efa->next) {
2430                 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2431                 if(uvedit_face_visible(scene, ima, efa, tface)) {
2432                         if(uvedit_uv_selected(scene, efa, tface, 0))            VECCOPY2D(tface->uv[0], sima->cursor);
2433                         if(uvedit_uv_selected(scene, efa, tface, 1))            VECCOPY2D(tface->uv[1], sima->cursor);
2434                         if(uvedit_uv_selected(scene, efa, tface, 2))            VECCOPY2D(tface->uv[2], sima->cursor);
2435                         if(efa->v4)
2436                                 if(uvedit_uv_selected(scene, efa, tface, 3))    VECCOPY2D(tface->uv[3], sima->cursor);
2437
2438                         change= 1;
2439                 }
2440         }
2441
2442         BKE_mesh_end_editmesh(obedit->data, em);
2443         return change;
2444 }
2445
2446 static int snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obedit)
2447 {
2448         EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
2449         EditFace *efa;
2450         EditVert *eve;
2451         MTFace *tface;
2452         short change = 0;
2453         int count = 0;
2454         float *coords;
2455         short *usercount, users;
2456         
2457         /* set all verts to -1 : an unused index*/
2458         for(eve= em->verts.first; eve; eve= eve->next)
2459                 eve->tmp.l=-1;
2460         
2461         /* index every vert that has a selected UV using it, but only once so as to
2462          * get unique indicies and to count how much to malloc */
2463         for(efa= em->faces.first; efa; efa= efa->next) {
2464                 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2465
2466                 if(uvedit_face_visible(scene, ima, efa, tface)) {
2467                         if(uvedit_uv_selected(scene, efa, tface, 0) && efa->v1->tmp.l==-1)              efa->v1->tmp.l= count++;
2468                         if(uvedit_uv_selected(scene, efa, tface, 1) && efa->v2->tmp.l==-1)              efa->v2->tmp.l= count++;
2469                         if(uvedit_uv_selected(scene, efa, tface, 2) && efa->v3->tmp.l==-1)              efa->v3->tmp.l= count++;
2470                         if(efa->v4)
2471                                 if(uvedit_uv_selected(scene, efa, tface, 3) && efa->v4->tmp.l==-1)      efa->v4->tmp.l= count++;
2472
2473                         change = 1;
2474                         
2475                         /* optional speedup */
2476                         efa->tmp.p = tface;
2477                 }
2478                 else
2479                         efa->tmp.p = NULL;
2480         }
2481         
2482         coords = MEM_callocN(sizeof(float)*count*2, "snap to adjacent coords");
2483         usercount = MEM_callocN(sizeof(short)*count, "snap to adjacent counts");
2484         
2485         /* add all UV coords from visible, unselected UV coords as well as counting them to average later */
2486         for(efa= em->faces.first; efa; efa= efa->next) {
2487                 if((tface=(MTFace *)efa->tmp.p)) {
2488                         /* is this an unselected UV we can snap to? */
2489                         if(efa->v1->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 0))) {
2490                                 coords[efa->v1->tmp.l*2] +=             tface->uv[0][0];
2491                                 coords[(efa->v1->tmp.l*2)+1] += tface->uv[0][1];
2492                                 usercount[efa->v1->tmp.l]++;
2493                                 change = 1;
2494                         }
2495                         if(efa->v2->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 1))) {
2496                                 coords[efa->v2->tmp.l*2] +=             tface->uv[1][0];
2497                                 coords[(efa->v2->tmp.l*2)+1] += tface->uv[1][1];
2498                                 usercount[efa->v2->tmp.l]++;
2499                                 change = 1;
2500                         }
2501                         if(efa->v3->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 2))) {
2502                                 coords[efa->v3->tmp.l*2] +=             tface->uv[2][0];
2503                                 coords[(efa->v3->tmp.l*2)+1] += tface->uv[2][1];
2504                                 usercount[efa->v3->tmp.l]++;
2505                                 change = 1;
2506                         }
2507                         
2508                         if(efa->v4) {
2509                                 if(efa->v4->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 3))) {
2510                                         coords[efa->v4->tmp.l*2] +=             tface->uv[3][0];
2511                                         coords[(efa->v4->tmp.l*2)+1] += tface->uv[3][1];
2512                                         usercount[efa->v4->tmp.l]++;
2513                                         change = 1;
2514                                 }
2515                         }
2516                 }
2517         }
2518         
2519         /* no other verts selected, bail out */
2520         if(!change) {
2521                 MEM_freeN(coords);
2522                 MEM_freeN(usercount);
2523                 BKE_mesh_end_editmesh(obedit->data, em);
2524                 return change;
2525         }
2526         
2527         /* copy the averaged unselected UVs back to the selected UVs */
2528         for(efa= em->faces.first; efa; efa= efa->next) {
2529                 if((tface=(MTFace *)efa->tmp.p)) {
2530                         
2531                         if(     uvedit_uv_selected(scene, efa, tface, 0) &&
2532                                         efa->v1->tmp.l >= 0 &&
2533                                         (users = usercount[efa->v1->tmp.l])
2534                         ) {
2535                                 tface->uv[0][0] = coords[efa->v1->tmp.l*2]              / users;
2536                                 tface->uv[0][1] = coords[(efa->v1->tmp.l*2)+1]  / users;
2537                         }
2538
2539                         if(     uvedit_uv_selected(scene, efa, tface, 1) &&
2540                                         efa->v2->tmp.l >= 0 &&
2541                                         (users = usercount[efa->v2->tmp.l])
2542                         ) {
2543                                 tface->uv[1][0] = coords[efa->v2->tmp.l*2]              / users;
2544                                 tface->uv[1][1] = coords[(efa->v2->tmp.l*2)+1]  / users;
2545                         }
2546                         
2547                         if(     uvedit_uv_selected(scene, efa, tface, 2) &&
2548                                         efa->v3->tmp.l >= 0 &&
2549                                         (users = usercount[efa->v3->tmp.l])
2550                         ) {
2551                                 tface->uv[2][0] = coords[efa->v3->tmp.l*2]              / users;
2552                                 tface->uv[2][1] = coords[(efa->v3->tmp.l*2)+1]  / users;
2553                         }
2554                         
2555                         if(efa->v4) {
2556                                 if(     uvedit_uv_selected(scene, efa, tface, 3) &&
2557                                                 efa->v4->tmp.l >= 0 &&
2558                                                 (users = usercount[efa->v4->tmp.l])
2559                                 ) {
2560                                         tface->uv[3][0] = coords[efa->v4->tmp.l*2]              / users;
2561                                         tface->uv[3][1] = coords[(efa->v4->tmp.l*2)+1]  / users;
2562                                 }
2563                         }
2564                 }
2565         }
2566         
2567         MEM_freeN(coords);
2568         MEM_freeN(usercount);
2569
2570         BKE_mesh_end_editmesh(obedit->data, em);
2571         return change;
2572 }
2573
2574 static int snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit)
2575 {
2576         EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
2577         Image *ima;
2578         EditFace *efa;
2579         MTFace *tface;
2580         int width= 0, height= 0;
2581         float w, h;
2582         short change = 0;
2583
2584         if(!sima)
2585                 return 0;
2586         
2587         ima= sima->image;
2588         
2589         ED_space_image_size(sima, &width, &height);
2590         w = (float)width;
2591         h = (float)height;
2592         
2593         for(efa= em->faces.first; efa; efa= efa->next) {
2594                 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2595                 if(uvedit_face_visible(scene, ima, efa, tface)) {
2596                         if(uvedit_uv_selected(scene, efa, tface, 0)) snap_uv_to_pixel(tface->uv[0], w, h);
2597                         if(uvedit_uv_selected(scene, efa, tface, 1)) snap_uv_to_pixel(tface->uv[1], w, h);
2598                         if(uvedit_uv_selected(scene, efa, tface, 2)) snap_uv_to_pixel(tface->uv[2], w, h);
2599                         if(efa->v4)
2600                                 if(uvedit_uv_selected(scene, efa, tface, 3)) snap_uv_to_pixel(tface->uv[3], w, h);
2601
2602                         change = 1;
2603                 }
2604         }
2605
2606         BKE_mesh_end_editmesh(obedit->data, em);
2607         return change;
2608 }
2609
2610 static int snap_selection_exec(bContext *C, wmOperator *op)
2611 {
2612         SpaceImage *sima= CTX_wm_space_image(C);
2613         Scene *scene= CTX_data_scene(C);
2614         Object *obedit= CTX_data_edit_object(C);
2615         Image *ima= CTX_data_edit_image(C);
2616         int change= 0;
2617
2618         switch(RNA_boolean_get(op->ptr, "target")) {
2619                 case 0:
2620                         change= snap_uvs_to_pixels(sima, scene, obedit);
2621                         break;
2622                 case 1:
2623                         change= snap_uvs_to_cursor(scene, ima, obedit, sima);
2624                         break;
2625                 case 2:
2626                         change= snap_uvs_to_adjacent_unselected(scene, ima, obedit);
2627                         break;
2628         }
2629
2630         if(!change)
2631                 return OPERATOR_CANCELLED;
2632         
2633         DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
2634         WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
2635
2636         return OPERATOR_FINISHED;
2637 }
2638
2639 void UV_OT_snap_selection(wmOperatorType *ot)
2640 {
2641         static EnumPropertyItem target_items[] = {
2642                 {0, "PIXELS", 0, "Pixels", ""},
2643                 {1, "CURSOR", 0, "Cursor", ""},
2644                 {2, "ADJACENT_UNSELECTED", 0, "Adjacent Unselected", ""},
2645                 {0, NULL, 0, NULL, NULL}};
2646
2647         /* identifiers */
2648         ot->name= "Snap Selection";
2649         ot->description= "Snap selected UV vertices to target type";
2650         ot->idname= "UV_OT_snap_selection";
2651         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2652         
2653         /* api callbacks */
2654         ot->exec= snap_selection_exec;
2655         ot->poll= ED_operator_uvedit;
2656
2657         /* properties */
2658         RNA_def_enum(ot->srna, "target", target_items, 0, "Target", "Target to snap the selected UV's to.");
2659 }
2660
2661 /* ******************** pin operator **************** */
2662
2663 static int pin_exec(bContext *C, wmOperator *op)
2664 {
2665         Scene *scene= CTX_data_scene(C);
2666         Object *obedit= CTX_data_edit_object(C);
2667         Image *ima= CTX_data_edit_image(C);
2668         EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
2669         EditFace *efa;
2670         MTFace *tface;
2671         int clear= RNA_boolean_get(op->ptr, "clear");
2672         
2673         for(efa= em->faces.first; efa; efa= efa->next) {
2674                 tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2675
2676                 if(uvedit_face_visible(scene, ima, efa, tface)) {
2677                         if(!clear) {
2678                                 if(uvedit_uv_selected(scene, efa, tface, 0)) tface->unwrap |= TF_PIN1;
2679                                 if(uvedit_uv_selected(scene, efa, tface, 1)) tface->unwrap |= TF_PIN2;
2680                                 if(uvedit_uv_selected(scene, efa, tface, 2)) tface->unwrap |= TF_PIN3;
2681                                 if(efa->v4)
2682                                         if(uvedit_uv_selected(scene, efa, tface, 3)) tface->unwrap |= TF_PIN4;
2683                         }
2684                         else {
2685                                 if(uvedit_uv_selected(scene, efa, tface, 0)) tface->unwrap &= ~TF_PIN1;
2686                                 if(uvedit_uv_selected(scene, efa, tface, 1)) tface->unwrap &= ~TF_PIN2;
2687                                 if(uvedit_uv_selected(scene, efa, tface, 2)) tface->unwrap &= ~TF_PIN3;
2688                                 if(efa->v4)
2689                                         if(uvedit_uv_selected(scene, efa, tface, 3)) tface->unwrap &= ~TF_PIN4;
2690                         }
2691                 }
2692         }
2693         
2694         WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
2695
2696         BKE_mesh_end_editmesh(obedit->data, em);
2697         return OPERATOR_FINISHED;
2698 }
2699
2700 void UV_OT_pin(wmOperatorType *ot)
2701 {
2702         /* identifiers */
2703         ot->name= "Pin";
2704         ot->description= "Set/clear selected UV vertices as anchored between multiple unwrap operations";
2705         ot->idname= "UV_OT_pin";
2706         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2707         
2708         /* api callbacks */
2709         ot->exec= pin_exec;
2710         ot->poll= ED_operator_uvedit;
2711
2712         /* properties */
2713         RNA_def_boolean(ot->srna, "clear", 0, "Clear", "Clear pinning for the selection instead of setting it.");
2714 }
2715
2716 /******************* select pinned operator ***************/
2717
2718 static int select_pinned_exec(bContext *C, wmOperator *op)
2719 {
2720         Scene *scene= CTX_data_scene(C);
2721         Object *obedit= CTX_data_edit_object(C);
2722         Image *ima= CTX_data_edit_image(C);
2723         EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
2724         EditFace *efa;
2725         MTFace *tface;
2726         
2727         for(efa= em->faces.first; efa; efa= efa->next) {
2728                 tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2729
2730                 if(uvedit_face_visible(scene, ima, efa, tface)) {
2731                         if(tface->unwrap & TF_PIN1) uvedit_uv_select(scene, efa, tface, 0);
2732                         if(tface->unwrap & TF_PIN2) uvedit_uv_select(scene, efa, tface, 1);
2733                         if(tface->unwrap & TF_PIN3) uvedit_uv_select(scene, efa, tface, 2);
2734                         if(efa->v4) {
2735                                 if(tface->unwrap & TF_PIN4) uvedit_uv_select(scene, efa, tface, 3);
2736                         }
2737                 }
2738         }
2739         
2740         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
2741
2742         BKE_mesh_end_editmesh(obedit->data, em);
2743         return OPERATOR_FINISHED;
2744 }
2745
2746 void UV_OT_select_pinned(wmOperatorType *ot)
2747 {
2748         /* identifiers */
2749         ot->name= "Selected Pinned";
2750         ot->description= "Select all pinned UV vertices";
2751         ot->idname= "UV_OT_select_pinned";
2752         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2753         
2754         /* api callbacks */
2755         ot->exec= select_pinned_exec;
2756         ot->poll= ED_operator_uvedit;
2757 }
2758
2759 /********************** hide operator *********************/
2760
2761 static int hide_exec(bContext *C, wmOperator *op)
2762 {
2763         SpaceImage *sima= CTX_wm_space_image(C);
2764         ToolSettings *ts= CTX_data_tool_settings(C);
2765         Object *obedit= CTX_data_edit_object(C);
2766         EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
2767         EditFace *efa;
2768         MTFace *tf;
2769         int swap= RNA_boolean_get(op->ptr, "unselected");
2770         int facemode= sima ? sima->flag & SI_SELACTFACE : 0;
2771
2772         if(ts->uv_flag & UV_SYNC_SELECTION) {
2773                 EM_hide_mesh(em, swap);
2774                 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
2775
2776                 BKE_mesh_end_editmesh(obedit->data, em);
2777                 return OPERATOR_FINISHED;
2778         }
2779         
2780         if(swap) {
2781                 for(efa= em->faces.first; efa; efa= efa->next) {
2782                         if(efa->f & SELECT) {
2783                                 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2784                                 if(facemode) {
2785                                         /* Pretend face mode */
2786                                         if((    (efa->v4==NULL && 
2787                                                         (       tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) ==                        (TF_SEL1|TF_SEL2|TF_SEL3) )                      ||
2788                                                         (       tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) ==        (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)       ) == 0) {
2789                                                 
2790                                                 if(em->selectmode == SCE_SELECT_FACE) {
2791                                                         efa->f &= ~SELECT;
2792                                                         /* must re-select after */
2793                                                         efa->e1->f &= ~SELECT;
2794                                                         efa->e2->f &= ~SELECT;
2795                                                         efa->e3->f &= ~SELECT;
2796                                                         if(efa->e4) efa->e4->f &= ~SELECT;
2797                                                 }
2798                                                 else
2799                                                         EM_select_face(efa, 0);
2800                                         }
2801                                         tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2802                                 }
2803                                 else if(em->selectmode == SCE_SELECT_FACE) {
2804                                         if((tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))==0) {
2805                                                 if(!efa->v4)
2806                                                         EM_select_face(efa, 0);
2807                                                 else if(!(tf->flag & TF_SEL4))
2808                                                         EM_select_face(efa, 0);
2809                                                 tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2810                                         }
2811                                 }
2812                                 else {
2813                                         /* EM_deselect_flush will deselect the face */
2814                                         if((tf->flag & TF_SEL1)==0)                             efa->v1->f &= ~SELECT;
2815                                         if((tf->flag & TF_SEL2)==0)                             efa->v2->f &= ~SELECT;
2816                                         if((tf->flag & TF_SEL3)==0)                             efa->v3->f &= ~SELECT;
2817                                         if((efa->v4) && (tf->flag & TF_SEL4)==0)        efa->v4->f &= ~SELECT;                  
2818
2819                                         tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2820                                 }
2821                         }
2822                 }
2823         }
2824         else {
2825                 for(efa= em->faces.first; efa; efa= efa->next) {
2826                         if(efa->f & SELECT) {
2827                                 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2828
2829                                 if(facemode) {
2830                                         if(     (efa->v4==NULL && 
2831                                                         (       tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) ==                        (TF_SEL1|TF_SEL2|TF_SEL3) )                      ||
2832                                                         (       tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) ==        (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)       ) {
2833                                                 
2834                                                 if(em->selectmode == SCE_SELECT_FACE) {
2835                                                         efa->f &= ~SELECT;
2836                                                         /* must re-select after */
2837                                                         efa->e1->f &= ~SELECT;
2838                                                         efa->e2->f &= ~SELECT;
2839                                                         efa->e3->f &= ~SELECT;
2840                                                         if(efa->e4) efa->e4->f &= ~SELECT;
2841                                                 }
2842                                                 else
2843                                                         EM_select_face(efa, 0);
2844                                         }
2845
2846                                         tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2847                                 }
2848                                 else if(em->selectmode == SCE_SELECT_FACE) {
2849                                         if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
2850                                                 EM_select_face(efa, 0);
2851                                         else if(efa->v4 && tf->flag & TF_SEL4)
2852                                                 EM_select_face(efa, 0);
2853
2854                                         tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2855                                 }
2856                                 else {
2857                                         /* EM_deselect_flush will deselect the face */
2858                                         if(tf->flag & TF_SEL1)                          efa->v1->f &= ~SELECT;
2859                                         if(tf->flag & TF_SEL2)                          efa->v2->f &= ~SELECT;
2860                                         if(tf->flag & TF_SEL3)                          efa->v3->f &= ~SELECT;
2861                                         if((efa->v4) && tf->flag & TF_SEL4)     efa->v4->f &= ~SELECT;
2862
2863                                         tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2864                                 }
2865                         }
2866                 }
2867         }
2868         
2869         /*deselects too many but ok for now*/
2870         if(em->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_VERTEX))
2871                 EM_deselect_flush(em);
2872         
2873         if(em->selectmode==SCE_SELECT_FACE) {
2874                 /* de-selected all edges from faces that were de-selected.
2875                  * now make sure all faces that are selected also have selected edges */
2876                 for(efa= em->faces.first; efa; efa= efa->next)
2877                         if(efa->f & SELECT)
2878                                 EM_select_face(efa, 1);
2879         }
2880         
2881         EM_validate_selections(em);
2882         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
2883
2884         BKE_mesh_end_editmesh(obedit->data, em);
2885         return OPERATOR_FINISHED;
2886 }
2887
2888 void UV_OT_hide(wmOperatorType *ot)
2889 {
2890         /* identifiers */
2891         ot->name= "Hide Selected";
2892         ot->description= "Hide (un)selected UV vertices";
2893         ot->idname= "UV_OT_hide";
2894         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2895         
2896         /* api callbacks */
2897         ot->exec= hide_exec;
2898         ot->poll= ED_operator_uvedit;
2899
2900         /* props */
2901         RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected.");
2902 }
2903
2904 /****************** reveal operator ******************/
2905
2906 static int reveal_exec(bContext *C, wmOperator *op)
2907 {
2908         SpaceImage *sima= CTX_wm_space_image(C);
2909         ToolSettings *ts= CTX_data_tool_settings(C);
2910         Object *obedit= CTX_data_edit_object(C);
2911         EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
2912         EditFace *efa;
2913         MTFace *tf;
2914         int facemode= sima ? sima->flag & SI_SELACTFACE : 0;
2915         int stickymode= sima ? (sima->sticky != SI_STICKY_DISABLE) : 1;
2916         
2917         /* call the mesh function if we are in mesh sync sel */
2918         if(ts->uv_flag & UV_SYNC_SELECTION) {
2919                 EM_reveal_mesh(em);
2920                 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
2921
2922                 BKE_mesh_end_editmesh(obedit->data, em);
2923                 return OPERATOR_FINISHED;
2924         }
2925         
2926         if(facemode) {
2927                 if(em->selectmode == SCE_SELECT_FACE) {
2928                         for(efa= em->faces.first; efa; efa= efa->next) {
2929                                 if(!(efa->h) && !(efa->f & SELECT)) {
2930                                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2931                                         EM_select_face(efa, 1);
2932                                         tf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4;
2933                                 }
2934                         }
2935                 }
2936                 else {
2937                         /* enable adjacent faces to have disconnected UV selections if sticky is disabled */
2938                         if(!stickymode) {
2939                                 for(efa= em->faces.first; efa; efa= efa->next) {
2940                                         if(!(efa->h) && !(efa->f & SELECT)) {
2941                                                 /* All verts must be unselected for the face to be selected in the UV view */
2942                                                 if((efa->v1->f&SELECT)==0 && (efa->v2->f&SELECT)==0 && (efa->v3->f&SELECT)==0 && (efa->v4==0 || (efa->v4->f&SELECT)==0)) {
2943                                                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2944
2945                                                         tf->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4;
2946                                                         /* Cant use EM_select_face here because it unselects the verts
2947                                                          * and we cant tell if the face was totally unselected or not */
2948                                                         /*EM_select_face(efa, 1);
2949                                                          * 
2950                                                          * See Loop with EM_select_face() below... */
2951                                                         efa->f |= SELECT;
2952                                                 }
2953                                         }
2954                                 }