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