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