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