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