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