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