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