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