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