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