200c6a173ea5f3e4b649f44e12d63740cd7dfaab
[blender.git] / source / blender / editors / mesh / editmesh_mods.c
1 /**
2  * $Id: 
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2004 Blender Foundation.
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 /*
31
32 editmesh_mods.c, UI level access, no geometry changes 
33
34 */
35
36 #include <stdlib.h>
37 #include <string.h>
38 #include <math.h>
39
40 #include "MEM_guardedalloc.h"
41
42 #include "MTC_matrixops.h"
43
44 #include "DNA_mesh_types.h"
45 #include "DNA_material_types.h"
46 #include "DNA_meshdata_types.h"
47 #include "DNA_modifier_types.h"
48 #include "DNA_object_types.h"
49 #include "DNA_texture_types.h"
50 #include "DNA_scene_types.h"
51 #include "DNA_screen_types.h"
52 #include "DNA_space_types.h"
53 #include "DNA_view3d_types.h"
54
55 #include "BLI_blenlib.h"
56 #include "BLI_arithb.h"
57 #include "BLI_editVert.h"
58 #include "BLI_rand.h"
59
60 #include "BKE_context.h"
61 #include "BKE_displist.h"
62 #include "BKE_depsgraph.h"
63 #include "BKE_DerivedMesh.h"
64 #include "BKE_customdata.h"
65 #include "BKE_global.h"
66 #include "BKE_mesh.h"
67 #include "BKE_material.h"
68 #include "BKE_texture.h"
69 #include "BKE_utildefines.h"
70
71 #include "IMB_imbuf_types.h"
72 #include "IMB_imbuf.h"
73
74 #include "RE_render_ext.h"  /* externtex */
75
76 #include "WM_api.h"
77 #include "WM_types.h"
78
79 #include "RNA_access.h"
80 #include "RNA_define.h"
81
82 #include "ED_mesh.h"
83 #include "ED_screen.h"
84 #include "ED_view3d.h"
85
86 #include "BIF_gl.h"
87 #include "BIF_glutil.h"
88
89 #include "mesh_intern.h"
90
91 #include "BLO_sys_types.h" // for intptr_t support
92
93 static void BIF_undo_push() {}
94 static void waitcursor() {}
95 static void error() {}
96 static int pupmenu() {return 0;}
97
98 /* ****************************** MIRROR **************** */
99
100 void EM_select_mirrored(Object *obedit, EditMesh *em)
101 {
102         if(em->selectmode & SCE_SELECT_VERTEX) {
103                 EditVert *eve, *v1;
104                 
105                 for(eve= em->verts.first; eve; eve= eve->next) {
106                         if(eve->f & SELECT) {
107                                 v1= editmesh_get_x_mirror_vert(obedit, em, eve->co);
108                                 if(v1) {
109                                         eve->f &= ~SELECT;
110                                         v1->f |= SELECT;
111                                 }
112                         }
113                 }
114         }
115 }
116
117 void EM_automerge(int update) 
118 {
119 // XXX  int len;
120         
121 //      if ((scene->automerge) &&
122 //              (obedit && obedit->type==OB_MESH) &&
123 //              (((Mesh*)obedit->data)->mr==NULL)
124 //        ) {
125 //              len = removedoublesflag(1, 1, scene->toolsettings->doublimit);
126 //              if (len) {
127 //                      em->totvert -= len; /* saves doing a countall */
128 //                      if (update) {
129 //                              DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
130 //                      }
131 //              }
132 //      }
133 }
134
135 /* ****************************** SELECTION ROUTINES **************** */
136
137 unsigned int em_solidoffs=0, em_wireoffs=0, em_vertoffs=0;      /* set in drawobject.c ... for colorindices */
138
139 /* facilities for border select and circle select */
140 static char *selbuf= NULL;
141
142 /* opengl doesn't support concave... */
143 static void draw_triangulated(short mcords[][2], short tot)
144 {
145         ListBase lb={NULL, NULL};
146         DispList *dl;
147         float *fp;
148         int a;
149         
150         /* make displist */
151         dl= MEM_callocN(sizeof(DispList), "poly disp");
152         dl->type= DL_POLY;
153         dl->parts= 1;
154         dl->nr= tot;
155         dl->verts= fp=  MEM_callocN(tot*3*sizeof(float), "poly verts");
156         BLI_addtail(&lb, dl);
157         
158         for(a=0; a<tot; a++, fp+=3) {
159                 fp[0]= (float)mcords[a][0];
160                 fp[1]= (float)mcords[a][1];
161         }
162         
163         /* do the fill */
164         filldisplist(&lb, &lb);
165
166         /* do the draw */
167         dl= lb.first;   /* filldisplist adds in head of list */
168         if(dl->type==DL_INDEX3) {
169                 int *index;
170                 
171                 a= dl->parts;
172                 fp= dl->verts;
173                 index= dl->index;
174                 glBegin(GL_TRIANGLES);
175                 while(a--) {
176                         glVertex3fv(fp+3*index[0]);
177                         glVertex3fv(fp+3*index[1]);
178                         glVertex3fv(fp+3*index[2]);
179                         index+= 3;
180                 }
181                 glEnd();
182         }
183         
184         freedisplist(&lb);
185 }
186
187
188 /* reads rect, and builds selection array for quick lookup */
189 /* returns if all is OK */
190 int EM_init_backbuf_border(ViewContext *vc, short xmin, short ymin, short xmax, short ymax)
191 {
192         struct ImBuf *buf;
193         unsigned int *dr;
194         int a;
195         
196         if(vc->obedit==NULL || vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
197         
198         buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
199         if(buf==NULL) return 0;
200         if(em_vertoffs==0) return 0;
201
202         dr = buf->rect;
203         
204         /* build selection lookup */
205         selbuf= MEM_callocN(em_vertoffs+1, "selbuf");
206         
207         a= (xmax-xmin+1)*(ymax-ymin+1);
208         while(a--) {
209                 if(*dr>0 && *dr<=em_vertoffs) 
210                         selbuf[*dr]= 1;
211                 dr++;
212         }
213         IMB_freeImBuf(buf);
214         return 1;
215 }
216
217 int EM_check_backbuf(unsigned int index)
218 {
219         if(selbuf==NULL) return 1;
220         if(index>0 && index<=em_vertoffs)
221                 return selbuf[index];
222         return 0;
223 }
224
225 void EM_free_backbuf(void)
226 {
227         if(selbuf) MEM_freeN(selbuf);
228         selbuf= NULL;
229 }
230
231 /* mcords is a polygon mask
232    - grab backbuffer,
233    - draw with black in backbuffer, 
234    - grab again and compare
235    returns 'OK' 
236 */
237 int EM_mask_init_backbuf_border(ViewContext *vc, short mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax)
238 {
239         unsigned int *dr, *drm;
240         struct ImBuf *buf, *bufmask;
241         int a;
242         
243         /* method in use for face selecting too */
244         if(vc->obedit==NULL) {
245                 if(FACESEL_PAINT_TEST);
246                 else return 0;
247         }
248         else if(vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
249
250         if(em_vertoffs==0) return 0;
251         
252         buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
253         if(buf==NULL) return 0;
254
255         dr = buf->rect;
256
257         /* draw the mask */
258 #ifdef __APPLE__
259         glDrawBuffer(GL_AUX0);
260 #endif
261         glDisable(GL_DEPTH_TEST);
262         
263 // XXX  persp(PERSP_WIN);
264         glColor3ub(0, 0, 0);
265         
266         /* yah, opengl doesn't do concave... tsk! */
267         draw_triangulated(mcords, tot); 
268         
269         glBegin(GL_LINE_LOOP);  /* for zero sized masks, lines */
270         for(a=0; a<tot; a++) glVertex2s(mcords[a][0], mcords[a][1]);
271         glEnd();
272         
273 // XXX  persp(PERSP_VIEW);
274         glFinish();     /* to be sure readpixels sees mask */
275         
276         glDrawBuffer(GL_BACK);
277         
278         /* grab mask */
279         bufmask= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
280         drm = bufmask->rect;
281         if(bufmask==NULL) return 0; /* only when mem alloc fails, go crash somewhere else! */
282         
283         /* build selection lookup */
284         selbuf= MEM_callocN(em_vertoffs+1, "selbuf");
285         
286         a= (xmax-xmin+1)*(ymax-ymin+1);
287         while(a--) {
288                 if(*dr>0 && *dr<=em_vertoffs && *drm==0) selbuf[*dr]= 1;
289                 dr++; drm++;
290         }
291         IMB_freeImBuf(buf);
292         IMB_freeImBuf(bufmask);
293         return 1;
294         
295 }
296
297 /* circle shaped sample area */
298 int EM_init_backbuf_circle(ViewContext *vc, short xs, short ys, short rads)
299 {
300         struct ImBuf *buf;
301         unsigned int *dr;
302         short xmin, ymin, xmax, ymax, xc, yc;
303         int radsq;
304         
305         /* method in use for face selecting too */
306         if(vc->obedit==NULL) {
307                 if(FACESEL_PAINT_TEST);
308                 else return 0;
309         }
310         else if(vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
311         if(em_vertoffs==0) return 0;
312         
313         xmin= xs-rads; xmax= xs+rads;
314         ymin= ys-rads; ymax= ys+rads;
315         buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
316         if(buf==NULL) return 0;
317
318         dr = buf->rect;
319         
320         /* build selection lookup */
321         selbuf= MEM_callocN(em_vertoffs+1, "selbuf");
322         radsq= rads*rads;
323         for(yc= -rads; yc<=rads; yc++) {
324                 for(xc= -rads; xc<=rads; xc++, dr++) {
325                         if(xc*xc + yc*yc < radsq) {
326                                 if(*dr>0 && *dr<=em_vertoffs) selbuf[*dr]= 1;
327                         }
328                 }
329         }
330
331         IMB_freeImBuf(buf);
332         return 1;
333         
334 }
335
336 static void findnearestvert__doClosest(void *userData, EditVert *eve, int x, int y, int index)
337 {
338         struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; EditVert *closest; } *data = userData;
339
340         if (data->pass==0) {
341                 if (index<=data->lastIndex)
342                         return;
343         } else {
344                 if (index>data->lastIndex)
345                         return;
346         }
347
348         if (data->dist>3) {
349                 int temp = abs(data->mval[0] - x) + abs(data->mval[1]- y);
350                 if ((eve->f&1) == data->select) {
351                         if (data->strict == 1)
352                                 return;
353                         else
354                                 temp += 5;
355                 }
356
357                 if (temp<data->dist) {
358                         data->dist = temp;
359                         data->closest = eve;
360                         data->closestIndex = index;
361                 }
362         }
363 }
364
365
366
367
368 static unsigned int findnearestvert__backbufIndextest(void *handle, unsigned int index)
369 {
370         EditMesh *em= (EditMesh *)handle;
371         EditVert *eve = BLI_findlink(&em->verts, index-1);
372
373         if(eve && (eve->f & SELECT)) return 0;
374         return 1; 
375 }
376 /**
377  * findnearestvert
378  * 
379  * dist (in/out): minimal distance to the nearest and at the end, actual distance
380  * sel: selection bias
381  *              if SELECT, selected vertice are given a 5 pixel bias to make them farter than unselect verts
382  *              if 0, unselected vertice are given the bias
383  * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased 
384  */
385 EditVert *findnearestvert(ViewContext *vc, int *dist, short sel, short strict)
386 {
387         if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)){
388                 int distance;
389                 unsigned int index;
390                 EditVert *eve;
391                 
392                 if(strict) index = view3d_sample_backbuf_rect(vc, vc->mval, 50, em_wireoffs, 0xFFFFFF, &distance, strict, vc->em, findnearestvert__backbufIndextest); 
393                 else index = view3d_sample_backbuf_rect(vc, vc->mval, 50, em_wireoffs, 0xFFFFFF, &distance, 0, NULL, NULL); 
394                 
395                 eve = BLI_findlink(&vc->em->verts, index-1);
396                 
397                 if(eve && distance < *dist) {
398                         *dist = distance;
399                         return eve;
400                 } else {
401                         return NULL;
402                 }
403                         
404         }
405         else {
406                 struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; EditVert *closest; } data;
407                 static int lastSelectedIndex=0;
408                 static EditVert *lastSelected=NULL;
409
410                 if (lastSelected && BLI_findlink(&vc->em->verts, lastSelectedIndex)!=lastSelected) {
411                         lastSelectedIndex = 0;
412                         lastSelected = NULL;
413                 }
414
415                 data.lastIndex = lastSelectedIndex;
416                 data.mval[0] = vc->mval[0];
417                 data.mval[1] = vc->mval[1];
418                 data.select = sel;
419                 data.dist = *dist;
420                 data.strict = strict;
421                 data.closest = NULL;
422                 data.closestIndex = 0;
423
424                 data.pass = 0;
425                 mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, 1);
426
427                 if (data.dist>3) {
428                         data.pass = 1;
429                         mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, 1);
430                 }
431
432                 *dist = data.dist;
433                 lastSelected = data.closest;
434                 lastSelectedIndex = data.closestIndex;
435
436                 return data.closest;
437         }
438 }
439
440 /* returns labda for closest distance v1 to line-piece v2-v3 */
441 static float labda_PdistVL2Dfl( float *v1, float *v2, float *v3) 
442 {
443         float rc[2], len;
444         
445         rc[0]= v3[0]-v2[0];
446         rc[1]= v3[1]-v2[1];
447         len= rc[0]*rc[0]+ rc[1]*rc[1];
448         if(len==0.0f)
449                 return 0.0f;
450         
451         return ( rc[0]*(v1[0]-v2[0]) + rc[1]*(v1[1]-v2[1]) )/len;
452 }
453
454 /* note; uses v3d, so needs active 3d window */
455 static void findnearestedge__doClosest(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index)
456 {
457         struct { ViewContext vc; float mval[2]; int dist; EditEdge *closest; } *data = userData;
458         float v1[2], v2[2];
459         int distance;
460                 
461         v1[0] = x0;
462         v1[1] = y0;
463         v2[0] = x1;
464         v2[1] = y1;
465                 
466         distance= PdistVL2Dfl(data->mval, v1, v2);
467                 
468         if(eed->f & SELECT) distance+=5;
469         if(distance < data->dist) {
470                 if(data->vc.rv3d->rflag & RV3D_CLIPPING) {
471                         float labda= labda_PdistVL2Dfl(data->mval, v1, v2);
472                         float vec[3];
473
474                         vec[0]= eed->v1->co[0] + labda*(eed->v2->co[0] - eed->v1->co[0]);
475                         vec[1]= eed->v1->co[1] + labda*(eed->v2->co[1] - eed->v1->co[1]);
476                         vec[2]= eed->v1->co[2] + labda*(eed->v2->co[2] - eed->v1->co[2]);
477                         Mat4MulVecfl(data->vc.obedit->obmat, vec);
478
479                         if(view3d_test_clipping(data->vc.rv3d, vec)==0) {
480                                 data->dist = distance;
481                                 data->closest = eed;
482                         }
483                 }
484                 else {
485                         data->dist = distance;
486                         data->closest = eed;
487                 }
488         }
489 }
490 EditEdge *findnearestedge(ViewContext *vc, int *dist)
491 {
492
493         if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
494                 int distance;
495                 unsigned int index = view3d_sample_backbuf_rect(vc, vc->mval, 50, em_solidoffs, em_wireoffs, &distance,0, NULL, NULL);
496                 EditEdge *eed = BLI_findlink(&vc->em->edges, index-1);
497
498                 if (eed && distance<*dist) {
499                         *dist = distance;
500                         return eed;
501                 } else {
502                         return NULL;
503                 }
504         }
505         else {
506                 struct { ViewContext vc; float mval[2]; int dist; EditEdge *closest; } data;
507
508                 data.vc= *vc;
509                 data.mval[0] = vc->mval[0];
510                 data.mval[1] = vc->mval[1];
511                 data.dist = *dist;
512                 data.closest = NULL;
513
514                 mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, 2);
515
516                 *dist = data.dist;
517                 return data.closest;
518         }
519 }
520
521 static void findnearestface__getDistance(void *userData, EditFace *efa, int x, int y, int index)
522 {
523         struct { short mval[2]; int dist; EditFace *toFace; } *data = userData;
524
525         if (efa==data->toFace) {
526                 int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
527
528                 if (temp<data->dist)
529                         data->dist = temp;
530         }
531 }
532 static void findnearestface__doClosest(void *userData, EditFace *efa, int x, int y, int index)
533 {
534         struct { short mval[2], pass; int dist, lastIndex, closestIndex; EditFace *closest; } *data = userData;
535
536         if (data->pass==0) {
537                 if (index<=data->lastIndex)
538                         return;
539         } else {
540                 if (index>data->lastIndex)
541                         return;
542         }
543
544         if (data->dist>3) {
545                 int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
546
547                 if (temp<data->dist) {
548                         data->dist = temp;
549                         data->closest = efa;
550                         data->closestIndex = index;
551                 }
552         }
553 }
554 static EditFace *findnearestface(ViewContext *vc, int *dist)
555 {
556
557         if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
558                 unsigned int index = view3d_sample_backbuf(vc, vc->mval[0], vc->mval[1]);
559                 EditFace *efa = BLI_findlink(&vc->em->faces, index-1);
560
561                 if (efa) {
562                         struct { short mval[2]; int dist; EditFace *toFace; } data;
563
564                         data.mval[0] = vc->mval[0];
565                         data.mval[1] = vc->mval[1];
566                         data.dist = 0x7FFF;             /* largest short */
567                         data.toFace = efa;
568
569                         mesh_foreachScreenFace(vc, findnearestface__getDistance, &data);
570
571                         if(vc->em->selectmode == SCE_SELECT_FACE || data.dist<*dist) {  /* only faces, no dist check */
572                                 *dist= data.dist;
573                                 return efa;
574                         }
575                 }
576                 
577                 return NULL;
578         }
579         else {
580                 struct { short mval[2], pass; int dist, lastIndex, closestIndex; EditFace *closest; } data;
581                 static int lastSelectedIndex=0;
582                 static EditFace *lastSelected=NULL;
583
584                 if (lastSelected && BLI_findlink(&vc->em->faces, lastSelectedIndex)!=lastSelected) {
585                         lastSelectedIndex = 0;
586                         lastSelected = NULL;
587                 }
588
589                 data.lastIndex = lastSelectedIndex;
590                 data.mval[0] = vc->mval[0];
591                 data.mval[1] = vc->mval[1];
592                 data.dist = *dist;
593                 data.closest = NULL;
594                 data.closestIndex = 0;
595
596                 data.pass = 0;
597                 mesh_foreachScreenFace(vc, findnearestface__doClosest, &data);
598
599                 if (data.dist>3) {
600                         data.pass = 1;
601                         mesh_foreachScreenFace(vc, findnearestface__doClosest, &data);
602                 }
603
604                 *dist = data.dist;
605                 lastSelected = data.closest;
606                 lastSelectedIndex = data.closestIndex;
607
608                 return data.closest;
609         }
610 }
611
612 /* best distance based on screen coords. 
613    use em->selectmode to define how to use 
614    selected vertices and edges get disadvantage
615    return 1 if found one
616 */
617 static int unified_findnearest(ViewContext *vc, EditVert **eve, EditEdge **eed, EditFace **efa) 
618 {
619         EditMesh *em= vc->em;
620         int dist= 75;
621         
622         *eve= NULL;
623         *eed= NULL;
624         *efa= NULL;
625         
626         /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
627         view3d_validate_backbuf(vc);
628         
629         if(em->selectmode & SCE_SELECT_VERTEX)
630                 *eve= findnearestvert(vc, &dist, SELECT, 0);
631         if(em->selectmode & SCE_SELECT_FACE)
632                 *efa= findnearestface(vc, &dist);
633
634         dist-= 20;      /* since edges select lines, we give dots advantage of 20 pix */
635         if(em->selectmode & SCE_SELECT_EDGE)
636                 *eed= findnearestedge(vc, &dist);
637
638         /* return only one of 3 pointers, for frontbuffer redraws */
639         if(*eed) {
640                 *efa= NULL; *eve= NULL;
641         }
642         else if(*efa) {
643                 *eve= NULL;
644         }
645         
646         return (*eve || *eed || *efa);
647 }
648
649 /* this as a way to compare the ares, perim  of 2 faces thay will scale to different sizes
650  *0.5 so smaller faces arnt ALWAYS selected with a thresh of 1.0 */
651 #define SCALE_CMP(a,b) ((a+a*thresh >= b) && (a-(a*thresh*0.5) <= b))
652
653 /* ****************  GROUP SELECTS ************** */
654 /* selects new faces/edges/verts based on the
655  existing selection
656
657 FACES GROUP
658  mode 1: same material
659  mode 2: same image
660  mode 3: same area
661  mode 4: same perimeter
662  mode 5: same normal
663  mode 6: same co-planer
664 */
665 int facegroup_select(EditMesh *em, short mode)
666 {
667         EditFace *efa, *base_efa=NULL;
668         unsigned int selcount=0; /*count how many new faces we select*/
669         
670         /*deselcount, count how many deselected faces are left, so we can bail out early
671         also means that if there are no deselected faces, we can avoid a lot of looping */
672         unsigned int deselcount=0; 
673         
674         short ok=0;
675         float thresh=0; // XXX scene->toolsettings->select_thresh;
676         
677         for(efa= em->faces.first; efa; efa= efa->next) {
678                 if (!efa->h) {
679                         if (efa->f & SELECT) {
680                                 efa->f1=1;
681                                 ok=1;
682                         } else {
683                                 efa->f1=0;
684                                 deselcount++; /* a deselected face we may select later */
685                         }
686                 }
687         }
688         
689         if (!ok || !deselcount) /* no data selected OR no more data to select */
690                 return 0;
691         
692         /*if mode is 3 then record face areas, 4 record perimeter */
693         if (mode==3) {
694                 for(efa= em->faces.first; efa; efa= efa->next) {
695                         efa->tmp.fp= EM_face_area(efa);
696                 }
697         } else if (mode==4) {
698                 for(efa= em->faces.first; efa; efa= efa->next) {
699                         efa->tmp.fp= EM_face_perimeter(efa);
700                 }
701         }
702         
703         for(base_efa= em->faces.first; base_efa; base_efa= base_efa->next) {
704                 if (base_efa->f1) { /* This was one of the faces originaly selected */
705                         if (mode==1) { /* same material */
706                                 for(efa= em->faces.first; efa; efa= efa->next) {
707                                         if (
708                                                 !(efa->f & SELECT) &&
709                                                 !efa->h &&
710                                                 base_efa->mat_nr == efa->mat_nr
711                                         ) {
712                                                 EM_select_face(efa, 1);
713                                                 selcount++;
714                                                 deselcount--;
715                                                 if (!deselcount) /*have we selected all posible faces?, if so return*/
716                                                         return selcount;
717                                         }
718                                 }
719                         } else if (mode==2) { /* same image */
720                                 MTFace *tf, *base_tf;
721
722                                 base_tf = (MTFace*)CustomData_em_get(&em->fdata, base_efa->data,
723                                                                      CD_MTFACE);
724
725                                 if(!base_tf)
726                                         return selcount;
727
728                                 for(efa= em->faces.first; efa; efa= efa->next) {
729                                         if (!(efa->f & SELECT) && !efa->h) {
730                                                 tf = (MTFace*)CustomData_em_get(&em->fdata, efa->data,
731                                                                                 CD_MTFACE);
732
733                                                 if(base_tf->tpage == tf->tpage) {
734                                                         EM_select_face(efa, 1);
735                                                         selcount++;
736                                                         deselcount--;
737                                                         if (!deselcount) /*have we selected all posible faces?, if so return*/
738                                                                 return selcount;
739                                                 }
740                                         }
741                                 }
742                         } else if (mode==3 || mode==4) { /* same area OR same perimeter, both use the same temp var */
743                                 for(efa= em->faces.first; efa; efa= efa->next) {
744                                         if (
745                                                 (!(efa->f & SELECT) && !efa->h) &&
746                                                 SCALE_CMP(base_efa->tmp.fp, efa->tmp.fp)
747                                         ) {
748                                                 EM_select_face(efa, 1);
749                                                 selcount++;
750                                                 deselcount--;
751                                                 if (!deselcount) /*have we selected all posible faces?, if so return*/
752                                                         return selcount;
753                                         }
754                                 }
755                         } else if (mode==5) { /* same normal */
756                                 float angle;
757                                 for(efa= em->faces.first; efa; efa= efa->next) {
758                                         if (!(efa->f & SELECT) && !efa->h) {
759                                                 angle= VecAngle2(base_efa->n, efa->n);
760                                                 if (angle/180.0<=thresh) {
761                                                         EM_select_face(efa, 1);
762                                                         selcount++;
763                                                         deselcount--;
764                                                         if (!deselcount) /*have we selected all posible faces?, if so return*/
765                                                                 return selcount;
766                                                 }
767                                         }
768                                 }
769                         } else if (mode==6) { /* same planer */
770                                 float angle, base_dot, dot;
771                                 base_dot= Inpf(base_efa->cent, base_efa->n);
772                                 for(efa= em->faces.first; efa; efa= efa->next) {
773                                         if (!(efa->f & SELECT) && !efa->h) {
774                                                 angle= VecAngle2(base_efa->n, efa->n);
775                                                 if (angle/180.0<=thresh) {
776                                                         dot=Inpf(efa->cent, base_efa->n);
777                                                         if (fabs(base_dot-dot) <= thresh) {
778                                                                 EM_select_face(efa, 1);
779                                                                 selcount++;
780                                                                 deselcount--;
781                                                                 if (!deselcount) /*have we selected all posible faces?, if so return*/
782                                                                         return selcount;
783                                                         }
784                                                 }
785                                         }
786                                 }
787                         }
788                 }
789         } /* end base_efa loop */
790         return selcount;
791 }
792
793
794 /*
795 EDGE GROUP
796  mode 1: same length
797  mode 2: same direction
798  mode 3: same number of face users
799  mode 4: similar face angles.
800  mode 5: similar crease
801  mode 6: similar seam
802  mode 7: similar sharp
803 */
804
805 /* this function is only used by edgegroup_select's edge angle */
806
807
808
809 static int edgegroup_select__internal(EditMesh *em, short mode)
810 {
811         EditEdge *eed, *base_eed=NULL;
812         unsigned int selcount=0; /* count how many new edges we select*/
813         
814         /*count how many visible selected edges there are,
815         so we can return when there are none left */
816         unsigned int deselcount=0;
817         
818         short ok=0;
819         float thresh=0; // XXX scene->toolsettings->select_thresh;
820         
821         for(eed= em->edges.first; eed; eed= eed->next) {
822                 if (!eed->h) {
823                         if (eed->f & SELECT) {
824                                 eed->f1=1;
825                                 ok=1;
826                         } else {
827                                 eed->f1=0;
828                                 deselcount++;
829                         }
830                         /* set all eed->tmp.l to 0 we use it later.
831                         for counting face users*/
832                         eed->tmp.l=0;
833                         eed->f2=0; /* only for mode 4, edge animations */
834                 }
835         }
836         
837         if (!ok || !deselcount) /* no data selected OR no more data to select*/
838                 return 0;
839         
840         if (mode==1) { /*store length*/
841                 for(eed= em->edges.first; eed; eed= eed->next) {
842                         if (!eed->h) /* dont calc data for hidden edges*/
843                                 eed->tmp.fp= VecLenf(eed->v1->co, eed->v2->co);
844                 }
845         } else if (mode==3) { /*store face users*/
846                 EditFace *efa;
847                 /* cound how many faces each edge uses use tmp->l */
848                 for(efa= em->faces.first; efa; efa= efa->next) {
849                         efa->e1->tmp.l++;
850                         efa->e2->tmp.l++;
851                         efa->e3->tmp.l++;
852                         if (efa->e4) efa->e4->tmp.l++;
853                 }
854         } else if (mode==4) { /*store edge angles */
855                 EditFace *efa;
856                 int j;
857                 /* cound how many faces each edge uses use tmp.l */
858                 for(efa= em->faces.first; efa; efa= efa->next) {
859                         /* here we use the edges temp data to assign a face
860                         if a face has alredy been assigned (eed->f2==1)
861                         we calculate the angle between the current face and
862                         the edges previously found face.
863                         store the angle in eed->tmp.fp (loosing the face eed->tmp.f)
864                         but tagging eed->f2==2, so we know not to look at it again.
865                         This only works for edges that connect to 2 faces. but its good enough
866                         */
867                         
868                         /* se we can loop through face edges*/
869                         j=0;
870                         eed= efa->e1;
871                         while (j<4) {
872                                 if (j==1) eed= efa->e2;
873                                 else if (j==2) eed= efa->e3;
874                                 else if (j==3) {
875                                         eed= efa->e4;
876                                         if (!eed)
877                                                 break;
878                                 } /* done looping */
879                                 
880                                 if (!eed->h) { /* dont calc data for hidden edges*/
881                                         if (eed->f2==2)
882                                                 break;
883                                         else if (eed->f2==0) /* first access, assign the face */
884                                                 eed->tmp.f= efa;
885                                         else if (eed->f2==1) /* second, we assign the angle*/
886                                                 eed->tmp.fp= VecAngle2(eed->tmp.f->n, efa->n)/180;
887                                         eed->f2++; /* f2==0 no face assigned. f2==1 one face found. f2==2 angle calculated.*/
888                                 }
889                                 j++;
890                         }
891                 }
892         }
893         
894         for(base_eed= em->edges.first; base_eed; base_eed= base_eed->next) {
895                 if (base_eed->f1) {
896                         if (mode==1) { /* same length */
897                                 for(eed= em->edges.first; eed; eed= eed->next) {
898                                         if (
899                                                 !(eed->f & SELECT) &&
900                                                 !eed->h &&
901                                                 SCALE_CMP(base_eed->tmp.fp, eed->tmp.fp)
902                                         ) {
903                                                 EM_select_edge(eed, 1);
904                                                 selcount++;
905                                                 deselcount--;
906                                                 if (!deselcount) /*have we selected all posible faces?, if so return*/
907                                                         return selcount;
908                                         }
909                                 }
910                         } else if (mode==2) { /* same direction */
911                                 float base_dir[3], dir[3], angle;
912                                 VecSubf(base_dir, base_eed->v1->co, base_eed->v2->co);
913                                 for(eed= em->edges.first; eed; eed= eed->next) {
914                                         if (!(eed->f & SELECT) && !eed->h) {
915                                                 VecSubf(dir, eed->v1->co, eed->v2->co);
916                                                 angle= VecAngle2(base_dir, dir);
917                                                 
918                                                 if (angle>90) /* use the smallest angle between the edges */
919                                                         angle= fabs(angle-180.0f);
920                                                 
921                                                 if (angle/90.0<=thresh) {
922                                                         EM_select_edge(eed, 1);
923                                                         selcount++;
924                                                         deselcount--;
925                                                         if (!deselcount) /*have we selected all posible faces?, if so return*/
926                                                                 return selcount;
927                                                 }
928                                         }
929                                 }
930                         } else if (mode==3) { /* face users */                          
931                                 for(eed= em->edges.first; eed; eed= eed->next) {
932                                         if (
933                                                 !(eed->f & SELECT) &&
934                                                 !eed->h &&
935                                                 base_eed->tmp.l==eed->tmp.l
936                                         ) {
937                                                 EM_select_edge(eed, 1);
938                                                 selcount++;
939                                                 deselcount--;
940                                                 if (!deselcount) /*have we selected all posible faces?, if so return*/
941                                                         return selcount;
942                                         }
943                                 }
944                         } else if (mode==4 && base_eed->f2==2) { /* edge angles, f2==2 means the edge has an angle. */                          
945                                 for(eed= em->edges.first; eed; eed= eed->next) {
946                                         if (
947                                                 !(eed->f & SELECT) &&
948                                                 !eed->h &&
949                                                 eed->f2==2 &&
950                                                 (fabs(base_eed->tmp.fp-eed->tmp.fp)<=thresh)
951                                         ) {
952                                                 EM_select_edge(eed, 1);
953                                                 selcount++;
954                                                 deselcount--;
955                                                 if (!deselcount) /*have we selected all posible faces?, if so return*/
956                                                         return selcount;
957                                         }
958                                 }
959                         } else if (mode==5) { /* edge crease */
960                                 for(eed= em->edges.first; eed; eed= eed->next) {
961                                         if (
962                                                 !(eed->f & SELECT) &&
963                                                 !eed->h &&
964                                                 (fabs(base_eed->crease-eed->crease) <= thresh)
965                                         ) {
966                                                 EM_select_edge(eed, 1);
967                                                 selcount++;
968                                                 deselcount--;
969                                                 if (!deselcount) /*have we selected all posible faces?, if so return*/
970                                                         return selcount;
971                                         }
972                                 }
973                         } else if (mode==6) { /* edge seam */
974                                 for(eed= em->edges.first; eed; eed= eed->next) {
975                                         if (
976                                                 !(eed->f & SELECT) &&
977                                                 !eed->h &&
978                                                 (eed->seam == base_eed->seam)
979                                         ) {
980                                                 EM_select_edge(eed, 1);
981                                                 selcount++;
982                                                 deselcount--;
983                                                 if (!deselcount) /*have we selected all posible faces?, if so return*/
984                                                         return selcount;
985                                         }
986                                 }
987                         } else if (mode==7) { /* edge sharp */
988                                 for(eed= em->edges.first; eed; eed= eed->next) {
989                                         if (
990                                                 !(eed->f & SELECT) &&
991                                                 !eed->h &&
992                                                 (eed->sharp == base_eed->sharp)
993                                         ) {
994                                                 EM_select_edge(eed, 1);
995                                                 selcount++;
996                                                 deselcount--;
997                                                 if (!deselcount) /*have we selected all posible faces?, if so return*/
998                                                         return selcount;
999                                         }
1000                                 }
1001                         }
1002                 }
1003         }       
1004         return selcount;
1005 }
1006 /* wrap the above function but do selection flushing edge to face */
1007 int edgegroup_select(EditMesh *em, short mode)
1008 {
1009         int selcount = edgegroup_select__internal(em, mode);
1010         
1011         if (selcount) {
1012                 /* Could run a generic flush function,
1013                  * but the problem is only that all edges of a face
1014                  * can be selected without the face becoming selected */
1015                 EditFace *efa;
1016                 for(efa= em->faces.first; efa; efa= efa->next) {
1017                         if (efa->v4) {
1018                                 if (efa->e1->f&SELECT && efa->e2->f&SELECT && efa->e3->f&SELECT && efa->e4->f&SELECT)
1019                                         efa->f |= SELECT;
1020                         }  else {
1021                                 if (efa->e1->f&SELECT && efa->e2->f&SELECT && efa->e3->f&SELECT)
1022                                         efa->f |= SELECT;
1023                         }
1024                 }
1025         }
1026         return selcount;
1027 }
1028
1029
1030
1031 /*
1032 VERT GROUP
1033  mode 1: same normal
1034  mode 2: same number of face users
1035  mode 3: same vertex groups
1036 */
1037 int vertgroup_select(EditMesh *em, short mode)
1038 {
1039         EditVert *eve, *base_eve=NULL;
1040         
1041         unsigned int selcount=0; /* count how many new edges we select*/
1042         
1043         /*count how many visible selected edges there are,
1044         so we can return when there are none left */
1045         unsigned int deselcount=0;
1046         
1047         short ok=0;
1048         float thresh=0; // XXX scene->toolsettings->select_thresh;
1049         
1050         for(eve= em->verts.first; eve; eve= eve->next) {
1051                 if (!eve->h) {
1052                         if (eve->f & SELECT) {
1053                                 eve->f1=1;
1054                                 ok=1;
1055                         } else {
1056                                 eve->f1=0;
1057                                 deselcount++;
1058                         }
1059                         /* set all eve->tmp.l to 0 we use them later.*/
1060                         eve->tmp.l=0;
1061                 }
1062                 
1063         }
1064         
1065         if (!ok || !deselcount) /* no data selected OR no more data to select*/
1066                 return 0;
1067         
1068         
1069         if (mode==2) { /* store face users */
1070                 EditFace *efa;
1071                 
1072                 /* count how many faces each edge uses use tmp->l */
1073                 for(efa= em->faces.first; efa; efa= efa->next) {
1074                         efa->v1->tmp.l++;
1075                         efa->v2->tmp.l++;
1076                         efa->v3->tmp.l++;
1077                         if (efa->v4) efa->v4->tmp.l++;
1078                 }
1079         }
1080         
1081         
1082         for(base_eve= em->verts.first; base_eve; base_eve= base_eve->next) {
1083                 if (base_eve->f1) {
1084                                 
1085                         if (mode==1) { /* same normal */
1086                                 float angle;
1087                                 for(eve= em->verts.first; eve; eve= eve->next) {
1088                                         if (!(eve->f & SELECT) && !eve->h) {
1089                                                 angle= VecAngle2(base_eve->no, eve->no);
1090                                                 if (angle/180.0<=thresh) {
1091                                                         eve->f |= SELECT;
1092                                                         selcount++;
1093                                                         deselcount--;
1094                                                         if (!deselcount) /*have we selected all posible faces?, if so return*/
1095                                                                 return selcount;
1096                                                 }
1097                                         }
1098                                 }
1099                         } else if (mode==2) { /* face users */
1100                                 for(eve= em->verts.first; eve; eve= eve->next) {
1101                                         if (
1102                                                 !(eve->f & SELECT) &&
1103                                                 !eve->h &&
1104                                                 base_eve->tmp.l==eve->tmp.l
1105                                         ) {
1106                                                 eve->f |= SELECT;
1107                                                 selcount++;
1108                                                 deselcount--;
1109                                                 if (!deselcount) /*have we selected all posible faces?, if so return*/
1110                                                         return selcount;
1111                                         }
1112                                 }
1113                         } else if (mode==3) { /* vertex groups */
1114                                 MDeformVert *dvert, *base_dvert;
1115                                 short i, j; /* weight index */
1116
1117                                 base_dvert= CustomData_em_get(&em->vdata, base_eve->data,
1118                                         CD_MDEFORMVERT);
1119
1120                                 if (!base_dvert || base_dvert->totweight == 0)
1121                                         return selcount;
1122                                 
1123                                 for(eve= em->verts.first; eve; eve= eve->next) {
1124                                         dvert= CustomData_em_get(&em->vdata, eve->data,
1125                                                 CD_MDEFORMVERT);
1126
1127                                         if (dvert && !(eve->f & SELECT) && !eve->h && dvert->totweight) {
1128                                                 /* do the extra check for selection in the following if, so were not
1129                                                 checking verts that may be alredy selected */
1130                                                 for (i=0; base_dvert->totweight >i && !(eve->f & SELECT); i++) { 
1131                                                         for (j=0; dvert->totweight >j; j++) {
1132                                                                 if (base_dvert->dw[i].def_nr==dvert->dw[j].def_nr) {
1133                                                                         eve->f |= SELECT;
1134                                                                         selcount++;
1135                                                                         deselcount--;
1136                                                                         if (!deselcount) /*have we selected all posible faces?, if so return*/
1137                                                                                 return selcount;
1138                                                                         break;
1139                                                                 }
1140                                                         }
1141                                                 }
1142                                         }
1143                                 }
1144                         }
1145                 }
1146         } /* end basevert loop */
1147         return selcount;
1148 }
1149
1150 /* EditMode menu triggered from space.c by pressing Shift+G
1151 handles face/edge vert context and
1152 facegroup_select/edgegroup_select/vertgroup_select do all the work
1153 */
1154
1155 void select_mesh_group_menu(EditMesh *em)
1156 {
1157         short ret;
1158         int selcount, first_item=1, multi=0;
1159         char str[512] = "Select Similar "; /* total max length is 404 at the moment */
1160         
1161         if (!ELEM3(em->selectmode, SCE_SELECT_VERTEX, SCE_SELECT_EDGE, SCE_SELECT_FACE)) {
1162                 multi=1;
1163         }
1164         
1165         if(em->selectmode & SCE_SELECT_VERTEX) {
1166                 if (multi) strcat(str, "%t|Vertices%x-1|");
1167                 else strcat(str, "Vertices %t|");
1168                 strcat(str, "    Normal %x1|    Face Users %x2|    Shared Vertex Groups%x3");
1169                 first_item=0;
1170         }
1171
1172         if(em->selectmode & SCE_SELECT_EDGE) {
1173                 if (multi) {
1174                         if (first_item) strcat(str, "%t|Edges%x-1|");
1175                         else strcat(str, "|%l|Edges%x-1|");
1176                 } else strcat(str, "Edges %t|");
1177                 
1178                 strcat(str, "    Length %x10|    Direction %x20|    Face Users%x30|    Face Angle%x40|    Crease%x50|    Seam%x60|    Sharp%x70");
1179                 first_item=0;
1180         }
1181         
1182         if(em->selectmode & SCE_SELECT_FACE) {
1183                 if (multi) {
1184                         strcat(str, "|%l|Faces%x-1|");
1185                 } else strcat(str, "Faces %t|");
1186                 strcat(str, "    Material %x100|    Image %x200|    Area %x300|    Perimeter %x400|    Normal %x500|    Co-Planar %x600");
1187         
1188         }
1189         
1190         ret= pupmenu(str);
1191         if (ret<1) return;
1192         
1193         if (ret<10) {
1194                 selcount= vertgroup_select(em, ret);
1195                 if (selcount) { /* update if data was selected */
1196                         EM_select_flush(em); /* so that selected verts, go onto select faces */
1197                         em->totvertsel += selcount;
1198 //                      if (EM_texFaceCheck())
1199                         BIF_undo_push("Select Similar Vertices");
1200                 }
1201                 return;
1202         }
1203         
1204         if (ret<100) {
1205                 selcount= edgegroup_select(em, ret/10);
1206                 
1207                 if (selcount) { /* update if data was selected */
1208                         /*EM_select_flush(em);*/ /* dont use because it can end up selecting more edges and is not usefull*/
1209                         em->totedgesel+=selcount;
1210 //                      if (EM_texFaceCheck())
1211                         BIF_undo_push("Select Similar Edges");
1212                 }
1213                 return;
1214         }
1215         
1216         if (ret<1000) {
1217                 selcount= facegroup_select(em, ret/100);
1218                 if (selcount) { /* update if data was selected */
1219                         em->totfacesel+=selcount;
1220 //                      if (EM_texFaceCheck())
1221                         BIF_undo_push("Select Similar Faces");
1222                 }
1223                 return;
1224         }
1225 }
1226
1227 int mesh_layers_menu_charlen(CustomData *data, int type)
1228 {
1229         int i, len = 0;
1230         /* see if there is a duplicate */
1231         for(i=0; i<data->totlayer; i++) {
1232                 if((&data->layers[i])->type == type) {
1233                         /* we could count the chars here but we'll just assumeme each
1234                          * is 32 chars with some room for the menu text - 40 should be fine */
1235                         len+=40; 
1236                 }
1237         }
1238         return len;
1239 }
1240
1241 /* this function adds menu text into an existing string.
1242  * this string's size should be allocated with mesh_layers_menu_charlen */
1243 void mesh_layers_menu_concat(CustomData *data, int type, char *str) {
1244         int i, count = 0;
1245         char *str_pt = str;
1246         CustomDataLayer *layer;
1247         
1248         /* see if there is a duplicate */
1249         for(i=0; i<data->totlayer; i++) {
1250                 layer = &data->layers[i];
1251                 if(layer->type == type) {
1252                         str_pt += sprintf(str_pt, "%s%%x%d|", layer->name, count);
1253                         count++;
1254                 }
1255         }
1256 }
1257
1258 int mesh_layers_menu(CustomData *data, int type) {
1259         int ret;
1260         char *str_pt, *str;
1261         
1262         str_pt = str = MEM_mallocN(mesh_layers_menu_charlen(data, type) + 18, "layer menu");
1263         str[0] = '\0';
1264         
1265         str_pt += sprintf(str_pt, "Layers%%t|");
1266         
1267         mesh_layers_menu_concat(data, type, str_pt);
1268         
1269         ret = pupmenu(str);
1270         MEM_freeN(str);
1271         return ret;
1272 }
1273
1274 void EM_mesh_copy_edge(EditMesh *em, short type) 
1275 {
1276         EditSelection *ese;
1277         short change=0;
1278         
1279         EditEdge *eed, *eed_act;
1280         float vec[3], vec_mid[3], eed_len, eed_len_act;
1281         
1282         if (!em) return;
1283         
1284         ese = em->selected.last;
1285         if (!ese) return;
1286         
1287         eed_act = (EditEdge*)ese->data;
1288         
1289         switch (type) {
1290         case 1: /* copy crease */
1291                 for(eed=em->edges.first; eed; eed=eed->next) {
1292                         if (eed->f & SELECT && eed != eed_act && eed->crease != eed_act->crease) {
1293                                 eed->crease = eed_act->crease;
1294                                 change = 1;
1295                         }
1296                 }
1297                 break;
1298         case 2: /* copy bevel weight */
1299                 for(eed=em->edges.first; eed; eed=eed->next) {
1300                         if (eed->f & SELECT && eed != eed_act && eed->bweight != eed_act->bweight) {
1301                                 eed->bweight = eed_act->bweight;
1302                                 change = 1;
1303                         }
1304                 }
1305                 break;
1306
1307         case 3: /* copy length */
1308                 eed_len_act = VecLenf(eed_act->v1->co, eed_act->v2->co);
1309                 for(eed=em->edges.first; eed; eed=eed->next) {
1310                         if (eed->f & SELECT && eed != eed_act) {
1311
1312                                 eed_len = VecLenf(eed->v1->co, eed->v2->co);
1313
1314                                 if (eed_len == eed_len_act) continue;
1315                                 /* if this edge is zero length we cont do anything with it*/
1316                                 if (eed_len == 0.0f) continue;
1317                                 if (eed_len_act == 0.0f) {
1318                                         VecAddf(vec_mid, eed->v1->co, eed->v2->co);
1319                                         VecMulf(vec_mid, 0.5);
1320                                         VECCOPY(eed->v1->co, vec_mid);
1321                                         VECCOPY(eed->v2->co, vec_mid);
1322                                 } else {
1323                                         /* copy the edge length */
1324                                         VecAddf(vec_mid, eed->v1->co, eed->v2->co);
1325                                         VecMulf(vec_mid, 0.5);
1326
1327                                         /* SCALE 1 */
1328                                         VecSubf(vec, eed->v1->co, vec_mid);
1329                                         VecMulf(vec, eed_len_act/eed_len);
1330                                         VecAddf(eed->v1->co, vec, vec_mid);
1331
1332                                         /* SCALE 2 */
1333                                         VecSubf(vec, eed->v2->co, vec_mid);
1334                                         VecMulf(vec, eed_len_act/eed_len);
1335                                         VecAddf(eed->v2->co, vec, vec_mid);
1336                                 }
1337                                 change = 1;
1338                         }
1339                 }
1340
1341                 if (change)
1342                         recalc_editnormals(em);
1343
1344                 break;
1345         }
1346         
1347         if (change) {
1348 //              DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
1349                 
1350                 BIF_undo_push("Copy Edge Attribute");
1351         }
1352 }
1353
1354 void EM_mesh_copy_face(EditMesh *em, short type)
1355 {
1356         short change=0;
1357         
1358         EditFace *efa, *efa_act;
1359         MTFace *tf, *tf_act = NULL;
1360         MCol *mcol, *mcol_act = NULL;
1361         if (!em) return;
1362         efa_act = EM_get_actFace(em, 0);
1363         
1364         if (!efa_act) return;
1365         
1366         tf_act =        CustomData_em_get(&em->fdata, efa_act->data, CD_MTFACE);
1367         mcol_act =      CustomData_em_get(&em->fdata, efa_act->data, CD_MCOL);
1368         
1369         switch (type) {
1370         case 1: /* copy material */
1371                 for(efa=em->faces.first; efa; efa=efa->next) {
1372                         if (efa->f & SELECT && efa->mat_nr != efa_act->mat_nr) {
1373                                 efa->mat_nr = efa_act->mat_nr;
1374                                 change = 1;
1375                         }
1376                 }
1377                 break;
1378         case 2: /* copy image */
1379                 if (!tf_act) {
1380                         error("mesh has no uv/image layers");
1381                         return;
1382                 }
1383                 for(efa=em->faces.first; efa; efa=efa->next) {
1384                         if (efa->f & SELECT && efa != efa_act) {
1385                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1386                                 if (tf_act->tpage) {
1387                                         tf->tpage = tf_act->tpage;
1388                                         tf->mode |= TF_TEX;
1389                                 } else {
1390                                         tf->tpage = NULL;
1391                                         tf->mode &= ~TF_TEX;
1392                                 }
1393                                 tf->tile= tf_act->tile;
1394                                 change = 1;
1395                         }
1396                 }
1397                 break;
1398
1399         case 3: /* copy UV's */
1400                 if (!tf_act) {
1401                         error("mesh has no uv/image layers");
1402                         return;
1403                 }
1404                 for(efa=em->faces.first; efa; efa=efa->next) {
1405                         if (efa->f & SELECT && efa != efa_act) {
1406                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1407                                 memcpy(tf->uv, tf_act->uv, sizeof(tf->uv));
1408                                 change = 1;
1409                         }
1410                 }
1411                 break;
1412         case 4: /* mode's */
1413                 if (!tf_act) {
1414                         error("mesh has no uv/image layers");
1415                         return;
1416                 }
1417                 for(efa=em->faces.first; efa; efa=efa->next) {
1418                         if (efa->f & SELECT && efa != efa_act) {
1419                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1420                                 tf->mode= tf_act->mode;
1421                                 change = 1;
1422                         }
1423                 }
1424                 break;
1425         case 5: /* copy transp's */
1426                 if (!tf_act) {
1427                         error("mesh has no uv/image layers");
1428                         return;
1429                 }
1430                 for(efa=em->faces.first; efa; efa=efa->next) {
1431                         if (efa->f & SELECT && efa != efa_act) {
1432                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1433                                 tf->transp= tf_act->transp;
1434                                 change = 1;
1435                         }
1436                 }
1437                 break;
1438
1439         case 6: /* copy vcols's */
1440                 if (!mcol_act) {
1441                         error("mesh has no color layers");
1442                         return;
1443                 } else {
1444                         /* guess the 4th color if needs be */
1445                         float val =- 1;
1446
1447                         if (!efa_act->v4) {
1448                                 /* guess the othe vale, we may need to use it
1449                                  * 
1450                                  * Modifying the 4th value of the mcol is ok here since its not seen
1451                                  * on a triangle
1452                                  * */
1453                                 val = ((float)(mcol_act->r +  (mcol_act+1)->r + (mcol_act+2)->r)) / 3; CLAMP(val, 0, 255);
1454                                 (mcol_act+3)->r = (char)val;
1455
1456                                 val = ((float)(mcol_act->g +  (mcol_act+1)->g + (mcol_act+2)->g)) / 3; CLAMP(val, 0, 255);
1457                                 (mcol_act+3)->g = (char)val;
1458
1459                                 val = ((float)(mcol_act->b +  (mcol_act+1)->b + (mcol_act+2)->b)) / 3; CLAMP(val, 0, 255);
1460                                 (mcol_act+3)->b = (char)val;
1461                         } 
1462
1463
1464                         for(efa=em->faces.first; efa; efa=efa->next) {
1465                                 if (efa->f & SELECT && efa != efa_act) {
1466                                         /* TODO - make copy from tri to quad guess the 4th vert */
1467                                         mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
1468                                         memcpy(mcol, mcol_act, sizeof(MCol)*4); 
1469                                         change = 1;
1470                                 }
1471                         }
1472                 }
1473                 break;
1474         }
1475         
1476         if (change) {
1477 //              DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
1478                 if (type==3) {
1479 // XXX                  allqueue(REDRAWIMAGE, 0);                       
1480                 }
1481                 
1482                 BIF_undo_push("Copy Face Attribute");
1483         }
1484 }
1485
1486
1487 void EM_mesh_copy_face_layer(EditMesh *em, short type) 
1488 {
1489         short change=0;
1490         
1491         EditFace *efa;
1492         MTFace *tf, *tf_from;
1493         MCol *mcol, *mcol_from;
1494         
1495         if (!em) return;
1496         
1497         switch(type) {
1498         case 7:
1499         case 8:
1500         case 9:
1501                 if (CustomData_number_of_layers(&em->fdata, CD_MTFACE)<2) {
1502                         error("mesh does not have multiple uv/image layers");
1503                         return;
1504                 } else {
1505                         int layer_orig_idx, layer_idx;
1506
1507                         layer_idx = mesh_layers_menu(&em->fdata, CD_MTFACE);
1508                         if (layer_idx<0) return;
1509
1510                         /* warning, have not updated mesh pointers however this is not needed since we swicth back */
1511                         layer_orig_idx = CustomData_get_active_layer(&em->fdata, CD_MTFACE);
1512                         if (layer_idx==layer_orig_idx)
1513                                 return;
1514
1515                         /* get the tfaces */
1516                         CustomData_set_layer_active(&em->fdata, CD_MTFACE, (int)layer_idx);
1517                         /* store the tfaces in our temp */
1518                         for(efa=em->faces.first; efa; efa=efa->next) {
1519                                 if (efa->f & SELECT) {
1520                                         efa->tmp.p = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1521                                 }       
1522                         }
1523                         CustomData_set_layer_active(&em->fdata, CD_MTFACE, layer_orig_idx);
1524                 }
1525                 break;
1526
1527         case 10: /* select vcol layers - make sure this stays in sync with above code */
1528                 if (CustomData_number_of_layers(&em->fdata, CD_MCOL)<2) {
1529                         error("mesh does not have multiple color layers");
1530                         return;
1531                 } else {
1532                         int layer_orig_idx, layer_idx;
1533
1534                         layer_idx = mesh_layers_menu(&em->fdata, CD_MCOL);
1535                         if (layer_idx<0) return;
1536
1537                         /* warning, have not updated mesh pointers however this is not needed since we swicth back */
1538                         layer_orig_idx = CustomData_get_active_layer(&em->fdata, CD_MCOL);
1539                         if (layer_idx==layer_orig_idx)
1540                                 return;
1541
1542                         /* get the tfaces */
1543                         CustomData_set_layer_active(&em->fdata, CD_MCOL, (int)layer_idx);
1544                         /* store the tfaces in our temp */
1545                         for(efa=em->faces.first; efa; efa=efa->next) {
1546                                 if (efa->f & SELECT) {
1547                                         efa->tmp.p = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
1548                                 }       
1549                         }
1550                         CustomData_set_layer_active(&em->fdata, CD_MCOL, layer_orig_idx);
1551
1552                 }
1553                 break;
1554         }
1555
1556         /* layer copy only - sanity checks done above */
1557         switch (type) {
1558         case 7: /* copy UV's only */
1559                 for(efa=em->faces.first; efa; efa=efa->next) {
1560                         if (efa->f & SELECT) {
1561                                 tf_from = (MTFace *)efa->tmp.p; /* not active but easier to use this way */
1562                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1563                                 memcpy(tf->uv, tf_from->uv, sizeof(tf->uv));
1564                                 change = 1;
1565                         }
1566                 }
1567                 break;
1568         case 8: /* copy image settings only */
1569                 for(efa=em->faces.first; efa; efa=efa->next) {
1570                         if (efa->f & SELECT) {
1571                                 tf_from = (MTFace *)efa->tmp.p; /* not active but easier to use this way */
1572                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1573                                 if (tf_from->tpage) {
1574                                         tf->tpage = tf_from->tpage;
1575                                         tf->mode |= TF_TEX;
1576                                 } else {
1577                                         tf->tpage = NULL;
1578                                         tf->mode &= ~TF_TEX;
1579                                 }
1580                                 tf->tile= tf_from->tile;
1581                                 change = 1;
1582                         }
1583                 }
1584                 break;
1585         case 9: /* copy all tface info */
1586                 for(efa=em->faces.first; efa; efa=efa->next) {
1587                         if (efa->f & SELECT) {
1588                                 tf_from = (MTFace *)efa->tmp.p; /* not active but easier to use this way */
1589                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1590                                 memcpy(tf->uv, ((MTFace *)efa->tmp.p)->uv, sizeof(tf->uv));
1591                                 tf->tpage = tf_from->tpage;
1592                                 tf->mode = tf_from->mode;
1593                                 tf->transp = tf_from->transp;
1594                                 change = 1;
1595                         }
1596                 }
1597                 break;
1598         case 10:
1599                 for(efa=em->faces.first; efa; efa=efa->next) {
1600                         if (efa->f & SELECT) {
1601                                 mcol_from = (MCol *)efa->tmp.p; 
1602                                 mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
1603                                 memcpy(mcol, mcol_from, sizeof(MCol)*4);        
1604                                 change = 1;
1605                         }
1606                 }
1607                 break;
1608         }
1609
1610         if (change) {
1611 //              DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
1612                 
1613                 BIF_undo_push("Copy Face Layer");
1614         }
1615 }
1616
1617
1618 /* ctrl+c in mesh editmode */
1619 void mesh_copy_menu(EditMesh *em)
1620 {
1621         EditSelection *ese;
1622         int ret;
1623         if (!em) return;
1624         
1625         ese = em->selected.last;
1626         
1627         /* Faces can have a NULL ese, so dont return on a NULL ese here */
1628         
1629         if(ese && ese->type == EDITVERT) {
1630                 /* EditVert *ev, *ev_act = (EditVert*)ese->data;
1631                 ret= pupmenu(""); */
1632         } else if(ese && ese->type == EDITEDGE) {
1633                 ret= pupmenu("Copy Active Edge to Selected%t|Crease%x1|Bevel Weight%x2|Length%x3");
1634                 if (ret<1) return;
1635                 
1636                 EM_mesh_copy_edge(em, ret);
1637                 
1638         } else if(ese==NULL || ese->type == EDITFACE) {
1639                 ret= pupmenu(
1640                         "Copy Face Selected%t|"
1641                         "Active Material%x1|Active Image%x2|Active UV Coords%x3|"
1642                         "Active Mode%x4|Active Transp%x5|Active Vertex Colors%x6|%l|"
1643
1644                         "TexFace UVs from layer%x7|"
1645                         "TexFace Images from layer%x8|"
1646                         "TexFace All from layer%x9|"
1647                         "Vertex Colors from layer%x10");
1648                 if (ret<1) return;
1649                 
1650                 if (ret<=6) {
1651                         EM_mesh_copy_face(em, ret);
1652                 } else {
1653                         EM_mesh_copy_face_layer(em, ret);
1654                 }
1655         }
1656 }
1657
1658
1659 /* ****************  LOOP SELECTS *************** */
1660
1661 /* selects quads in loop direction of indicated edge */
1662 /* only flush over edges with valence <= 2 */
1663 void faceloop_select(EditMesh *em, EditEdge *startedge, int select)
1664 {
1665         EditEdge *eed;
1666         EditFace *efa;
1667         int looking= 1;
1668         
1669         /* in eed->f1 we put the valence (amount of faces in edge) */
1670         /* in eed->f2 we put tagged flag as correct loop */
1671         /* in efa->f1 we put tagged flag as correct to select */
1672
1673         for(eed= em->edges.first; eed; eed= eed->next) {
1674                 eed->f1= 0;
1675                 eed->f2= 0;
1676         }
1677         for(efa= em->faces.first; efa; efa= efa->next) {
1678                 efa->f1= 0;
1679                 if(efa->h==0) {
1680                         efa->e1->f1++;
1681                         efa->e2->f1++;
1682                         efa->e3->f1++;
1683                         if(efa->e4) efa->e4->f1++;
1684                 }
1685         }
1686         
1687         /* tag startedge OK*/
1688         startedge->f2= 1;
1689         
1690         while(looking) {
1691                 looking= 0;
1692                 
1693                 for(efa= em->faces.first; efa; efa= efa->next) {
1694                         if(efa->h==0 && efa->e4 && efa->f1==0) {        /* not done quad */
1695                                 if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { /* valence ok */
1696
1697                                         /* if edge tagged, select opposing edge and mark face ok */
1698                                         if(efa->e1->f2) {
1699                                                 efa->e3->f2= 1;
1700                                                 efa->f1= 1;
1701                                                 looking= 1;
1702                                         }
1703                                         else if(efa->e2->f2) {
1704                                                 efa->e4->f2= 1;
1705                                                 efa->f1= 1;
1706                                                 looking= 1;
1707                                         }
1708                                         if(efa->e3->f2) {
1709                                                 efa->e1->f2= 1;
1710                                                 efa->f1= 1;
1711                                                 looking= 1;
1712                                         }
1713                                         if(efa->e4->f2) {
1714                                                 efa->e2->f2= 1;
1715                                                 efa->f1= 1;
1716                                                 looking= 1;
1717                                         }
1718                                 }
1719                         }
1720                 }
1721         }
1722         
1723         /* (de)select the faces */
1724         if(select!=2) {
1725                 for(efa= em->faces.first; efa; efa= efa->next) {
1726                         if(efa->f1) EM_select_face(efa, select);
1727                 }
1728         }
1729 }
1730
1731
1732 /* helper for edgeloop_select, checks for eed->f2 tag in faces */
1733 static int edge_not_in_tagged_face(EditMesh *em, EditEdge *eed)
1734 {
1735         EditFace *efa;
1736         
1737         for(efa= em->faces.first; efa; efa= efa->next) {
1738                 if(efa->h==0) {
1739                         if(efa->e1==eed || efa->e2==eed || efa->e3==eed || efa->e4==eed) {      /* edge is in face */
1740                                 if(efa->e1->f2 || efa->e2->f2 || efa->e3->f2 || (efa->e4 && efa->e4->f2)) {     /* face is tagged */
1741                                         return 0;
1742                                 }
1743                         }
1744                 }
1745         }
1746         return 1;
1747 }
1748
1749 /* selects or deselects edges that:
1750 - if edges has 2 faces:
1751         - has vertices with valence of 4
1752         - not shares face with previous edge
1753 - if edge has 1 face:
1754         - has vertices with valence 4
1755         - not shares face with previous edge
1756         - but also only 1 face
1757 - if edge no face:
1758         - has vertices with valence 2
1759 */
1760 static void edgeloop_select(EditMesh *em, EditEdge *starteed, int select)
1761 {
1762         EditVert *eve;
1763         EditEdge *eed;
1764         EditFace *efa;
1765         int looking= 1;
1766         
1767         /* in f1 we put the valence (amount of edges in a vertex, or faces in edge) */
1768         /* in eed->f2 and efa->f1 we put tagged flag as correct loop */
1769         for(eve= em->verts.first; eve; eve= eve->next) {
1770                 eve->f1= 0;
1771                 eve->f2= 0;
1772         }
1773         for(eed= em->edges.first; eed; eed= eed->next) {
1774                 eed->f1= 0;
1775                 eed->f2= 0;
1776                 if((eed->h & 1)==0) {   /* fgon edges add to valence too */
1777                         eed->v1->f1++; eed->v2->f1++;
1778                 }
1779         }
1780         for(efa= em->faces.first; efa; efa= efa->next) {
1781                 efa->f1= 0;
1782                 if(efa->h==0) {
1783                         efa->e1->f1++;
1784                         efa->e2->f1++;
1785                         efa->e3->f1++;
1786                         if(efa->e4) efa->e4->f1++;
1787                 }
1788         }
1789         
1790         /* looped edges & vertices get tagged f2 */
1791         starteed->f2= 1;
1792         if(starteed->v1->f1<5) starteed->v1->f2= 1;
1793         if(starteed->v2->f1<5) starteed->v2->f2= 1;
1794         /* sorry, first edge isnt even ok */
1795         if(starteed->v1->f2==0 && starteed->v2->f2==0) looking= 0;
1796         
1797         while(looking) {
1798                 looking= 0;
1799                 
1800                 /* find correct valence edges which are not tagged yet, but connect to tagged one */
1801                 for(eed= em->edges.first; eed; eed= eed->next) {
1802                         if(eed->h==0 && eed->f2==0) { /* edge not hidden, not tagged */
1803                                 if( (eed->v1->f1<5 && eed->v1->f2) || (eed->v2->f1<5 && eed->v2->f2)) { /* valence of vertex OK, and is tagged */
1804                                         /* new edge is not allowed to be in face with tagged edge */
1805                                         if(edge_not_in_tagged_face(em, eed)) {
1806                                                 if(eed->f1==starteed->f1) {     /* same amount of faces */
1807                                                         looking= 1;
1808                                                         eed->f2= 1;
1809                                                         if(eed->v2->f1<5) eed->v2->f2= 1;
1810                                                         if(eed->v1->f1<5) eed->v1->f2= 1;
1811                                                 }
1812                                         }
1813                                 }
1814                         }
1815                 }
1816         }
1817         /* and we do the select */
1818         for(eed= em->edges.first; eed; eed= eed->next) {
1819                 if(eed->f2) EM_select_edge(eed, select);
1820         }
1821 }
1822
1823 /* 
1824    Almostly exactly the same code as faceloop select
1825 */
1826 static void edgering_select(EditMesh *em, EditEdge *startedge, int select)
1827 {
1828         EditEdge *eed;
1829         EditFace *efa;
1830         int looking= 1;
1831         
1832         /* in eed->f1 we put the valence (amount of faces in edge) */
1833         /* in eed->f2 we put tagged flag as correct loop */
1834         /* in efa->f1 we put tagged flag as correct to select */
1835
1836         for(eed= em->edges.first; eed; eed= eed->next) {
1837                 eed->f1= 0;
1838                 eed->f2= 0;
1839         }
1840         for(efa= em->faces.first; efa; efa= efa->next) {
1841                 efa->f1= 0;
1842                 if(efa->h==0) {
1843                         efa->e1->f1++;
1844                         efa->e2->f1++;
1845                         efa->e3->f1++;
1846                         if(efa->e4) efa->e4->f1++;
1847                 }
1848         }
1849         
1850         /* tag startedge OK */
1851         startedge->f2= 1;
1852         
1853         while(looking) {
1854                 looking= 0;
1855                 
1856                 for(efa= em->faces.first; efa; efa= efa->next) {
1857                         if(efa->e4 && efa->f1==0 && !efa->h) {  /* not done quad */
1858                                 if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { /* valence ok */
1859
1860                                         /* if edge tagged, select opposing edge and mark face ok */
1861                                         if(efa->e1->f2) {
1862                                                 efa->e3->f2= 1;
1863                                                 efa->f1= 1;
1864                                                 looking= 1;
1865                                         }
1866                                         else if(efa->e2->f2) {
1867                                                 efa->e4->f2= 1;
1868                                                 efa->f1= 1;
1869                                                 looking= 1;
1870                                         }
1871                                         if(efa->e3->f2) {
1872                                                 efa->e1->f2= 1;
1873                                                 efa->f1= 1;
1874                                                 looking= 1;
1875                                         }
1876                                         if(efa->e4->f2) {
1877                                                 efa->e2->f2= 1;
1878                                                 efa->f1= 1;
1879                                                 looking= 1;
1880                                         }
1881                                 }
1882                         }
1883                 }
1884         }
1885         
1886         /* (de)select the edges */
1887         for(eed= em->edges.first; eed; eed= eed->next) {
1888                 if(eed->f2) EM_select_edge(eed, select);
1889         }
1890 }
1891
1892 void loop_multiselect(EditMesh *em, int looptype)
1893 {
1894         EditEdge *eed;
1895         EditEdge **edarray;
1896         int edindex, edfirstcount;
1897         
1898         /* sets em->totedgesel */
1899         EM_nedges_selected(em);
1900         
1901         edarray = MEM_mallocN(sizeof(EditEdge*)*em->totedgesel,"edge array");
1902         edindex = 0;
1903         edfirstcount = em->totedgesel;
1904         
1905         for(eed=em->edges.first; eed; eed=eed->next){
1906                 if(eed->f&SELECT){
1907                         edarray[edindex] = eed;
1908                         edindex += 1;
1909                 }
1910         }
1911         
1912         if(looptype){
1913                 for(edindex = 0; edindex < edfirstcount; edindex +=1){
1914                         eed = edarray[edindex];
1915                         edgering_select(em, eed,SELECT);
1916                 }
1917                 EM_selectmode_flush(em);
1918                 BIF_undo_push("Edge Ring Multi-Select");
1919         }
1920         else{
1921                 for(edindex = 0; edindex < edfirstcount; edindex +=1){
1922                         eed = edarray[edindex];
1923                         edgeloop_select(em, eed,SELECT);
1924                 }
1925                 EM_selectmode_flush(em);
1926                 BIF_undo_push("Edge Loop Multi-Select");
1927         }
1928         MEM_freeN(edarray);
1929 //      if (EM_texFaceCheck())
1930 }
1931                 
1932 /* ***************** MAIN MOUSE SELECTION ************** */
1933
1934 /* just to have the functions nice together */
1935
1936 static void mouse_mesh_loop(ViewContext *vc)
1937 {
1938         EditMesh *em= vc->em;
1939         EditEdge *eed;
1940         int select= 1;
1941         int dist= 50;
1942         int shift= 0, alt= 0, ctrl= 0; // XXX
1943         
1944         eed= findnearestedge(vc, &dist);
1945         if(eed) {
1946                 if (vc->scene->toolsettings->edge_mode == EDGE_MODE_SELECT) {
1947                         if(shift==0) EM_clear_flag_all(em, SELECT);
1948                 
1949                         if((eed->f & SELECT)==0) select=1;
1950                         else if(shift) select=0;
1951
1952                         if(em->selectmode & SCE_SELECT_FACE) {
1953                                 faceloop_select(em, eed, select);
1954                         }
1955                         else if(em->selectmode & SCE_SELECT_EDGE) {
1956                         if((alt && ctrl))
1957                                         edgering_select(em, eed, select);
1958                         else if(alt)
1959                                         edgeloop_select(em, eed, select);
1960                         }
1961                     else if(em->selectmode & SCE_SELECT_VERTEX) {
1962                         if((alt && ctrl))
1963                                         edgering_select(em, eed, select);
1964                         else if(alt)
1965                                         edgeloop_select(em, eed, select);
1966                         }
1967
1968                         EM_selectmode_flush(em);
1969 //                      if (EM_texFaceCheck())
1970                         
1971                 } 
1972                 else {
1973                         int act = (edgetag_context_check(vc->scene, eed)==0);
1974                         int path = 0;
1975                         
1976                         if (alt && ctrl && em->selected.last) {
1977                                 EditSelection *ese = em->selected.last;
1978         
1979                                 if(ese && ese->type == EDITEDGE) {
1980                                         EditEdge *eed_act;
1981                                         eed_act = (EditEdge*)ese->data;
1982                                         if (eed_act != eed) {
1983                                                 /* If shift is pressed we need to use the last active edge, (if it exists) */
1984                                                 if (edgetag_shortest_path(vc->scene, em, eed_act, eed)) {
1985                                                         EM_remove_selection(em, eed_act, EDITEDGE);
1986                                                         EM_select_edge(eed_act, 0);
1987                                                         path = 1;
1988                                                 }
1989                                         }
1990                                 }
1991                         }
1992                         if (path==0) {
1993                                 edgetag_context_set(vc->scene, eed, act); /* switch the edge option */
1994                         }
1995                         
1996                         if (act) {
1997                                 if ((eed->f & SELECT)==0) {
1998                                         EM_select_edge(eed, 1);
1999                                         EM_selectmode_flush(em);
2000                                 }
2001                                 /* even if this is selected it may not be in the selection list */
2002                                 EM_store_selection(em, eed, EDITEDGE);
2003                         } else {
2004                                 if (eed->f & SELECT) {
2005                                         EM_select_edge(eed, 0);
2006                                         /* logic is differnt from above here since if this was selected we dont know if its in the selection list or not */
2007                                         EM_remove_selection(em, eed, EDITEDGE);
2008                                         
2009                                         EM_selectmode_flush(em);
2010                                 }
2011                         }
2012                         
2013                         switch (0) { // XXX scene->toolsettings->edge_mode) {
2014                         case EDGE_MODE_TAG_SEAM:
2015                                 G.f |= G_DRAWSEAMS;
2016                                 break;
2017                         case EDGE_MODE_TAG_SHARP:
2018                                 G.f |= G_DRAWSHARP;
2019                                 break;
2020                         case EDGE_MODE_TAG_CREASE:      
2021                                 G.f |= G_DRAWCREASES;
2022                                 break;
2023                         case EDGE_MODE_TAG_BEVEL:
2024                                 G.f |= G_DRAWBWEIGHTS;
2025                                 break;
2026                         }
2027                         
2028 //                      DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
2029                 }
2030                                 
2031         }
2032 }
2033
2034
2035 /* here actual select happens */
2036 /* gets called via generic mouse select operator */
2037 void mouse_mesh(bContext *C, short mval[2], short extend)
2038 {
2039         ViewContext vc;
2040         EditVert *eve;
2041         EditEdge *eed;
2042         EditFace *efa;
2043         int  alt= 0; // XXX
2044         
2045         /* setup view context for argument to callbacks */
2046         em_setup_viewcontext(C, &vc);
2047         vc.mval[0]= mval[0];
2048         vc.mval[1]= mval[1];
2049         
2050         if(alt) mouse_mesh_loop(&vc);
2051         else if(unified_findnearest(&vc, &eve, &eed, &efa)) {
2052                 
2053                 if(extend==0) EM_clear_flag_all(vc.em, SELECT);
2054                 
2055                 if(efa) {
2056                         /* set the last selected face */
2057                         EM_set_actFace(vc.em, efa);
2058                         
2059                         if( (efa->f & SELECT)==0 ) {
2060                                 EM_store_selection(vc.em, efa, EDITFACE);
2061                                 EM_select_face_fgon(vc.em, efa, 1);
2062                         }
2063                         else if(extend) {
2064                                 EM_remove_selection(vc.em, efa, EDITFACE);
2065                                 EM_select_face_fgon(vc.em, efa, 0);
2066                         }
2067                 }
2068                 else if(eed) {
2069                         if((eed->f & SELECT)==0) {
2070                                 EM_store_selection(vc.em, eed, EDITEDGE);
2071                                 EM_select_edge(eed, 1);
2072                         }
2073                         else if(extend) {
2074                                 EM_remove_selection(vc.em, eed, EDITEDGE);
2075                                 EM_select_edge(eed, 0);
2076                         }
2077                 }
2078                 else if(eve) {
2079                         if((eve->f & SELECT)==0) {
2080                                 eve->f |= SELECT;
2081                                 EM_store_selection(vc.em, eve, EDITVERT);
2082                         }
2083                         else if(extend){ 
2084                                 EM_remove_selection(vc.em, eve, EDITVERT);
2085                                 eve->f &= ~SELECT;
2086                         }
2087                 }
2088                 
2089                 EM_selectmode_flush(vc.em);
2090                   
2091 //              if (EM_texFaceCheck()) {
2092
2093                 if (efa && efa->mat_nr != vc.obedit->actcol-1) {
2094                         vc.obedit->actcol= efa->mat_nr+1;
2095                         vc.em->mat_nr= efa->mat_nr;
2096 //                      BIF_preview_changed(ID_MA);
2097                 }
2098         }
2099
2100         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, vc.obedit);
2101         
2102 //      rightmouse_transform();
2103 }
2104
2105 // XXX should we use CTX_scene(C)->selectmode & SCE_SELECT_FACE like it was in the past ? calls selectconnected_delimit_mesh_all if true
2106 void selectconnected_mesh_all(EditMesh *em)
2107 {
2108         EditVert *v1,*v2;
2109         EditEdge *eed;
2110         short done=1, toggle=0;
2111
2112         if(em->edges.first==0) return;
2113         
2114         while(done==1) {
2115                 done= 0;
2116                 
2117                 toggle++;
2118                 if(toggle & 1) eed= em->edges.first;
2119                 else eed= em->edges.last;
2120                 
2121                 while(eed) {
2122                         v1= eed->v1;
2123                         v2= eed->v2;
2124                         if(eed->h==0) {
2125                                 if(v1->f & SELECT) {
2126                                         if( (v2->f & SELECT)==0 ) {
2127                                                 v2->f |= SELECT;
2128                                                 done= 1;
2129                                         }
2130                                 }
2131                                 else if(v2->f & SELECT) {
2132                                         if( (v1->f & SELECT)==0 ) {
2133                                                 v1->f |= SELECT;
2134                                                 done= 1;
2135                                         }
2136                                 }
2137                         }
2138                         if(toggle & 1) eed= eed->next;
2139                         else eed= eed->prev;
2140                 }
2141         }
2142
2143         /* now use vertex select flag to select rest */
2144         EM_select_flush(em);
2145         
2146 //      if (EM_texFaceCheck())
2147         BIF_undo_push("Select Connected (All)");
2148 }
2149
2150 static int selectconnected_mesh_all_exec(bContext *C, wmOperator *op)
2151 {
2152         Object *obedit= CTX_data_edit_object(C);
2153         EditMesh *em= ((Mesh *)obedit->data)->edit_mesh;
2154         
2155         selectconnected_mesh_all(em);
2156         
2157         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
2158         return OPERATOR_FINISHED;       
2159 }
2160
2161 void MESH_OT_selectconnected_mesh_all(wmOperatorType *ot)
2162 {
2163         /* identifiers */
2164         ot->name= "Select All of the Connected Mesh";
2165         ot->idname= "MESH_OT_selectconnected_mesh_all";
2166         
2167         /* api callbacks */
2168         ot->exec= selectconnected_mesh_all_exec;
2169         ot->poll= ED_operator_editmesh;
2170
2171 }
2172
2173 /* *********** select connected ************* */
2174
2175 // XXX should we use CTX_scene(C)->selectmode & SCE_SELECT_FACE like it was in the past ? calls selectconnected_delimit_mesh if true
2176 static int selectconnected_mesh_invoke(bContext *C, wmOperator *op, wmEvent *event)
2177 {
2178         Object *obedit= CTX_data_edit_object(C);
2179         ViewContext vc;
2180         EditVert *eve, *v1, *v2;
2181         EditEdge *eed;
2182         EditFace *efa;
2183         short done=1, toggle=0;
2184         int sel= !RNA_boolean_get(op->ptr, "deselect");
2185         
2186         /* unified_finednearest needs ogl */
2187         view3d_operator_needs_opengl(C);
2188         
2189         /* setup view context for argument to callbacks */
2190         em_setup_viewcontext(C, &vc);
2191         
2192         if(vc.em->edges.first==0) return OPERATOR_CANCELLED;
2193         
2194         vc.mval[0]= event->x - vc.ar->winrct.xmin;
2195         vc.mval[1]= event->y - vc.ar->winrct.ymin;
2196         
2197         if( unified_findnearest(&vc, &eve, &eed, &efa)==0 ) {
2198                 return OPERATOR_CANCELLED;
2199         }
2200
2201         /* clear test flags */
2202         for(v1= vc.em->verts.first; v1; v1= v1->next) v1->f1= 0;
2203         
2204         /* start vertex/face/edge */
2205         if(eve) eve->f1= 1;
2206         else if(eed) eed->v1->f1= eed->v2->f1= 1;
2207         else efa->v1->f1= efa->v2->f1= efa->v3->f1= 1;
2208         
2209         /* set flag f1 if affected */
2210         while(done==1) {
2211                 done= 0;
2212                 toggle++;
2213                 
2214                 if(toggle & 1) eed= vc.em->edges.first;
2215                 else eed= vc.em->edges.last;
2216                 
2217                 while(eed) {
2218                         v1= eed->v1;
2219                         v2= eed->v2;
2220                         
2221                         if(eed->h==0) {
2222                                 if(v1->f1 && v2->f1==0) {
2223                                         v2->f1= 1;
2224                                         done= 1;
2225                                 }
2226                                 else if(v1->f1==0 && v2->f1) {
2227                                         v1->f1= 1;
2228                                         done= 1;
2229                                 }
2230                         }
2231                         
2232                         if(toggle & 1) eed= eed->next;
2233                         else eed= eed->prev;
2234                 }
2235         }
2236         
2237         /* now use vertex f1 flag to select/deselect */
2238         for(eed= vc.em->edges.first; eed; eed= eed->next) {
2239                 if(eed->v1->f1 && eed->v2->f1) 
2240                         EM_select_edge(eed, sel);
2241         }
2242         for(efa= vc.em->faces.first; efa; efa= efa->next) {
2243                 if(efa->v1->f1 && efa->v2->f1 && efa->v3->f1 && (efa->v4==NULL || efa->v4->f1)) 
2244                         EM_select_face(efa, sel);
2245         }
2246         /* no flush needed, connected geometry is done */
2247         
2248 //      if (EM_texFaceCheck())
2249         
2250         BIF_undo_push("Select Linked");
2251         
2252         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
2253         return OPERATOR_FINISHED;       
2254 }
2255
2256 void MESH_OT_selectconnected_mesh(wmOperatorType *ot)
2257 {
2258         /* identifiers */
2259         ot->name= "Select Connected Mesh";
2260         ot->idname= "MESH_OT_selectconnected_mesh";
2261         
2262         /* api callbacks */
2263         ot->invoke= selectconnected_mesh_invoke;
2264         ot->poll= ED_operator_editmesh;
2265
2266         RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "");
2267 }
2268
2269 /* ************************* */
2270
2271 /* for use with selectconnected_delimit_mesh only! */
2272 #define is_edge_delimit_ok(eed) ((eed->tmp.l == 1) && (eed->seam==0))
2273 #define is_face_tag(efa) is_edge_delimit_ok(efa->e1) || is_edge_delimit_ok(efa->e2) || is_edge_delimit_ok(efa->e3) || (efa->v4 && is_edge_delimit_ok(efa->e4))
2274
2275 #define face_tag(efa)\
2276         if(efa->v4)     efa->tmp.l=             efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= efa->e4->tmp.l= 1;\
2277         else            efa->tmp.l=             efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= 1;
2278
2279 /* all - 1) use all faces for extending the selection  2) only use the mouse face
2280  * sel - 1) select  0) deselect 
2281  * */
2282 static void selectconnected_delimit_mesh__internal(ViewContext *vc, short all, short sel)
2283 {
2284         EditMesh *em= vc->em;
2285         EditFace *efa;
2286         EditEdge *eed;
2287         short done=1, change=0;
2288         int dist = 75;
2289         
2290         if(em->faces.first==0) return;
2291         
2292         /* flag all edges as off*/
2293         for(eed= em->edges.first; eed; eed= eed->next)
2294                 eed->tmp.l=0;
2295         
2296         if (all) {
2297                 for(efa= em->faces.first; efa; efa= efa->next) {
2298                         if (efa->f & SELECT) {
2299                                 face_tag(efa);
2300                         } else {
2301                                 efa->tmp.l = 0;
2302                         }
2303                 }
2304         } else {
2305                 EditFace *efa_mouse = findnearestface(vc, &dist);
2306                 
2307                 if( !efa_mouse ) {
2308                         /* error("Nothing indicated "); */ /* this is mostly annoying, eps with occluded geometry */
2309                         return;
2310                 }
2311                 
2312                 for(efa= em->faces.first; efa; efa= efa->next) {
2313                         efa->tmp.l = 0;
2314                 }
2315                 efa_mouse->tmp.l = 1;
2316                 face_tag(efa_mouse);
2317         }
2318         
2319         while(done==1) {
2320                 done= 0;
2321                 /* simple algo - select all faces that have a selected edge
2322                  * this intern selects the edge, repeat until nothing is left to do */
2323                 for(efa= em->faces.first; efa; efa= efa->next) {
2324                         if ((efa->tmp.l == 0) && (!efa->h)) {
2325                                 if (is_face_tag(efa)) {
2326                                         face_tag(efa);
2327                                         done= 1;
2328                                 }
2329                         }
2330                 }
2331         }
2332         
2333         for(efa= em->faces.first; efa; efa= efa->next) {
2334                 if (efa->tmp.l) {
2335                         if (sel) {
2336                                 if (!(efa->f & SELECT)) {
2337                                         EM_select_face(efa, 1);
2338                                         change = 1;
2339                                 }
2340                         } else {
2341                                 if (efa->f & SELECT) {
2342                                         EM_select_face(efa, 0);
2343                                         change = 1;
2344                                 }
2345                         }
2346                 }
2347         }
2348         
2349         if (!change)
2350                 return;
2351         
2352         if (!sel) /* make sure de-selecting faces didnt de-select the verts/edges connected to selected faces, this is common with boundries */
2353                 for(efa= em->faces.first; efa; efa= efa->next)
2354                         if (efa->f & SELECT)
2355                                 EM_select_face(efa, 1);
2356         
2357 //      if (EM_texFaceCheck())
2358         
2359         BIF_undo_push("Select Linked Delimeted");
2360         
2361 }
2362
2363 #undef is_edge_delimit_ok
2364 #undef is_face_tag
2365 #undef face_tag
2366
2367 void selectconnected_delimit_mesh(EditMesh *em)
2368 {
2369         
2370         // XXX selectconnected_delimit_mesh__internal(em, 0, ((G.qual & LR_SHIFTKEY)==0));
2371 }
2372 void selectconnected_delimit_mesh_all(ViewContext *vc)
2373 {
2374         selectconnected_delimit_mesh__internal(vc, 1, 1);
2375 }       
2376         
2377         
2378 /* swap is 0 or 1, if 1 it hides not selected */
2379 void hide_mesh(EditMesh *em, int swap)
2380 {
2381         EditVert *eve;
2382         EditEdge *eed;
2383         EditFace *efa;
2384         int a;
2385         
2386         if(em==NULL) return;
2387
2388         /* hide happens on least dominant select mode, and flushes up, not down! (helps preventing errors in subsurf) */
2389         /*  - vertex hidden, always means edge is hidden too
2390                 - edge hidden, always means face is hidden too
2391                 - face hidden, only set face hide
2392                 - then only flush back down what's absolute hidden
2393         */
2394         if(em->selectmode & SCE_SELECT_VERTEX) {
2395                 for(eve= em->verts.first; eve; eve= eve->next) {
2396                         if((eve->f & SELECT)!=swap) {
2397                                 eve->f &= ~SELECT;
2398                                 eve->h= 1;
2399                         }
2400                 }
2401         
2402                 for(eed= em->edges.first; eed; eed= eed->next) {
2403                         if(eed->v1->h || eed->v2->h) {
2404                                 eed->h |= 1;
2405                                 eed->f &= ~SELECT;
2406                         }
2407                 }
2408         
2409                 for(efa= em->faces.first; efa; efa= efa->next) {
2410                         if(efa->e1->h & 1 || efa->e2->h & 1 || efa->e3->h & 1 || (efa->e4 && efa->e4->h & 1)) {
2411                                 efa->h= 1;
2412                                 efa->f &= ~SELECT;
2413                         }
2414                 }
2415         }
2416         else if(em->selectmode & SCE_SELECT_EDGE) {
2417
2418                 for(eed= em->edges.first; eed; eed= eed->next) {
2419                         if((eed->f & SELECT)!=swap) {
2420                                 eed->h |= 1;
2421                                 EM_select_edge(eed, 0);
2422                         }
2423                 }
2424
2425                 for(efa= em->faces.first; efa; efa= efa->next) {
2426                         if(efa->e1->h & 1 || efa->e2->h & 1 || efa->e3->h & 1 || (efa->e4 && efa->e4->h & 1)) {
2427                                 efa->h= 1;
2428                                 efa->f &= ~SELECT;
2429                         }
2430                 }
2431         }
2432         else {
2433
2434                 for(efa= em->faces.first; efa; efa= efa->next) {
2435                         if((efa->f & SELECT)!=swap) {
2436                                 efa->h= 1;
2437                                 EM_select_face(efa, 0);
2438                         }
2439                 }
2440         }
2441         
2442         /* flush down, only whats 100% hidden */
2443         for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2444         for(eed= em->edges.first; eed; eed= eed->next) eed->f1= 0;
2445         
2446         if(em->selectmode & SCE_SELECT_FACE) {
2447                 for(efa= em->faces.first; efa; efa= efa->next) {
2448                         if(efa->h) a= 1; else a= 2;
2449                         efa->e1->f1 |= a;
2450                         efa->e2->f1 |= a;
2451                         efa->e3->f1 |= a;
2452                         if(efa->e4) efa->e4->f1 |= a;
2453                         /* When edges are not delt with in their own loop, we need to explicitly re-selct select edges that are joined to unselected faces */
2454                         if (swap && (em->selectmode == SCE_SELECT_FACE) && (efa->f & SELECT)) {
2455                                 EM_select_face(efa, 1);
2456                         }
2457                 }
2458         }
2459         
2460         if(em->selectmode >= SCE_SELECT_EDGE) {
2461                 for(eed= em->edges.first; eed; eed= eed->next) {
2462                         if(eed->f1==1) eed->h |= 1;
2463                         if(eed->h & 1) a= 1; else a= 2;
2464                         eed->v1->f1 |= a;
2465                         eed->v2->f1 |= a;
2466                 }
2467         }
2468
2469         if(em->selectmode >= SCE_SELECT_VERTEX) {
2470                 for(eve= em->verts.first; eve; eve= eve->next) {
2471                         if(eve->f1==1) eve->h= 1;
2472                 }
2473         }
2474         
2475         em->totedgesel= em->totfacesel= em->totvertsel= 0;
2476 //      if(EM_texFaceCheck())
2477
2478         //      DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); 
2479         BIF_undo_push("Hide");
2480 }
2481
2482 static int hide_mesh_exec(bContext *C, wmOperator *op)
2483 {
2484         Object *obedit= CTX_data_edit_object(C);
2485         EditMesh *em= ((Mesh *)obedit->data)->edit_mesh;
2486         
2487         /* 'standard' behaviour - check if selected, then apply relevant selection */
2488         if (RNA_boolean_get(op->ptr, "swap"))
2489                 hide_mesh(em,1);
2490         else
2491                 hide_mesh(em,0);
2492                 
2493         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
2494         return OPERATOR_FINISHED;       
2495 }
2496
2497 void MESH_OT_hide_mesh(wmOperatorType *ot)
2498 {
2499         /* identifiers */
2500         ot->name= "Hide vertice or Hide All of the Mesh";
2501         ot->idname= "MESH_OT_hide_mesh";
2502         
2503         /* api callbacks */
2504         ot->exec= hide_mesh_exec;
2505         ot->poll= ED_operator_editmesh;
2506         
2507         /* flags */
2508         ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
2509         
2510         /* props */
2511         RNA_def_boolean(ot->srna, "swap", 0, "Swap", "");
2512 }
2513
2514 void reveal_mesh(EditMesh *em)
2515 {
2516         EditVert *eve;
2517         EditEdge *eed;
2518         EditFace *efa;
2519         
2520         if(em==NULL) return;
2521
2522         for(eve= em->verts.first; eve; eve= eve->next) {
2523                 if(eve->h) {
2524                         eve->h= 0;
2525                         eve->f |= SELECT;
2526                 }
2527         }
2528         for(eed= em->edges.first; eed; eed= eed->next) {
2529                 if(eed->h & 1) {
2530                         eed->h &= ~1;
2531                         if(em->selectmode & SCE_SELECT_VERTEX); 
2532                         else EM_select_edge(eed, 1);
2533                 }
2534         }
2535         for(efa= em->faces.first; efa; efa= efa->next) {
2536                 if(efa->h) {
2537                         efa->h= 0;
2538                         if(em->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_VERTEX)); 
2539                         else EM_select_face(efa, 1);
2540                 }
2541         }
2542
2543         EM_fgon_flags(em);      /* redo flags and indices for fgons */
2544         EM_selectmode_flush(em);
2545
2546 //      if (EM_texFaceCheck())
2547 //      DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); 
2548         BIF_undo_push("Reveal");
2549 }
2550
2551 static int reveal_mesh_exec(bContext *C, wmOperator *op)
2552 {
2553         Object *obedit= CTX_data_edit_object(C);
2554         EditMesh *em= ((Mesh *)obedit->data)->edit_mesh;
2555         
2556         reveal_mesh(em);
2557                 
2558         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
2559         return OPERATOR_FINISHED;       
2560 }
2561
2562 void MESH_OT_reveal_mesh(wmOperatorType *ot)
2563 {
2564         /* identifiers */
2565         ot->name= "Reveal the Mesh";
2566         ot->idname= "MESH_OT_reveal_mesh";
2567         
2568         /* api callbacks */
2569         ot->exec= reveal_mesh_exec;
2570         ot->poll= ED_operator_editmesh;
2571 }
2572
2573 void hide_tface_uv(EditMesh *em, int swap)
2574 {
2575 #if 0
2576         /* no space image here */
2577         EditFace *efa;
2578         MTFace *tface;
2579         
2580         if( is_uv_tface_editing_allowed()==0 ) return;
2581
2582         /* call the mesh function if we are in mesh sync sel */
2583         if (G.sima->flag & SI_SYNC_UVSEL) {
2584                 hide_mesh(swap);
2585                 return;
2586         }
2587         
2588         if(swap) {
2589                 for (efa= em->faces.first; efa; efa= efa->next) {
2590                         if(efa->f & SELECT) {
2591                                 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2592                                 if (G.sima->flag & SI_SELACTFACE) {
2593                                         /* Pretend face mode */
2594                                         if ((   (efa->v4==NULL && 
2595                                                         (       tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) ==                     (TF_SEL1|TF_SEL2|TF_SEL3) )                      ||
2596                                                         (       tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) ==     (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)       ) == 0) {
2597                                                 
2598                                                 if (em->selectmode == SCE_SELECT_FACE) {
2599                                                         efa->f &= ~SELECT;
2600                                                         /* must re-select after */
2601                                                         efa->e1->f &= ~SELECT;
2602                                                         efa->e2->f &= ~SELECT;
2603                                                         efa->e3->f &= ~SELECT;
2604                                                         if(efa->e4) efa->e4->f &= ~SELECT;
2605                                                 } else {
2606                                                         EM_select_face(efa, 0);
2607                                                 }
2608                                         }
2609                                         tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2610                                 } else if (em->selectmode == SCE_SELECT_FACE) {
2611                                         if((tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3))==0) {
2612                                                 if(!efa->v4)
2613                                                         EM_select_face(efa, 0);
2614                                                 else if(!(tface->flag & TF_SEL4))
2615                                                         EM_select_face(efa, 0);
2616                                                 tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2617                                         }
2618                                 } else {
2619                                         /* EM_deselect_flush will deselect the face */
2620                                         if((tface->flag & TF_SEL1)==0)                          efa->v1->f &= ~SELECT;
2621                                         if((tface->flag & TF_SEL2)==0)                          efa->v2->f &= ~SELECT;
2622                                         if((tface->flag & TF_SEL3)==0)                          efa->v3->f &= ~SELECT;
2623                                         if((efa->v4) && (tface->flag & TF_SEL4)==0)     efa->v4->f &= ~SELECT;                  
2624                                         tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2625                                 }
2626                         }
2627                 }
2628         } else {
2629                 for (efa= em->faces.first; efa; efa= efa->next) {
2630                         if(efa->f & SELECT) {
2631                                 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2632                                 if (G.sima->flag & SI_SELACTFACE) {
2633                                         if (    (efa->v4==NULL && 
2634                                                         (       tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) ==                     (TF_SEL1|TF_SEL2|TF_SEL3) )                      ||
2635                                                         (       tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) ==     (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)       ) {
2636                                                 
2637                                                 if (em->selectmode == SCE_SELECT_FACE) {
2638                                                         efa->f &= ~SELECT;
2639                                                         /* must re-select after */
2640                                                         efa->e1->f &= ~SELECT;
2641                                                         efa->e2->f &= ~SELECT;
2642                                                         efa->e3->f &= ~SELECT;
2643                                                         if(efa->e4) efa->e4->f &= ~SELECT;
2644                                                 } else {
2645                                                         EM_select_face(efa, 0);
2646                                                 }
2647                                         }
2648                                         tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2649                                 } else if (em->selectmode == SCE_SELECT_FACE) {
2650                                         if(tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
2651                                                 EM_select_face(efa, 0);
2652                                         else if(efa->v4 && tface->flag & TF_SEL4)
2653                                                 EM_select_face(efa, 0);
2654                                         tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2655                                 } else {
2656                                         /* EM_deselect_flush will deselect the face */
2657                                         if(tface->flag & TF_SEL1)                               efa->v1->f &= ~SELECT;
2658                                         if(tface->flag & TF_SEL2)                               efa->v2->f &= ~SELECT;
2659                                         if(tface->flag & TF_SEL3)                               efa->v3->f &= ~SELECT;
2660                                         if((efa->v4) && tface->flag & TF_SEL4)  efa->v4->f &= ~SELECT;
2661                                         tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2662                                 }
2663                         }
2664                 }
2665         }
2666         
2667         
2668         /*deselects too many but ok for now*/
2669         if(em->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_VERTEX)) {
2670                 EM_deselect_flush(em);
2671         }
2672         
2673         if (em->selectmode==SCE_SELECT_FACE) {
2674                 /* de-selected all edges from faces that were de-selected.
2675                  * now make sure all faces that are selected also have selected edges */
2676                 for (efa= em->faces.first; efa; efa= efa->next) {
2677                         if (efa->f & SELECT) {
2678                                 EM_select_face(efa, 1);
2679                         }
2680                 }
2681         }
2682         
2683         EM_validate_selections();
2684         
2685         BIF_undo_push("Hide UV");
2686
2687 // XXX  object_tface_flags_changed(OBACT, 0);
2688 #endif
2689 }
2690
2691 void reveal_tface_uv(EditMesh *em)
2692 {
2693 #if 0
2694         /* function should move away? */
2695         EditFace *efa;
2696         MTFace *tface;
2697
2698         if( is_uv_tface_editing_allowed()==0 ) return;
2699         
2700         /* call the mesh function if we are in mesh sync sel */
2701         if (G.sima->flag & SI_SYNC_UVSEL) {
2702                 reveal_mesh();
2703                 return;
2704         }
2705         
2706         if (G.sima->flag & SI_SELACTFACE) {
2707                 if (em->selectmode == SCE_SELECT_FACE) {
2708                         for (efa= em->faces.first; efa; efa= efa->next) {
2709                                 if (!(efa->h) && !(efa->f & SELECT)) {
2710                                         tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2711                                         EM_select_face(efa, 1);
2712                                         tface->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4;
2713                                 }
2714                         }
2715                 } else {
2716                         /* enable adjacent faces to have disconnected UV selections if sticky is disabled */
2717                         if (G.sima->sticky == SI_STICKY_DISABLE) {
2718                                 for (efa= em->faces.first; efa; efa= efa->next) {
2719                                         if (!(efa->h) && !(efa->f & SELECT)) {
2720                                                 /* All verts must be unselected for the face to be selected in the UV view */
2721                                                 if ((efa->v1->f&SELECT)==0 && (efa->v2->f&SELECT)==0 && (efa->v3->f&SELECT)==0 && (efa->v4==0 || (efa->v4->f&SELECT)==0)) {
2722                                                         tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2723                                                         tface->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4;
2724                                                         /* Cant use EM_select_face here because it unselects the verts
2725                                                          * and we cant tell if the face was totally unselected or not */
2726                                                         /*EM_select_face(efa, 1);
2727                                                          * 
2728                                                          * See Loop with EM_select_face() below... */
2729                                                         efa->f |= SELECT;
2730                                                 }
2731                                         }
2732                                 }
2733                         } else {
2734                                 for (efa= em->faces.first; efa; efa= efa->next) {
2735                                         if (!(efa->h) && !(efa->f & SELECT)) {
2736                                                 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2737                                                 if ((efa->v1->f & SELECT)==0)                           {tface->flag |= TF_SEL1;}
2738                                                 if ((efa->v2->f & SELECT)==0)                           {tface->flag |= TF_SEL2;}
2739                                                 if ((efa->v3->f & SELECT)==0)                           {tface->flag |= TF_SEL3;}
2740                                                 if ((efa->v4 && (efa->v4->f & SELECT)==0))      {tface->flag |= TF_SEL4;}
2741                                                 efa->f |= SELECT;
2742                                         }
2743                                 }
2744                         }
2745                         
2746                         /* Select all edges and verts now */
2747                         for (efa= em->faces.first; efa; efa= efa->next) {
2748                                 /* we only selected the face flags, and didnt changes edges or verts, fix this now */
2749                                 if (!(efa->h) && (efa->f & SELECT)) {
2750                                         EM_select_face(efa, 1);
2751                                 }
2752                         }
2753                         EM_select_flush(em);
2754                 }
2755         } else if (em->selectmode == SCE_SELECT_FACE) {
2756                 for (efa= em->faces.first; efa; efa= efa->next) {
2757                         if (!(efa->h) && !(efa->f & SELECT)) {
2758                                 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2759                                 efa->f |= SELECT;
2760                                 tface->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4;
2761                         }
2762                 }
2763                 
2764                 /* Select all edges and verts now */
2765                 for (efa= em->faces.first; efa; efa= efa->next) {
2766                         /* we only selected the face flags, and didnt changes edges or verts, fix this now */
2767                         if (!(efa->h) && (efa->f & SELECT)) {
2768                                 EM_select_face(efa, 1);
2769                         }
2770                 }
2771                 
2772         } else {
2773                 for (efa= em->faces.first; efa; efa= efa->next) {
2774                         if (!(efa->h) && !(efa->f & SELECT)) {
2775                                 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2776                                 if ((efa->v1->f & SELECT)==0)                           {tface->flag |= TF_SEL1;}
2777                                 if ((efa->v2->f & SELECT)==0)                           {tface->flag |= TF_SEL2;}
2778                                 if ((efa->v3->f & SELECT)==0)                           {tface->flag |= TF_SEL3;}
2779                                 if ((efa->v4 && (efa->v4->f & SELECT)==0))      {tface->flag |= TF_SEL4;}
2780                                 efa->f |= SELECT;
2781                         }
2782                 }
2783                 
2784                 /* Select all edges and verts now */
2785                 for (efa= em->faces.first; efa; efa= efa->next) {
2786                         /* we only selected the face flags, and didnt changes edges or verts, fix this now */
2787                         if (!(efa->h) && (efa->f & SELECT)) {
2788                                 EM_select_face(efa, 1);
2789                         }
2790                 }
2791         }
2792         
2793         BIF_undo_push("Reveal UV");
2794         
2795 // XXX  object_tface_flags_changed(OBACT, 0);
2796 #endif
2797 }
2798
2799 void select_faces_by_numverts(EditMesh *em, int numverts)
2800 {
2801         EditFace *efa;
2802
2803         /* Selects trias/qiads or isolated verts, and edges that do not have 2 neighboring
2804          * faces
2805          */
2806
2807         /* for loose vertices/edges, we first select all, loop below will deselect */
2808         if(numverts==5)
2809                 EM_set_flag_all(em, SELECT);
2810         else if(em->selectmode!=SCE_SELECT_FACE) {
2811                 error("Only works in face selection mode");
2812                 return;
2813         }
2814         
2815         for(efa= em->faces.first; efa; efa= efa->next) {
2816                 if (efa->e4) {
2817                         EM_select_face(efa, (numverts==4) );
2818                 }
2819                 else {
2820                         EM_select_face(efa, (numverts==3) );
2821                 }
2822         }
2823
2824 //      if (EM_texFaceCheck())
2825         
2826         if (numverts==3)
2827                 BIF_undo_push("Select Triangles");
2828         else if (numverts==4)
2829                 BIF_undo_push("Select Quads");
2830         else
2831                 BIF_undo_push("Select non-Triangles/Quads");
2832 }
2833
2834 void select_sharp_edges(EditMesh *em, float fsharpness)
2835 {
2836         /* Find edges that have exactly two neighboring faces,
2837          * check the angle between those faces, and if angle is
2838          * small enough, select the edge
2839          */
2840         EditEdge *eed;
2841         EditFace *efa;
2842         EditFace **efa1;
2843         EditFace **efa2;
2844         intptr_t edgecount = 0, i;
2845         static short sharpness = 135;
2846
2847         if(em->selectmode==SCE_SELECT_FACE) {
2848                 error("Doesn't work in face selection mode");
2849                 return;
2850         }
2851
2852 // XXX  if(button(&sharpness,0, 180,"Max Angle:")==0) return;
2853         /* if faces are at angle 'sharpness', then the face normals
2854          * are at angle 180.0 - 'sharpness' (convert to radians too)
2855          */
2856         fsharpness = ((180.0 - sharpness) * M_PI) / 180.0;
2857
2858         i=0;
2859         /* count edges, use tmp.l  */
2860         eed= em->edges.first;
2861         while(eed) {
2862                 edgecount++;
2863                 eed->tmp.l = i;
2864                 eed= eed->next;
2865                 ++i;
2866         }
2867
2868         /* for each edge, we want a pointer to two adjacent faces */
2869         efa1 = MEM_callocN(edgecount*sizeof(EditFace *), 
2870                                            "pairs of edit face pointers");
2871         efa2 = MEM_callocN(edgecount*sizeof(EditFace *), 
2872                                            "pairs of edit face pointers");
2873
2874 #define face_table_edge(eed) { \
2875                 i = eed->tmp.l; \
2876                 if (i != -1) { \
2877                         if (efa1[i]) { \
2878                                 if (efa2[i]) { \