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