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