remove unused args
[blender.git] / source / blender / editors / mesh / bmesh_select.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 BMEditMesh_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 "DNA_mesh_types.h"
43 #include "DNA_material_types.h"
44 #include "DNA_meshdata_types.h"
45 #include "DNA_modifier_types.h"
46 #include "DNA_object_types.h"
47 #include "DNA_texture_types.h"
48 #include "DNA_scene_types.h"
49 #include "DNA_screen_types.h"
50 #include "DNA_space_types.h"
51 #include "DNA_view3d_types.h"
52
53 #include "BLI_utildefines.h"
54 #include "BLI_blenlib.h"
55 #include "BLI_math.h"
56 #include "BLI_rand.h"
57 #include "BLI_array.h"
58 #include "BLI_smallhash.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_report.h"
70 #include "BKE_tessmesh.h"
71 #include "BKE_paint.h"
72
73 #include "IMB_imbuf_types.h"
74 #include "IMB_imbuf.h"
75
76 #include "RE_render_ext.h"  /* externtex */
77
78 #include "WM_api.h"
79 #include "WM_types.h"
80
81 #include "RNA_access.h"
82 #include "RNA_define.h"
83
84 #include "ED_mesh.h"
85 #include "ED_screen.h"
86 #include "ED_view3d.h"
87 #include "bmesh.h"
88
89 #include "BIF_gl.h"
90 #include "BIF_glutil.h"
91
92 #include "UI_resources.h"
93
94 #include "mesh_intern.h"
95
96 #include "BLO_sys_types.h" // for intptr_t support
97
98 /* ****************************** MIRROR **************** */
99
100 static void EDBM_select_mirrored(Object *obedit, BMEditMesh *em)
101 {
102         if(em->selectmode & SCE_SELECT_VERTEX) {
103                 BMVert *eve, *v1;
104                 BMIter iter;
105                 int i;
106
107                 i= 0;
108                 BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
109                         if (BM_TestHFlag(eve, BM_SELECT) && !BM_TestHFlag(eve, BM_HIDDEN)) {
110                                 v1= editbmesh_get_x_mirror_vert(obedit, em, eve, eve->co, i);
111                                 if(v1) {
112                                         BM_Select(em->bm, eve, 0);
113                                         BM_Select(em->bm, v1, 1);
114                                 }
115                         }
116                         i++;
117                 }
118         }
119 }
120
121 void EDBM_automerge(Scene *scene, Object *obedit, int update)
122 {
123         BMEditMesh *em;
124         
125         if ((scene->toolsettings->automerge) &&
126             (obedit && obedit->type==OB_MESH))
127         {
128                 em = ((Mesh*)obedit->data)->edit_btmesh;
129                 if (!em)
130                         return;
131
132                 BMO_CallOpf(em->bm, "automerge verts=%hv dist=%f", BM_SELECT, scene->toolsettings->doublimit);
133                 if (update) {
134                         DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
135                 }
136         }
137 }
138
139 /* ****************************** SELECTION ROUTINES **************** */
140
141 unsigned int bm_solidoffs=0, bm_wireoffs=0, bm_vertoffs=0;      /* set in drawobject.c ... for colorindices */
142
143 /* facilities for border select and circle select */
144 static char *selbuf= NULL;
145
146 /* opengl doesn't support concave... */
147 static void draw_triangulated(int mcords[][2], short tot)
148 {
149         ListBase lb={NULL, NULL};
150         DispList *dl;
151         float *fp;
152         int a;
153         
154         /* make displist */
155         dl= MEM_callocN(sizeof(DispList), "poly disp");
156         dl->type= DL_POLY;
157         dl->parts= 1;
158         dl->nr= tot;
159         dl->verts= fp=  MEM_callocN(tot*3*sizeof(float), "poly verts");
160         BLI_addtail(&lb, dl);
161         
162         for(a=0; a<tot; a++, fp+=3) {
163                 fp[0]= (float)mcords[a][0];
164                 fp[1]= (float)mcords[a][1];
165         }
166         
167         /* do the fill */
168         filldisplist(&lb, &lb, 0);
169
170         /* do the draw */
171         dl= lb.first;   /* filldisplist adds in head of list */
172         if(dl->type==DL_INDEX3) {
173                 int *index;
174                 
175                 a= dl->parts;
176                 fp= dl->verts;
177                 index= dl->index;
178                 glBegin(GL_TRIANGLES);
179                 while(a--) {
180                         glVertex3fv(fp+3*index[0]);
181                         glVertex3fv(fp+3*index[1]);
182                         glVertex3fv(fp+3*index[2]);
183                         index+= 3;
184                 }
185                 glEnd();
186         }
187         
188         freedisplist(&lb);
189 }
190
191
192 /* reads rect, and builds selection array for quick lookup */
193 /* returns if all is OK */
194 int EDBM_init_backbuf_border(ViewContext *vc, short xmin, short ymin, short xmax, short ymax)
195 {
196         struct ImBuf *buf;
197         unsigned int *dr;
198         int a;
199         
200         if(vc->obedit==NULL || vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
201         
202         buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
203         if(buf==NULL) return 0;
204         if(bm_vertoffs==0) return 0;
205
206         dr = buf->rect;
207         
208         /* build selection lookup */
209         selbuf= MEM_callocN(bm_vertoffs+1, "selbuf");
210         
211         a= (xmax-xmin+1)*(ymax-ymin+1);
212         while(a--) {
213                 if(*dr>0 && *dr<=bm_vertoffs) 
214                         selbuf[*dr]= 1;
215                 dr++;
216         }
217         IMB_freeImBuf(buf);
218         return 1;
219 }
220
221 int EDBM_check_backbuf(unsigned int index)
222 {
223         if(selbuf==NULL) return 1;
224         if(index>0 && index<=bm_vertoffs)
225                 return selbuf[index];
226         return 0;
227 }
228
229 void EDBM_free_backbuf(void)
230 {
231         if(selbuf) MEM_freeN(selbuf);
232         selbuf= NULL;
233 }
234
235 /* mcords is a polygon mask
236    - grab backbuffer,
237    - draw with black in backbuffer, 
238    - grab again and compare
239    returns 'OK' 
240 */
241 int EDBM_mask_init_backbuf_border(ViewContext *vc, int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax)
242 {
243         unsigned int *dr, *drm;
244         struct ImBuf *buf, *bufmask;
245         int a;
246         
247         /* method in use for face selecting too */
248         if(vc->obedit==NULL) {
249                 if(paint_facesel_test(vc->obact));
250                 else return 0;
251         }
252         else if(vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
253
254         buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
255         if(buf==NULL) return 0;
256         if(bm_vertoffs==0) return 0;
257
258         dr = buf->rect;
259
260         /* draw the mask */
261         glDisable(GL_DEPTH_TEST);
262         
263         glColor3ub(0, 0, 0);
264         
265         /* yah, opengl doesn't do concave... tsk! */
266         ED_region_pixelspace(vc->ar);
267         draw_triangulated(mcords, tot); 
268         
269         glBegin(GL_LINE_LOOP);  /* for zero sized masks, lines */
270         for(a=0; a<tot; a++) glVertex2iv(mcords[a]);
271         glEnd();
272         
273         glFinish();     /* to be sure readpixels sees mask */
274         
275         /* grab mask */
276         bufmask= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
277         drm = bufmask->rect;
278         if(bufmask==NULL) return 0; /* only when mem alloc fails, go crash somewhere else! */
279         
280         /* build selection lookup */
281         selbuf= MEM_callocN(bm_vertoffs+1, "selbuf");
282         
283         a= (xmax-xmin+1)*(ymax-ymin+1);
284         while(a--) {
285                 if(*dr>0 && *dr<=bm_vertoffs && *drm==0) selbuf[*dr]= 1;
286                 dr++; drm++;
287         }
288         IMB_freeImBuf(buf);
289         IMB_freeImBuf(bufmask);
290         return 1;
291         
292 }
293
294 /* circle shaped sample area */
295 int EDBM_init_backbuf_circle(ViewContext *vc, short xs, short ys, short rads)
296 {
297         struct ImBuf *buf;
298         unsigned int *dr;
299         short xmin, ymin, xmax, ymax, xc, yc;
300         int radsq;
301         
302         /* method in use for face selecting too */
303         if(vc->obedit==NULL) {
304                 if(paint_facesel_test(vc->obact));
305                 else return 0;
306         }
307         else if(vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
308         
309         xmin= xs-rads; xmax= xs+rads;
310         ymin= ys-rads; ymax= ys+rads;
311         buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
312         if(bm_vertoffs==0) return 0;
313         if(buf==NULL) return 0;
314
315         dr = buf->rect;
316         
317         /* build selection lookup */
318         selbuf= MEM_callocN(bm_vertoffs+1, "selbuf");
319         radsq= rads*rads;
320         for(yc= -rads; yc<=rads; yc++) {
321                 for(xc= -rads; xc<=rads; xc++, dr++) {
322                         if(xc*xc + yc*yc < radsq) {
323                                 if(*dr>0 && *dr<=bm_vertoffs) selbuf[*dr]= 1;
324                         }
325                 }
326         }
327
328         IMB_freeImBuf(buf);
329         return 1;
330         
331 }
332
333 static void findnearestvert__doClosest(void *userData, BMVert *eve, int x, int y, int index)
334 {
335         struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; BMVert *closest; } *data = userData;
336
337         if (data->pass==0) {
338                 if (index<=data->lastIndex)
339                         return;
340         } else {
341                 if (index>data->lastIndex)
342                         return;
343         }
344
345         if (data->dist>3) {
346                 int temp = abs(data->mval[0] - x) + abs(data->mval[1]- y);
347                 if (BM_TestHFlag(eve, BM_SELECT) == data->select) {
348                         if (data->strict == 1)
349                                 return;
350                         else
351                                 temp += 5;
352                 }
353
354                 if (temp<data->dist) {
355                         data->dist = temp;
356                         data->closest = eve;
357                         data->closestIndex = index;
358                 }
359         }
360 }
361
362
363
364
365 static unsigned int findnearestvert__backbufIndextest(void *handle, unsigned int index)
366 {
367         BMEditMesh *em= (BMEditMesh *)handle;
368         BMVert *eve = BMIter_AtIndex(em->bm, BM_VERTS_OF_MESH, NULL, index-1);
369
370         if(eve && BM_TestHFlag(eve, BM_SELECT)) return 0;
371         return 1; 
372 }
373 /**
374  * findnearestvert
375  * 
376  * dist (in/out): minimal distance to the nearest and at the end, actual distance
377  * sel: selection bias
378  *              if SELECT, selected vertice are given a 5 pixel bias to make them farter than unselect verts
379  *              if 0, unselected vertice are given the bias
380  * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased 
381  */
382 BMVert *EDBM_findnearestvert(ViewContext *vc, int *dist, short sel, short strict)
383 {
384         if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)){
385                 int distance;
386                 unsigned int index;
387                 BMVert *eve;
388                 
389                 if(strict) index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_wireoffs, 0xFFFFFF, &distance, strict, vc->em, findnearestvert__backbufIndextest); 
390                 else index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_wireoffs, 0xFFFFFF, &distance, 0, NULL, NULL); 
391                 
392                 eve = BMIter_AtIndex(vc->em->bm, BM_VERTS_OF_MESH, NULL, index-1);
393                 
394                 if(eve && distance < *dist) {
395                         *dist = distance;
396                         return eve;
397                 } else {
398                         return NULL;
399                 }
400                         
401         }
402         else {
403                 struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; BMVert *closest; } data;
404                 static int lastSelectedIndex=0;
405                 static BMVert *lastSelected=NULL;
406                 
407                 if (lastSelected && BMIter_AtIndex(vc->em->bm, BM_VERTS_OF_MESH, NULL, lastSelectedIndex)!=lastSelected) {
408                         lastSelectedIndex = 0;
409                         lastSelected = NULL;
410                 }
411
412                 data.lastIndex = lastSelectedIndex;
413                 data.mval[0] = vc->mval[0];
414                 data.mval[1] = vc->mval[1];
415                 data.select = sel;
416                 data.dist = *dist;
417                 data.strict = strict;
418                 data.closest = NULL;
419                 data.closestIndex = 0;
420
421                 data.pass = 0;
422
423                 ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
424
425                 mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, 1);
426
427                 if (data.dist>3) {
428                         data.pass = 1;
429                         mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, 1);
430                 }
431
432                 *dist = data.dist;
433                 lastSelected = data.closest;
434                 lastSelectedIndex = data.closestIndex;
435
436                 return data.closest;
437         }
438 }
439
440 /* returns labda for closest distance v1 to line-piece v2-v3 */
441 float labda_PdistVL2Dfl(const float v1[3], const float v2[3], const float v3[3])
442 {
443         float rc[2], len;
444         
445         rc[0]= v3[0]-v2[0];
446         rc[1]= v3[1]-v2[1];
447         len= rc[0]*rc[0]+ rc[1]*rc[1];
448         if(len==0.0f)
449                 return 0.0f;
450         
451         return ( rc[0]*(v1[0]-v2[0]) + rc[1]*(v1[1]-v2[1]) )/len;
452 }
453
454 /* note; uses v3d, so needs active 3d window */
455 static void findnearestedge__doClosest(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int UNUSED(index))
456 {
457         struct { ViewContext vc; float mval[2]; int dist; BMEdge *closest; } *data = userData;
458         float v1[2], v2[2];
459         int distance;
460                 
461         v1[0] = x0;
462         v1[1] = y0;
463         v2[0] = x1;
464         v2[1] = y1;
465                 
466         distance= dist_to_line_segment_v2(data->mval, v1, v2);
467                 
468         if(BM_TestHFlag(eed, BM_SELECT)) distance+=5;
469         if(distance < data->dist) {
470                 if(data->vc.rv3d->rflag & RV3D_CLIPPING) {
471                         float labda= labda_PdistVL2Dfl(data->mval, v1, v2);
472                         float vec[3];
473
474                         vec[0]= eed->v1->co[0] + labda*(eed->v2->co[0] - eed->v1->co[0]);
475                         vec[1]= eed->v1->co[1] + labda*(eed->v2->co[1] - eed->v1->co[1]);
476                         vec[2]= eed->v1->co[2] + labda*(eed->v2->co[2] - eed->v1->co[2]);
477                         mul_m4_v3(data->vc.obedit->obmat, vec);
478
479                         if(ED_view3d_test_clipping(data->vc.rv3d, vec, 1)==0) {
480                                 data->dist = distance;
481                                 data->closest = eed;
482                         }
483                 }
484                 else {
485                         data->dist = distance;
486                         data->closest = eed;
487                 }
488         }
489 }
490 BMEdge *EDBM_findnearestedge(ViewContext *vc, int *dist)
491 {
492
493         if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
494                 int distance;
495                 unsigned int index;
496                 BMEdge *eed;
497                 
498                 view3d_validate_backbuf(vc);
499                 
500                 index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_solidoffs, bm_wireoffs, &distance,0, NULL, NULL);
501                 eed = BMIter_AtIndex(vc->em->bm, BM_EDGES_OF_MESH, NULL, index-1);
502                 
503                 if (eed && distance<*dist) {
504                         *dist = distance;
505                         return eed;
506                 } else {
507                         return NULL;
508                 }
509         }
510         else {
511                 struct { ViewContext vc; float mval[2]; int dist; BMEdge *closest; } data;
512
513                 data.vc= *vc;
514                 data.mval[0] = vc->mval[0];
515                 data.mval[1] = vc->mval[1];
516                 data.dist = *dist;
517                 data.closest = NULL;
518                 ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
519
520                 mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, 2);
521
522                 *dist = data.dist;
523                 return data.closest;
524         }
525 }
526
527 static void findnearestface__getDistance(void *userData, BMFace *efa, int x, int y, int UNUSED(index))
528 {
529         struct { short mval[2]; int dist; BMFace *toFace; } *data = userData;
530
531         if (efa==data->toFace) {
532                 int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
533
534                 if (temp<data->dist)
535                         data->dist = temp;
536         }
537 }
538 static void findnearestface__doClosest(void *userData, BMFace *efa, int x, int y, int index)
539 {
540         struct { short mval[2], pass; int dist, lastIndex, closestIndex; BMFace *closest; } *data = userData;
541
542         if (data->pass==0) {
543                 if (index<=data->lastIndex)
544                         return;
545         } else {
546                 if (index>data->lastIndex)
547                         return;
548         }
549
550         if (data->dist>3) {
551                 int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
552
553                 if (temp<data->dist) {
554                         data->dist = temp;
555                         data->closest = efa;
556                         data->closestIndex = index;
557                 }
558         }
559 }
560
561 BMFace *EDBM_findnearestface(ViewContext *vc, int *dist)
562 {
563
564         if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
565                 unsigned int index;
566                 BMFace *efa;
567
568                 view3d_validate_backbuf(vc);
569
570                 index = view3d_sample_backbuf(vc, vc->mval[0], vc->mval[1]);
571                 efa = BMIter_AtIndex(vc->em->bm, BM_FACES_OF_MESH, NULL, index-1);
572                 
573                 if (efa) {
574                         struct { short mval[2]; int dist; BMFace *toFace; } data;
575
576                         data.mval[0] = vc->mval[0];
577                         data.mval[1] = vc->mval[1];
578                         data.dist = 0x7FFF;             /* largest short */
579                         data.toFace = efa;
580
581                         mesh_foreachScreenFace(vc, findnearestface__getDistance, &data);
582
583                         if(vc->em->selectmode == SCE_SELECT_FACE || data.dist<*dist) {  /* only faces, no dist check */
584                                 *dist= data.dist;
585                                 return efa;
586                         }
587                 }
588                 
589                 return NULL;
590         }
591         else {
592                 struct { short mval[2], pass; int dist, lastIndex, closestIndex; BMFace *closest; } data;
593                 static int lastSelectedIndex=0;
594                 static BMFace *lastSelected=NULL;
595
596                 if (lastSelected && BMIter_AtIndex(vc->em->bm, BM_FACES_OF_MESH, NULL, lastSelectedIndex)!=lastSelected) {
597                         lastSelectedIndex = 0;
598                         lastSelected = NULL;
599                 }
600
601                 data.lastIndex = lastSelectedIndex;
602                 data.mval[0] = vc->mval[0];
603                 data.mval[1] = vc->mval[1];
604                 data.dist = *dist;
605                 data.closest = NULL;
606                 data.closestIndex = 0;
607                 ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
608
609                 data.pass = 0;
610                 mesh_foreachScreenFace(vc, findnearestface__doClosest, &data);
611
612                 if (data.dist>3) {
613                         data.pass = 1;
614                         ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
615                         mesh_foreachScreenFace(vc, findnearestface__doClosest, &data);
616                 }
617
618                 *dist = data.dist;
619                 lastSelected = data.closest;
620                 lastSelectedIndex = data.closestIndex;
621
622                 return data.closest;
623         }
624 }
625
626 /* best distance based on screen coords. 
627    use em->selectmode to define how to use 
628    selected vertices and edges get disadvantage
629    return 1 if found one
630 */
631 static int unified_findnearest(ViewContext *vc, BMVert **eve, BMEdge **eed, BMFace **efa) 
632 {
633         BMEditMesh *em= vc->em;
634         int dist= 75;
635         
636         *eve= NULL;
637         *eed= NULL;
638         *efa= NULL;
639         
640         /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
641         view3d_validate_backbuf(vc);
642         
643         if(em->selectmode & SCE_SELECT_VERTEX)
644                 *eve= EDBM_findnearestvert(vc, &dist, BM_SELECT, 0);
645         if(em->selectmode & SCE_SELECT_FACE)
646                 *efa= EDBM_findnearestface(vc, &dist);
647
648         dist-= 20;      /* since edges select lines, we give dots advantage of 20 pix */
649         if(em->selectmode & SCE_SELECT_EDGE)
650                 *eed= EDBM_findnearestedge(vc, &dist);
651
652         /* return only one of 3 pointers, for frontbuffer redraws */
653         if(*eed) {
654                 *efa= NULL; *eve= NULL;
655         }
656         else if(*efa) {
657                 *eve= NULL;
658         }
659         
660         return (*eve || *eed || *efa);
661 }
662
663 /* ****************  SIMILAR "group" SELECTS. FACE, EDGE AND VERTEX ************** */
664
665 static EnumPropertyItem prop_similar_types[] = {
666         {SIMVERT_NORMAL, "NORMAL", 0, "Normal", ""},
667         {SIMVERT_FACE, "FACE", 0, "Amount of Adjacent Faces", ""},
668         {SIMVERT_VGROUP, "VGROUP", 0, "Vertex Groups", ""},
669
670         {SIMEDGE_LENGTH, "LENGTH", 0, "Length", ""},
671         {SIMEDGE_DIR, "DIR", 0, "Direction", ""},
672         {SIMEDGE_FACE, "FACE", 0, "Amount of Faces Around an Edge", ""},
673         {SIMEDGE_FACE_ANGLE, "FACE_ANGLE", 0, "Face Angles", ""},
674         {SIMEDGE_CREASE, "CREASE", 0, "Crease", ""},
675         {SIMEDGE_SEAM, "SEAM", 0, "Seam", ""},
676         {SIMEDGE_SHARP, "SHARP", 0, "Sharpness", ""},
677
678         {SIMFACE_MATERIAL, "MATERIAL", 0, "Material", ""},
679         {SIMFACE_IMAGE, "IMAGE", 0, "Image", ""},
680         {SIMFACE_AREA, "AREA", 0, "Area", ""},
681         {SIMFACE_PERIMETER, "PERIMETER", 0, "Perimeter", ""},
682         {SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""},
683         {SIMFACE_COPLANAR, "COPLANAR", 0, "Co-planar", ""},
684
685         {0, NULL, 0, NULL, NULL}
686 };
687
688 /* selects new faces/edges/verts based on the existing selection */
689
690 static int similar_face_select_exec(bContext *C, wmOperator *op)
691 {
692         Object *ob = CTX_data_edit_object(C);
693         BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
694         BMOperator bmop;
695
696         /* get the type from RNA */
697         int type = RNA_enum_get(op->ptr, "type");
698
699         float thresh = CTX_data_tool_settings(C)->select_thresh;
700
701         /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
702         EDBM_InitOpf(em, &bmop, op, "similarfaces faces=%hf type=%d thresh=%f", BM_SELECT, type, thresh);
703
704         /* execute the operator */
705         BMO_Exec_Op(em->bm, &bmop);
706
707         /* clear the existing selection */
708         EDBM_clear_flag_all(em, BM_SELECT);
709
710         /* select the output */
711         BMO_HeaderFlag_Buffer(em->bm, &bmop, "faceout", BM_SELECT, BM_ALL);
712
713         /* finish the operator */
714         if( !EDBM_FinishOp(em, &bmop, op, 1) )
715                 return OPERATOR_CANCELLED;
716
717         /* dependencies graph and notification stuff */
718         DAG_id_tag_update(ob->data, OB_RECALC_DATA);
719         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
720
721         /* we succeeded */
722         return OPERATOR_FINISHED;
723 }       
724
725 /* ***************************************************** */
726
727 /* EDGE GROUP */
728
729 /* wrap the above function but do selection flushing edge to face */
730 static int similar_edge_select_exec(bContext *C, wmOperator *op)
731 {
732         Object *ob = CTX_data_edit_object(C);
733         BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
734         BMOperator bmop;
735
736         /* get the type from RNA */
737         int type = RNA_enum_get(op->ptr, "type");
738
739         float thresh = CTX_data_tool_settings(C)->select_thresh;
740
741         /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
742         EDBM_InitOpf(em, &bmop, op, "similaredges edges=%he type=%d thresh=%f", BM_SELECT, type, thresh);
743
744         /* execute the operator */
745         BMO_Exec_Op(em->bm, &bmop);
746
747         /* clear the existing selection */
748         EDBM_clear_flag_all(em, BM_SELECT);
749
750         /* select the output */
751         BMO_HeaderFlag_Buffer(em->bm, &bmop, "edgeout", BM_SELECT, BM_ALL);
752         EDBM_selectmode_flush(em);
753
754         /* finish the operator */
755         if( !EDBM_FinishOp(em, &bmop, op, 1) )
756                 return OPERATOR_CANCELLED;
757
758         /* dependencies graph and notification stuff */
759         DAG_id_tag_update(ob->data, OB_RECALC_DATA);
760         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
761
762         /* we succeeded */
763         return OPERATOR_FINISHED;
764 }
765
766 /* ********************************* */
767
768 /*
769 VERT GROUP
770  mode 1: same normal
771  mode 2: same number of face users
772  mode 3: same vertex groups
773 */
774
775
776 static int similar_vert_select_exec(bContext *C, wmOperator *op)
777 {
778         Object *ob = CTX_data_edit_object(C);
779         BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
780         BMOperator bmop;
781         /* get the type from RNA */
782         int type = RNA_enum_get(op->ptr, "type");
783         float thresh = CTX_data_tool_settings(C)->select_thresh;
784
785         /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
786         EDBM_InitOpf(em, &bmop, op, "similarverts verts=%hv type=%d thresh=%f", BM_SELECT, type, thresh);
787
788         /* execute the operator */
789         BMO_Exec_Op(em->bm, &bmop);
790
791         /* clear the existing selection */
792         EDBM_clear_flag_all(em, BM_SELECT);
793
794         /* select the output */
795         BMO_HeaderFlag_Buffer(em->bm, &bmop, "vertout", BM_SELECT, BM_ALL);
796
797         /* finish the operator */
798         if( !EDBM_FinishOp(em, &bmop, op, 1) )
799                 return OPERATOR_CANCELLED;
800
801         EDBM_selectmode_flush(em);
802
803         /* dependencies graph and notification stuff */
804         DAG_id_tag_update(ob->data, OB_RECALC_DATA);
805         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
806
807         /* we succeeded */
808         return OPERATOR_FINISHED;
809 }
810
811 static int select_similar_exec(bContext *C, wmOperator *op)
812 {
813         int type= RNA_enum_get(op->ptr, "type");
814
815         if(type < 100)
816                 return similar_vert_select_exec(C, op);
817         else if(type < 200)
818                 return similar_edge_select_exec(C, op);
819         else
820                 return similar_face_select_exec(C, op);
821 }
822
823 static EnumPropertyItem *select_similar_type_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
824 {
825         Object *obedit = CTX_data_edit_object(C);
826         EnumPropertyItem *item= NULL;
827         int a, totitem= 0;
828         
829         if(obedit && obedit->type == OB_MESH) {
830                 BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh; 
831
832                 if(em->selectmode & SCE_SELECT_VERTEX) {
833                         for (a=SIMVERT_NORMAL; a<SIMEDGE_LENGTH; a++) {
834                                 RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
835                         }
836                 } else if(em->selectmode & SCE_SELECT_EDGE) {
837                         for (a=SIMEDGE_LENGTH; a<SIMFACE_MATERIAL; a++) {
838                                 RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
839                         }
840                 } else if(em->selectmode & SCE_SELECT_FACE) {
841                         for (a=SIMFACE_MATERIAL; a<=SIMFACE_COPLANAR; a++) {
842                                 RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
843                         }
844                 }
845                 RNA_enum_item_end(&item, &totitem);
846
847                 *free= 1;
848
849                 return item;
850         }
851         
852         return NULL;
853 }
854
855 void MESH_OT_select_similar(wmOperatorType *ot)
856 {
857         PropertyRNA *prop;
858
859         /* identifiers */
860         ot->name= "Select Similar";
861         ot->idname= "MESH_OT_select_similar";
862         
863         /* api callbacks */
864         ot->invoke= WM_menu_invoke;
865         ot->exec= select_similar_exec;
866         ot->poll= ED_operator_editmesh;
867         ot->description= "Select similar vertices, edges or faces by property types.";
868         
869         /* flags */
870         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
871         
872         /* properties */
873         prop= ot->prop= RNA_def_enum(ot->srna, "type", prop_similar_types, SIMVERT_NORMAL, "Type", "");
874         RNA_def_enum_funcs(prop, select_similar_type_itemf);
875 }
876
877 /* ***************************************************** */
878
879 /* ****************  LOOP SELECTS *************** */
880 /*faceloop_select, edgeloop_select, and edgering_select, are left
881   here for reference purposes temporarily, but have all been replaced
882   by uses of walker_select.*/
883
884 static void walker_select(BMEditMesh *em, int walkercode, void *start, int select)
885 {
886         BMesh *bm = em->bm;
887         BMHeader *h;
888         BMWalker walker;
889
890         BMW_Init(&walker, bm, walkercode, 0, 0);
891         h = BMW_Begin(&walker, start);
892         for (; h; h=BMW_Step(&walker)) {
893                 BM_Select(bm, h, select);
894         }
895         BMW_End(&walker);
896 }
897
898 static int loop_multiselect(bContext *C, wmOperator *op)
899 {
900         Object *obedit= CTX_data_edit_object(C);
901         BMEditMesh *em = ((Mesh*)obedit->data)->edit_btmesh;
902         BMEdge *eed;
903         BMEdge **edarray;
904         int edindex;
905         int looptype= RNA_boolean_get(op->ptr, "ring");
906         
907         BMIter iter;
908         int totedgesel = 0;
909
910         for(eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
911             eed; eed = BMIter_Step(&iter)){
912
913                 if(BM_TestHFlag(eed, BM_SELECT)){
914                         totedgesel++;
915                 }
916         }
917
918         
919         edarray = MEM_mallocN(sizeof(BMEdge*)*totedgesel,"edge array");
920         edindex = 0;
921         
922         for(eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
923             eed; eed = BMIter_Step(&iter)){
924
925                 if(BM_TestHFlag(eed, BM_SELECT)){
926                         edarray[edindex] = eed;
927                         edindex++;
928                 }
929         }
930         
931         if(looptype){
932                 for(edindex = 0; edindex < totedgesel; edindex +=1){
933                         eed = edarray[edindex];
934                         walker_select(em, BMW_EDGERING, eed, 1);
935                 }
936                 EDBM_selectmode_flush(em);
937         }
938         else{
939                 for(edindex = 0; edindex < totedgesel; edindex +=1){
940                         eed = edarray[edindex];
941                         walker_select(em, BMW_LOOP, eed, 1);
942                 }
943                 EDBM_selectmode_flush(em);
944         }
945         MEM_freeN(edarray);
946 //      if (EM_texFaceCheck())
947         
948         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
949
950         return OPERATOR_FINISHED;       
951 }
952
953 void MESH_OT_loop_multi_select(wmOperatorType *ot)
954 {
955         /* identifiers */
956         ot->name= "Multi Select Loops";
957         ot->idname= "MESH_OT_loop_multi_select";
958         
959         /* api callbacks */
960         ot->exec= loop_multiselect;
961         ot->poll= ED_operator_editmesh;
962         ot->description= "Select a loop of connected edges by connection type.";
963         
964         /* flags */
965         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
966         
967         /* properties */
968         RNA_def_boolean(ot->srna, "ring", 0, "Ring", "");
969 }
970
971                 
972 /* ***************** MAIN MOUSE SELECTION ************** */
973
974
975 /* ***************** loop select (non modal) ************** */
976
977 static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short ring)
978 {
979         ViewContext vc;
980         BMEditMesh *em;
981         BMEdge *eed;
982         int select= 1;
983         int dist= 50;
984         
985         em_setup_viewcontext(C, &vc);
986         vc.mval[0]= mval[0];
987         vc.mval[1]= mval[1];
988         em= vc.em;
989         
990         /* no afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad */
991         view3d_validate_backbuf(&vc);
992
993         eed= EDBM_findnearestedge(&vc, &dist);
994         if(eed) {
995                 if(extend==0) EDBM_clear_flag_all(em, BM_SELECT);
996         
997                 if(BM_TestHFlag(em, BM_SELECT)==0) select=1;
998                 else if(extend) select=0;
999
1000                 if(em->selectmode & SCE_SELECT_FACE) {
1001                         walker_select(em, BMW_FACELOOP, eed, select);
1002                 }
1003                 else if(em->selectmode & SCE_SELECT_EDGE) {
1004                         if(ring)
1005                                 walker_select(em, BMW_EDGERING, eed, select);
1006                         else
1007                                 walker_select(em, BMW_LOOP, eed, select);
1008                 }
1009                 else if(em->selectmode & SCE_SELECT_VERTEX) {
1010                         if(ring)
1011                                 walker_select(em, BMW_EDGERING, eed, select);
1012                         else 
1013                                 walker_select(em, BMW_LOOP, eed, select);
1014                 }
1015
1016                 EDBM_selectmode_flush(em);
1017 //                      if (EM_texFaceCheck())
1018                 
1019                 /* sets as active, useful for other tools */
1020                 if(select && em->selectmode & SCE_SELECT_EDGE) {
1021                         EDBM_store_selection(em, eed);
1022                 }
1023
1024                 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, vc.obedit);
1025         }
1026 }
1027
1028 static int mesh_select_loop_invoke(bContext *C, wmOperator *op, wmEvent *event)
1029 {
1030         
1031         view3d_operator_needs_opengl(C);
1032         
1033         mouse_mesh_loop(C, event->mval, RNA_boolean_get(op->ptr, "extend"),
1034                                         RNA_boolean_get(op->ptr, "ring"));
1035         
1036         /* cannot do tweaks for as long this keymap is after transform map */
1037         return OPERATOR_FINISHED;
1038 }
1039
1040 void MESH_OT_loop_select(wmOperatorType *ot)
1041 {
1042         /* identifiers */
1043         ot->name= "Loop Select";
1044         ot->idname= "MESH_OT_loop_select";
1045         
1046         /* api callbacks */
1047         ot->invoke= mesh_select_loop_invoke;
1048         ot->poll= ED_operator_editmesh;
1049         ot->description= "Select a loop of connected edges.";
1050         
1051         /* flags */
1052         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1053         
1054         /* properties */
1055         RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
1056         RNA_def_boolean(ot->srna, "ring", 0, "Select Ring", "");
1057 }
1058
1059 /* ******************* mesh shortest path select, uses prev-selected edge ****************** */
1060
1061 /* since you want to create paths with multiple selects, it doesn't have extend option */
1062 static void mouse_mesh_shortest_path(bContext *UNUSED(C), int UNUSED(mval[2]))
1063 {
1064 #if 0 //BMESH_TODO
1065         ViewContext vc;
1066         BMEditMesh *em;
1067         BMEdge *eed;
1068         int dist= 50;
1069         
1070         em_setup_viewcontext(C, &vc);
1071         vc.mval[0]= mval[0];
1072         vc.mval[1]= mval[1];
1073         em= vc.em;
1074         
1075         eed= findnearestedge(&vc, &dist);
1076         if(eed) {
1077                 Mesh *me= vc.obedit->data;
1078                 int path = 0;
1079                 
1080                 if (em->bm->selected.last) {
1081                         EditSelection *ese = em->bm->selected.last;
1082                         
1083                         if(ese && ese->type == BMEdge) {
1084                                 BMEdge *eed_act;
1085                                 eed_act = (BMEdge*)ese->data;
1086                                 if (eed_act != eed) {
1087                                         if (edgetag_shortest_path(vc.scene, em, eed_act, eed)) {
1088                                                 EM_remove_selection(em, eed_act, BMEdge);
1089                                                 path = 1;
1090                                         }
1091                                 }
1092                         }
1093                 }
1094                 if (path==0) {
1095                         int act = (edgetag_context_check(vc.scene, eed)==0);
1096                         edgetag_context_set(em, vc.scene, eed, act); /* switch the edge option */
1097                 }
1098                 
1099                 EM_selectmode_flush(em);
1100
1101                 /* even if this is selected it may not be in the selection list */
1102                 if(edgetag_context_check(vc.scene, eed)==0)
1103                         EDBM_remove_selection(em, eed);
1104                 else
1105                         EDBM_store_selection(em, eed);
1106         
1107                 /* force drawmode for mesh */
1108                 switch (CTX_data_tool_settings(C)->edge_mode) {
1109                         
1110                         case EDGE_MODE_TAG_SEAM:
1111                                 me->drawflag |= ME_DRAWSEAMS;
1112                                 break;
1113                         case EDGE_MODE_TAG_SHARP:
1114                                 me->drawflag |= ME_DRAWSHARP;
1115                                 break;
1116                         case EDGE_MODE_TAG_CREASE:      
1117                                 me->drawflag |= ME_DRAWCREASES;
1118                                 break;
1119                         case EDGE_MODE_TAG_BEVEL:
1120                                 me->drawflag |= ME_DRAWBWEIGHTS;
1121                                 break;
1122                 }
1123                 
1124                 DAG_id_tag_update(ob->data, OB_RECALC_DATA);
1125                 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
1126         }
1127 #endif
1128 }
1129
1130
1131 static int mesh_shortest_path_select_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
1132 {
1133         
1134         view3d_operator_needs_opengl(C);
1135
1136         mouse_mesh_shortest_path(C, event->mval);
1137         
1138         return OPERATOR_FINISHED;
1139 }
1140         
1141 void MESH_OT_select_shortest_path(wmOperatorType *ot)
1142 {
1143         /* identifiers */
1144         ot->name= "Shortest Path Select";
1145         ot->idname= "MESH_OT_select_shortest_path";
1146         
1147         /* api callbacks */
1148         ot->invoke= mesh_shortest_path_select_invoke;
1149         ot->poll= ED_operator_editmesh;
1150         ot->description= "Select shortest path between two selections.";
1151         
1152         /* flags */
1153         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1154         
1155         /* properties */
1156         RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
1157 }
1158
1159 /* ************************************************** */
1160 /* here actual select happens */
1161 /* gets called via generic mouse select operator */
1162 int mouse_mesh(bContext *C, const int mval[2], short extend)
1163 {
1164         ViewContext vc;
1165         BMVert *eve = NULL;
1166         BMEdge *eed = NULL;
1167         BMFace *efa = NULL;
1168         
1169         /* setup view context for argument to callbacks */
1170         em_setup_viewcontext(C, &vc);
1171         vc.mval[0]= mval[0];
1172         vc.mval[1]= mval[1];
1173         
1174         if(unified_findnearest(&vc, &eve, &eed, &efa)) {
1175                 
1176                 if(extend==0) EDBM_clear_flag_all(vc.em, BM_SELECT);
1177                 
1178                 if(efa) {
1179                         /* set the last selected face */
1180                         EDBM_set_actFace(vc.em, efa);
1181                         
1182                         if(!BM_TestHFlag(efa, BM_SELECT)) {
1183                                 EDBM_store_selection(vc.em, efa);
1184                                 BM_Select(vc.em->bm, efa, 1);
1185                         }
1186                         else if(extend) {
1187                                 EDBM_remove_selection(vc.em, efa);
1188                                 BM_Select(vc.em->bm, efa, 0);
1189                         }
1190                 }
1191                 else if(eed) {
1192                         if(!BM_TestHFlag(eed, BM_SELECT)) {
1193                                 EDBM_store_selection(vc.em, eed);
1194                                 BM_Select(vc.em->bm, eed, 1);
1195                         }
1196                         else if(extend) {
1197                                 EDBM_remove_selection(vc.em, eed);
1198                                 BM_Select(vc.em->bm, eed, 0);
1199                         }
1200                 }
1201                 else if(eve) {
1202                         if(!BM_TestHFlag(eve, BM_SELECT)) {
1203                                 EDBM_store_selection(vc.em, eve);
1204                                 BM_Select(vc.em->bm, eve, 1);
1205                         }
1206                         else if(extend){ 
1207                                 EDBM_remove_selection(vc.em, eve);
1208                                 BM_Select(vc.em->bm, eve, 0);
1209                         }
1210                 }
1211                 
1212                 EDBM_selectmode_flush(vc.em);
1213                   
1214 //              if (EM_texFaceCheck()) {
1215
1216                 if (efa && efa->mat_nr != vc.obedit->actcol-1) {
1217                         vc.obedit->actcol= efa->mat_nr+1;
1218                         vc.em->mat_nr= efa->mat_nr;
1219 //                      BIF_preview_changed(ID_MA);
1220                 }
1221
1222                 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, vc.obedit);
1223                 return 1;
1224         }
1225
1226         return 0;
1227 }
1228
1229 static void EDBM_strip_selections(BMEditMesh *em)
1230 {
1231         BMEditSelection *ese, *nextese;
1232
1233         if(!(em->selectmode & SCE_SELECT_VERTEX)){
1234                 ese = em->bm->selected.first;
1235                 while(ese){
1236                         nextese = ese->next; 
1237                         if(ese->type == BM_VERT) BLI_freelinkN(&(em->bm->selected),ese);
1238                         ese = nextese;
1239                 }
1240         }
1241         if(!(em->selectmode & SCE_SELECT_EDGE)){
1242                 ese=em->bm->selected.first;
1243                 while(ese){
1244                         nextese = ese->next;
1245                         if(ese->type == BM_EDGE) BLI_freelinkN(&(em->bm->selected), ese);
1246                         ese = nextese;
1247                 }
1248         }
1249         if(!(em->selectmode & SCE_SELECT_FACE)){
1250                 ese=em->bm->selected.first;
1251                 while(ese){
1252                         nextese = ese->next;
1253                         if(ese->type == BM_FACE) BLI_freelinkN(&(em->bm->selected), ese);
1254                         ese = nextese;
1255                 }
1256         }
1257 }
1258
1259 /* when switching select mode, makes sure selection is consistant for editing */
1260 /* also for paranoia checks to make sure edge or face mode works */
1261 void EDBM_selectmode_set(BMEditMesh *em)
1262 {
1263         BMVert *eve;
1264         BMEdge *eed;
1265         BMFace *efa;
1266         BMIter iter;
1267         
1268         em->bm->selectmode = em->selectmode;
1269
1270         EDBM_strip_selections(em); /*strip BMEditSelections from em->selected that are not relevant to new mode*/
1271         
1272         if(em->selectmode & SCE_SELECT_VERTEX) {
1273                 /*BMIter iter;
1274                 
1275                 eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
1276                 for ( ; eed; eed=BMIter_Step(&iter)) BM_Select(em->bm, eed, 0);
1277                 
1278                 efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
1279                 for ( ; efa; efa=BMIter_Step(&iter)) BM_Select(em->bm, efa, 0);*/
1280
1281                 EDBM_selectmode_flush(em);
1282         }
1283         else if(em->selectmode & SCE_SELECT_EDGE) {
1284                 /* deselect vertices, and select again based on edge select */
1285                 eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
1286                 for ( ; eve; eve=BMIter_Step(&iter)) BM_Select(em->bm, eve, 0);
1287                 
1288                 eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
1289                 for ( ; eed; eed=BMIter_Step(&iter)) {
1290                         if (BM_TestHFlag(eed, BM_SELECT))
1291                                 BM_Select(em->bm, eed, 1);
1292                 }
1293                 
1294                 /* selects faces based on edge status */
1295                 EDBM_selectmode_flush(em);
1296         }
1297         else if(em->selectmode & SCE_SELECT_FACE) {
1298                 /* deselect eges, and select again based on face select */
1299                 eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
1300                 for ( ; eed; eed=BMIter_Step(&iter)) BM_Select(em->bm, eed, 0);
1301                 
1302                 efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
1303                 for ( ; efa; efa=BMIter_Step(&iter)) {
1304                         if (BM_TestHFlag(efa, BM_SELECT))
1305                                 BM_Select(em->bm, efa, 1);
1306                 }
1307         }
1308 }
1309
1310 void EDBM_convertsel(BMEditMesh *em, short oldmode, short selectmode)
1311 {
1312         BMEdge *eed;
1313         BMFace *efa;
1314         BMIter iter;
1315
1316         /*have to find out what the selectionmode was previously*/
1317         if(oldmode == SCE_SELECT_VERTEX) {
1318                 if(selectmode == SCE_SELECT_EDGE) {
1319                         /*select all edges associated with every selected vertex*/
1320                         eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
1321                         for ( ; eed; eed=BMIter_Step(&iter)) {
1322                                 if(BM_TestHFlag(eed->v1, BM_SELECT)) BM_Select(em->bm, eed, 1);
1323                                 else if(BM_TestHFlag(eed->v2, BM_SELECT)) BM_Select(em->bm, eed, 1);
1324                         }
1325                 }               
1326                 else if(selectmode == SCE_SELECT_FACE) {
1327                         BMIter liter;
1328                         BMLoop *l;
1329
1330                         /*select all faces associated with every selected vertex*/
1331                         efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
1332                         for ( ; efa; efa=BMIter_Step(&iter)) {
1333                                 l = BMIter_New(&liter, em->bm, BM_LOOPS_OF_FACE, efa);
1334                                 for (; l; l=BMIter_Step(&liter)) {
1335                                         if (BM_TestHFlag(l->v, BM_SELECT)) {
1336                                                 BM_Select(em->bm, efa, 1);
1337                                                 break;
1338                                         }
1339                                 }
1340                         }
1341                 }
1342         }
1343         
1344         if(oldmode == SCE_SELECT_EDGE){
1345                 if(selectmode == SCE_SELECT_FACE) {
1346                         BMIter liter;
1347                         BMLoop *l;
1348
1349                         /*select all faces associated with every selected vertex*/
1350                         efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
1351                         for ( ; efa; efa=BMIter_Step(&iter)) {
1352                                 l = BMIter_New(&liter, em->bm, BM_LOOPS_OF_FACE, efa);
1353                                 for (; l; l=BMIter_Step(&liter)) {
1354                                         if (BM_TestHFlag(l->v, BM_SELECT)) {
1355                                                 BM_Select(em->bm, efa, 1);
1356                                                 break;
1357                                         }
1358                                 }
1359                         }
1360                 }
1361         }
1362 }
1363
1364
1365 void EDBM_deselect_by_material(struct BMEditMesh *em, const short index, const short select)
1366 {
1367         BMIter iter;
1368         BMFace *efa;
1369
1370         BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
1371                 if (BM_TestHFlag(efa, BM_HIDDEN))
1372                         continue;
1373                 if(efa->mat_nr == index) {
1374                         BM_Select(em->bm, efa, select);
1375                 }
1376         }
1377 }
1378
1379
1380 void EDBM_select_swap(BMEditMesh *em) /* exported for UV */
1381 {
1382         BMIter iter;
1383         BMVert *eve;
1384         BMEdge *eed;
1385         BMFace *efa;
1386         
1387         if(em->bm->selectmode & SCE_SELECT_VERTEX) {
1388                 BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
1389                         if (BM_TestHFlag(eve, BM_HIDDEN))
1390                                 continue;
1391                         BM_Select(em->bm, eve, !BM_TestHFlag(eve, BM_SELECT));
1392                 }
1393         }
1394         else if(em->selectmode & SCE_SELECT_EDGE) {
1395                 BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
1396                         if (BM_TestHFlag(eed, BM_HIDDEN))
1397                                 continue;
1398                         BM_Select(em->bm, eed, !BM_TestHFlag(eed, BM_SELECT));
1399                 }
1400         }
1401         else {
1402                 BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
1403                         if (BM_TestHFlag(efa, BM_HIDDEN))
1404                                 continue;
1405                         BM_Select(em->bm, efa, !BM_TestHFlag(efa, BM_SELECT));
1406                 }
1407
1408         }
1409 //      if (EM_texFaceCheck())
1410 }
1411
1412 static int select_inverse_mesh_exec(bContext *C, wmOperator *UNUSED(op))
1413 {
1414         Object *obedit= CTX_data_edit_object(C);
1415         BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
1416         
1417         EDBM_select_swap(em);
1418         
1419         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
1420
1421         return OPERATOR_FINISHED;       
1422 }
1423
1424 void MESH_OT_select_inverse(wmOperatorType *ot)
1425 {
1426         /* identifiers */
1427         ot->name= "Select Inverse";
1428         ot->idname= "MESH_OT_select_inverse";
1429         ot->description= "Select inverse of (un)selected vertices, edges or faces.";
1430         
1431         /* api callbacks */
1432         ot->exec= select_inverse_mesh_exec;
1433         ot->poll= ED_operator_editmesh;
1434         
1435         /* flags */
1436         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1437 }
1438
1439
1440 static int select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
1441 {
1442         Object *obedit= CTX_data_edit_object(C);
1443         ViewContext vc;
1444         BMWalker walker;
1445         BMEditMesh *em;
1446         BMVert *eve;
1447         BMEdge *e, *eed;
1448         BMFace *efa;
1449         int sel= !RNA_boolean_get(op->ptr, "deselect");
1450         
1451         /* unified_finednearest needs ogl */
1452         view3d_operator_needs_opengl(C);
1453         
1454         /* setup view context for argument to callbacks */
1455         em_setup_viewcontext(C, &vc);
1456         em = vc.em;
1457
1458         if(vc.em->bm->totedge==0)
1459                 return OPERATOR_CANCELLED;
1460         
1461         vc.mval[0]= event->mval[0];
1462         vc.mval[1]= event->mval[1];
1463         
1464         /* return warning! */
1465
1466         /*if(limit) {
1467                 int retval= select_linked_limited_invoke(&vc, 0, sel);
1468                 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
1469                 return retval;
1470         }*/
1471         
1472         if( unified_findnearest(&vc, &eve, &eed, &efa)==0 ) {
1473                 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
1474         
1475                 return OPERATOR_CANCELLED;
1476         }
1477         
1478         if (efa) {
1479                 eed = bm_firstfaceloop(efa)->e;
1480         } else if (!eed) {
1481                 if (!eve || !eve->e)
1482                         return OPERATOR_CANCELLED;
1483                 
1484                 eed = eve->e;
1485         }
1486
1487         BMW_Init(&walker, em->bm, BMW_SHELL, 0, 0);
1488         e = BMW_Begin(&walker, eed->v1);
1489         for (; e; e=BMW_Step(&walker)) {
1490                         BM_Select(em->bm, e->v1, sel);
1491                         BM_Select(em->bm, e->v2, sel);
1492         }
1493         BMW_End(&walker);
1494         EDBM_select_flush(em, SCE_SELECT_VERTEX);
1495
1496         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
1497         return OPERATOR_FINISHED;       
1498 }
1499
1500 void MESH_OT_select_linked_pick(wmOperatorType *ot)
1501 {
1502         /* identifiers */
1503         ot->name= "Select Linked";
1504         ot->idname= "MESH_OT_select_linked_pick";
1505         
1506         /* api callbacks */
1507         ot->invoke= select_linked_pick_invoke;
1508         ot->poll= ED_operator_editmesh;
1509         ot->description= "select/deselect all vertices linked to the edge under the mouse cursor.";
1510         
1511         /* flags */
1512         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1513         
1514         RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "");
1515         RNA_def_boolean(ot->srna, "limit", 0, "Limit by Seams", "");
1516 }
1517
1518
1519 static int select_linked_exec(bContext *C, wmOperator *UNUSED(op))
1520 {
1521         Object *obedit= CTX_data_edit_object(C);
1522         BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
1523         BLI_array_declare(verts);
1524         BMVert **verts = NULL;
1525         BMIter iter;
1526         BMVert *v;
1527         BMEdge *e;
1528         BMWalker walker;
1529         int i, tot;
1530
1531         tot = 0;
1532         BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
1533                 if (BM_TestHFlag(v, BM_SELECT) && !BM_TestHFlag(v, BM_HIDDEN)) {
1534                         BLI_array_growone(verts);
1535                         verts[tot++] = v;
1536                 }
1537         }
1538
1539         BMW_Init(&walker, em->bm, BMW_SHELL, 0, 0);
1540         for (i=0; i<tot; i++) {
1541                 e = BMW_Begin(&walker, verts[i]);
1542                 for (; e; e=BMW_Step(&walker)) {
1543                         BM_Select(em->bm, e->v1, 1);
1544                         BM_Select(em->bm, e->v2, 1);
1545                 }
1546         }
1547         BMW_End(&walker);
1548         EDBM_select_flush(em, SCE_SELECT_VERTEX);
1549
1550         BLI_array_free(verts);
1551         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
1552
1553         return OPERATOR_FINISHED;       
1554 }
1555
1556 void MESH_OT_select_linked(wmOperatorType *ot)
1557 {
1558         /* identifiers */
1559         ot->name= "Select Linked All";
1560         ot->idname= "MESH_OT_select_linked";
1561         
1562         /* api callbacks */
1563         ot->exec= select_linked_exec;
1564         ot->poll= ED_operator_editmesh;
1565         ot->description= "Select all vertices linked to the active mesh.";
1566         
1567         /* flags */
1568         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1569         
1570         RNA_def_boolean(ot->srna, "limit", 0, "Limit by Seams", "");
1571 }
1572
1573 /* ******************** **************** */
1574
1575 static int select_more(bContext *C, wmOperator *op)
1576 {
1577         Object *obedit= CTX_data_edit_object(C);
1578         BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh;
1579         BMOperator bmop;
1580         int usefaces = em->selectmode > SCE_SELECT_EDGE;
1581
1582         EDBM_InitOpf(em, &bmop, op, "regionextend geom=%hvef constrict=%d usefaces=%d", 
1583                      BM_SELECT, 0, usefaces);
1584
1585         BMO_Exec_Op(em->bm, &bmop);
1586         BMO_HeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT, BM_ALL);
1587
1588         EDBM_selectmode_flush(em);
1589
1590         if (!EDBM_FinishOp(em, &bmop, op, 1))
1591                 return OPERATOR_CANCELLED;
1592
1593         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
1594         return OPERATOR_FINISHED;
1595 }
1596
1597 void MESH_OT_select_more(wmOperatorType *ot)
1598 {
1599         /* identifiers */
1600         ot->name= "Select More";
1601         ot->idname= "MESH_OT_select_more";
1602         ot->description= "Select more vertices, edges or faces connected to initial selection.";
1603
1604         /* api callbacks */
1605         ot->exec= select_more;
1606         ot->poll= ED_operator_editmesh;
1607         
1608         /* flags */
1609         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1610 }
1611
1612 static int select_less(bContext *C, wmOperator *op)
1613 {
1614         Object *obedit= CTX_data_edit_object(C);
1615         BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh;
1616         BMOperator bmop;
1617         int usefaces = em->selectmode > SCE_SELECT_EDGE;
1618
1619         EDBM_InitOpf(em, &bmop, op, "regionextend geom=%hvef constrict=%d usefaces=%d", 
1620                      BM_SELECT, 1, usefaces);
1621
1622         BMO_Exec_Op(em->bm, &bmop);
1623         BMO_UnHeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT, BM_ALL);
1624
1625         EDBM_selectmode_flush(em);
1626
1627         if (!EDBM_FinishOp(em, &bmop, op, 1))
1628                 return OPERATOR_CANCELLED;
1629
1630         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
1631         return OPERATOR_FINISHED;
1632 }
1633
1634 void MESH_OT_select_less(wmOperatorType *ot)
1635 {
1636         /* identifiers */
1637         ot->name= "Select Less";
1638         ot->idname= "MESH_OT_select_less";
1639         ot->description= "Deselect vertices, edges or faces at the boundary of each selection region.";
1640
1641         /* api callbacks */
1642         ot->exec= select_less;
1643         ot->poll= ED_operator_editmesh;
1644         
1645         /* flags */
1646         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1647 }
1648
1649 /* not that optimal!, should be nicer with bmesh */
1650 static void tag_face_edges(BMesh* bm, BMFace *f)
1651 {
1652         BMLoop *l;
1653         BMIter iter;
1654
1655         BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
1656                 BM_SetIndex(l->e, 1);
1657         }
1658 }
1659 static int tag_face_edges_test(BMesh* bm, BMFace *f)
1660 {
1661         BMLoop *l;
1662         BMIter iter;
1663
1664         BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
1665                 if(BM_GetIndex(l->e) != 0)
1666                         return 1;
1667         }
1668
1669         return 0;
1670 }
1671
1672 static void em_deselect_nth_face(BMEditMesh *em, int nth, BMFace *f_act)
1673 {
1674         BMFace *f;
1675         BMEdge *e;
1676         BMIter iter;
1677         BMesh *bm = em->bm;
1678         int index;
1679         int ok= 1;
1680
1681         if(f_act==NULL) {
1682                 return;
1683         }
1684
1685         /* to detect loose edges, we put f2 flag on 1 */
1686         BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
1687                 BM_SetIndex(e, 0);
1688         }
1689
1690         BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
1691                 BM_SetIndex(f, 0);
1692         }
1693
1694         BM_SetIndex(f_act, 1);
1695
1696         while(ok) {
1697                 ok = 0;
1698
1699                 BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
1700                         index= BM_GetIndex(f);
1701                         if(index==1) { /* initialize */
1702                                 tag_face_edges(bm, f);
1703                         }
1704
1705                         if (index)
1706                                 BM_SetIndex(f, index+1);
1707                 }
1708
1709                 BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
1710                         if(BM_GetIndex(f)==0 && tag_face_edges_test(bm, f)) {
1711                                 BM_SetIndex(f, 1);
1712                                 ok= 1; /* keep looping */
1713                         }
1714                 }
1715         }
1716
1717         BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
1718                 index= BM_GetIndex(f);
1719                 if(index > 0 && index % nth) {
1720                         BM_Select(bm, f, 0);
1721                 }
1722         }
1723
1724         EDBM_select_flush(em, SCE_SELECT_FACE);
1725 }
1726
1727 /* not that optimal!, should be nicer with bmesh */
1728 static void tag_edge_verts(BMEdge *e)
1729 {
1730         BM_SetIndex(e->v1, 1);
1731         BM_SetIndex(e->v2, 1);
1732 }
1733 static int tag_edge_verts_test(BMEdge *e)
1734 {
1735         return (BM_GetIndex(e->v1) || BM_GetIndex(e->v2)) ? 1:0;
1736 }
1737
1738 static void em_deselect_nth_edge(BMEditMesh *em, int nth, BMEdge *e_act)
1739 {
1740         BMEdge *e;
1741         BMVert *v;
1742         BMIter iter;
1743         BMesh *bm = em->bm;
1744         int index;
1745         int ok= 1;
1746
1747         if(e_act==NULL) {
1748                 return;
1749         }
1750
1751         BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
1752                 BM_SetIndex(v, 0);
1753         }
1754
1755         BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
1756                 BM_SetIndex(e, 0);
1757         }
1758
1759         BM_SetIndex(e_act, 1);
1760
1761         while(ok) {
1762                 ok = 0;
1763
1764                 BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
1765                         index= BM_GetIndex(e);
1766                         if (index==1) { /* initialize */
1767                                 tag_edge_verts(e);
1768                         }
1769
1770                         if (index)
1771                                 BM_SetIndex(e, index+1);
1772                 }
1773
1774                 BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
1775                         if (BM_GetIndex(e)==0 && tag_edge_verts_test(e)) {
1776                                 BM_SetIndex(e, 1);
1777                                 ok = 1; /* keep looping */
1778                         }
1779                 }
1780         }
1781
1782         BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
1783                 index= BM_GetIndex(e);
1784                 if (index > 0 && index % nth)
1785                         BM_Select(bm, e, 0);
1786         }
1787
1788         EDBM_select_flush(em, SCE_SELECT_EDGE);
1789 }
1790
1791 static void em_deselect_nth_vert(BMEditMesh *em, int nth, BMVert *v_act)
1792 {
1793         BMEdge *e;
1794         BMVert *v;
1795         BMIter iter;
1796         BMesh *bm = em->bm;
1797         int ok= 1;
1798
1799         if(v_act==NULL) {
1800                 return;
1801         }
1802
1803         BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
1804                 BM_SetIndex(v, 0);
1805         }
1806         
1807         BM_SetIndex(v_act, 1);
1808
1809         while(ok) {
1810                 ok = 0;
1811
1812                 BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
1813                         int index = BM_GetIndex(v);
1814                         if (index != 0)
1815                                 BM_SetIndex(v, index+1);
1816                 }
1817
1818                 BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
1819                         int indexv1= BM_GetIndex(e->v1);
1820                         int indexv2= BM_GetIndex(e->v2);
1821                         if (indexv1 == 2 && indexv2 == 0) {
1822                                 BM_SetIndex(e->v2, 1);
1823                                 ok = 1; /* keep looping */
1824                         }
1825                         else if (indexv2 == 2 && indexv1 == 0) {
1826                                 BM_SetIndex(e->v1, 1);
1827                                 ok = 1; /* keep looping */
1828                         }
1829                 }
1830         }
1831
1832         BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
1833                 int index= BM_GetIndex(v);
1834                 if(index && index % nth) {
1835                         BM_Select(bm, v, 0);
1836                 }
1837         }
1838
1839         EDBM_select_flush(em, SCE_SELECT_VERTEX);
1840 }
1841
1842 BMFace *EM_get_actFace(BMEditMesh *em, int sloppy)
1843 {
1844         if (em->bm->act_face) {
1845                 return em->bm->act_face;
1846         } else if (sloppy) {
1847                 BMIter iter;
1848                 BMFace *f= NULL;
1849                 BMEditSelection *ese;
1850                 
1851                 /* Find the latest non-hidden face from the BMEditSelection */
1852                 ese = em->bm->selected.last;
1853                 for (; ese; ese=ese->prev){
1854                         if(ese->type == BM_FACE) {
1855                                 f = (BMFace *)ese->data;
1856                                 
1857                                 if (BM_TestHFlag(f, BM_HIDDEN)) f= NULL;
1858                                 else            break;
1859                         }
1860                 }
1861                 /* Last attempt: try to find any selected face */
1862                 if (f==NULL) {
1863                         BM_ITER(f, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
1864                                 if (BM_TestHFlag(f, BM_SELECT))
1865                                         break;
1866                         }
1867                 }
1868                 return f; /* can still be null */
1869         }
1870         return NULL;
1871 }
1872
1873 static void deselect_nth_active(BMEditMesh *em, BMVert **v_p, BMEdge **e_p, BMFace **f_p)
1874 {
1875         BMVert *v;
1876         BMEdge *e;
1877         BMFace *f;
1878         BMIter iter;
1879         BMEditSelection *ese;
1880
1881         *v_p= NULL;
1882         *e_p= NULL;
1883         *f_p= NULL;
1884
1885         EDBM_selectmode_flush(em);
1886         ese= (BMEditSelection*)em->bm->selected.last;
1887
1888         if(ese) {
1889                 switch(ese->type) {
1890                 case BM_VERT:
1891                         *v_p= (BMVert *)ese->data;
1892                         return;
1893                 case BM_EDGE:
1894                         *e_p= (BMEdge *)ese->data;
1895                         return;
1896                 case BM_FACE:
1897                         *f_p= (BMFace *)ese->data;
1898                         return;
1899                 }
1900         }
1901
1902         if(em->selectmode & SCE_SELECT_VERTEX) {
1903                 BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
1904                         if (BM_TestHFlag(v, BM_SELECT)) {
1905                                 *v_p = v;
1906                                 return;
1907                         }
1908                 }
1909         }
1910         else if(em->selectmode & SCE_SELECT_EDGE) {
1911                 BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
1912                         if (BM_TestHFlag(e, BM_SELECT)) {
1913                                 *e_p = e;
1914                                 return;
1915                         }
1916                 }
1917         }
1918         else if(em->selectmode & SCE_SELECT_FACE) {
1919                 f= EM_get_actFace(em, 1);
1920                 if(f) {
1921                         *f_p= f;
1922                         return;
1923                 }
1924         }
1925 }
1926
1927 static int EM_deselect_nth(BMEditMesh *em, int nth)
1928 {
1929         BMVert *v;
1930         BMEdge *e;
1931         BMFace *f;
1932
1933         deselect_nth_active(em, &v, &e, &f);
1934
1935         if(v) {
1936                 em_deselect_nth_vert(em, nth, v);
1937                 return 1;
1938         }
1939         else if(e) {
1940                 em_deselect_nth_edge(em, nth, e);
1941                 return 1;
1942         }
1943         else if(f) {
1944                 em_deselect_nth_face(em, nth, f);
1945                 return 1;
1946         }
1947
1948         return 0;
1949 }
1950
1951 static int mesh_select_nth_exec(bContext *C, wmOperator *op)
1952 {
1953         Object *obedit= CTX_data_edit_object(C);
1954         BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
1955         int nth= RNA_int_get(op->ptr, "nth");
1956
1957         if(EM_deselect_nth(em, nth) == 0) {
1958                 BKE_report(op->reports, RPT_ERROR, "Mesh has no active vert/edge/face.");
1959                 return OPERATOR_CANCELLED;
1960         }
1961
1962         DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
1963         WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
1964
1965         return OPERATOR_FINISHED;
1966 }
1967
1968
1969 void MESH_OT_select_nth(wmOperatorType *ot)
1970 {
1971         /* identifiers */
1972         ot->name= "Select Nth";
1973         ot->description= "";
1974         ot->idname= "MESH_OT_select_nth";
1975
1976         /* api callbacks */
1977         ot->exec= mesh_select_nth_exec;
1978         ot->poll= ED_operator_editmesh;
1979
1980         /* flags */
1981         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1982
1983         RNA_def_int(ot->srna, "nth", 2, 2, 100, "Nth Selection", "", 1, INT_MAX);
1984 }
1985
1986 void em_setup_viewcontext(bContext *C, ViewContext *vc)
1987 {
1988         view3d_set_viewcontext(C, vc);
1989         
1990         if(vc->obedit) {
1991                 Mesh *me= vc->obedit->data;
1992                 vc->em= me->edit_btmesh;
1993         }
1994 }
1995
1996 /* poll call for mesh operators requiring a view3d context */
1997 int EM_view3d_poll(bContext *C)
1998 {
1999         if(ED_operator_editmesh(C) && ED_operator_view3d_active(C))
2000                 return 1;
2001         return 0;
2002 }
2003
2004
2005 static int select_sharp_edges_exec(bContext *C, wmOperator *op)
2006 {
2007         /* Find edges that have exactly two neighboring faces,
2008         * check the angle between those faces, and if angle is
2009         * small enough, select the edge
2010         */
2011         Object *obedit= CTX_data_edit_object(C);
2012         BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
2013         BMIter iter;
2014         BMEdge *e;
2015         BMLoop *l1, *l2;
2016         float sharp = RNA_float_get(op->ptr, "sharpness"), angle;
2017
2018         sharp = DEG2RADF(sharp);
2019
2020         BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
2021                 if (BM_TestHFlag(e, BM_HIDDEN) || !e->l)
2022                         continue;
2023
2024                 l1 = e->l;
2025                 l2 = l1->radial_next;
2026
2027                 if (l1 == l2)
2028                         continue;
2029
2030                 /* edge has exactly two neighboring faces, check angle */
2031                 angle = saacos(l1->f->no[0]*l2->f->no[0]+l1->f->no[1]*l2->f->no[1]+l1->f->no[2]*l2->f->no[2]);
2032
2033                 if (fabsf(angle) < sharp) {
2034                         BM_Select(em->bm, e, 1);
2035                 }
2036
2037         }
2038
2039         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
2040
2041         return OPERATOR_FINISHED;
2042 }
2043
2044 void MESH_OT_edges_select_sharp(wmOperatorType *ot)
2045 {
2046         /* identifiers */
2047         ot->name= "Select Sharp Edges";
2048         ot->description= "Marked selected edges as sharp.";
2049         ot->idname= "MESH_OT_edges_select_sharp";
2050         
2051         /* api callbacks */
2052         ot->exec= select_sharp_edges_exec;
2053         ot->poll= ED_operator_editmesh;
2054         
2055         /* flags */
2056         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2057         
2058         /* props */
2059         RNA_def_float(ot->srna, "sharpness", 1.0f, 0.01f, FLT_MAX, "sharpness", "", 1.0f, 180.0f);
2060 }
2061
2062 static int select_linked_flat_faces_exec(bContext *C, wmOperator *op)
2063 {
2064         Object *obedit= CTX_data_edit_object(C);
2065         BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
2066         BMIter iter, liter, liter2;
2067         BMFace *f, **stack = NULL;
2068         BLI_array_declare(stack);
2069         BMLoop *l, *l2;
2070         float sharp = RNA_float_get(op->ptr, "sharpness");
2071         int i;
2072
2073         sharp = (sharp * M_PI) / 180.0;
2074
2075         BM_ITER(f, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
2076                 BM_SetIndex(f, 0);
2077         }
2078
2079         BM_ITER(f, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
2080                 if (BM_TestHFlag(f, BM_HIDDEN) || !BM_TestHFlag(f, BM_SELECT) || BM_GetIndex(f))
2081                         continue;
2082
2083                 BLI_array_empty(stack);
2084                 i = 1;
2085
2086                 BLI_array_growone(stack);
2087                 stack[i-1] = f;
2088
2089                 while (i) {
2090                         f = stack[i-1];
2091                         i--;
2092
2093                         BM_Select(em->bm, f, 1);
2094
2095                         BM_SetIndex(f, 1);
2096
2097                         BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, f) {
2098                                 BM_ITER(l2, &liter2, em->bm, BM_LOOPS_OF_LOOP, l) {
2099                                         float angle;
2100
2101                                         if (BM_GetIndex(l2->f) || BM_TestHFlag(l2->f, BM_HIDDEN))
2102                                                 continue;
2103
2104                                         /* edge has exactly two neighboring faces, check angle */
2105                                         angle = saacos(f->no[0]*l2->f->no[0]+f->no[1]*l2->f->no[1]+f->no[2]*l2->f->no[2]);
2106
2107                                         /* invalidate: edge too sharp */
2108                                         if (fabs(angle) < sharp) {
2109                                                 BLI_array_growone(stack);
2110                                                 stack[i] = l2->f;
2111                                                 i++;
2112                                         }
2113                                 }
2114                         }
2115                 }
2116         }
2117
2118         BLI_array_free(stack);
2119
2120         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
2121
2122         return OPERATOR_FINISHED;
2123 }
2124
2125 void MESH_OT_faces_select_linked_flat(wmOperatorType *ot)
2126 {
2127         /* identifiers */
2128         ot->name= "Select Linked Flat Faces";
2129         ot->description= "Select linked faces by angle.";
2130         ot->idname= "MESH_OT_faces_select_linked_flat";
2131         
2132         /* api callbacks */
2133         ot->exec= select_linked_flat_faces_exec;
2134         ot->poll= ED_operator_editmesh;
2135         
2136         /* flags */
2137         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2138         
2139         /* props */
2140         RNA_def_float(ot->srna, "sharpness", 1.0f, 0.01f, FLT_MAX, "sharpness", "", 1.0f, 180.0f);
2141 }
2142
2143 static int select_non_manifold_exec(bContext *C, wmOperator *op)
2144 {
2145         Object *obedit= CTX_data_edit_object(C);
2146         BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
2147         BMVert *v;
2148         BMEdge *e;
2149         BMIter iter;
2150
2151         /* Selects isolated verts, and edges that do not have 2 neighboring
2152          * faces
2153          */
2154         
2155         if(em->selectmode==SCE_SELECT_FACE) {
2156                 BKE_report(op->reports, RPT_ERROR, "Doesn't work in face selection mode");
2157                 return OPERATOR_CANCELLED;
2158         }
2159         
2160         BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
2161                 if (!BM_TestHFlag(em->bm, BM_HIDDEN) && BM_Nonmanifold_Vert(em->bm, v))
2162                         BM_Select(em->bm, v, 1);
2163         }
2164         
2165         BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
2166                 if (!BM_TestHFlag(em->bm, BM_HIDDEN) && BM_Edge_FaceCount(e) != 2)
2167                         BM_Select(em->bm, e, 1);
2168         }
2169
2170         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
2171
2172         return OPERATOR_FINISHED;       
2173 }
2174
2175 void MESH_OT_select_non_manifold(wmOperatorType *ot)
2176 {
2177         /* identifiers */
2178         ot->name= "Select Non Manifold";
2179         ot->description= "Select all non-manifold vertices or edges.";
2180         ot->idname= "MESH_OT_select_non_manifold";
2181         
2182         /* api callbacks */
2183         ot->exec= select_non_manifold_exec;
2184         ot->poll= ED_operator_editmesh;
2185         
2186         /* flags */
2187         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2188 }
2189
2190 static int mesh_select_random_exec(bContext *C, wmOperator *op)
2191 {
2192         Object *obedit= CTX_data_edit_object(C);
2193         BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
2194         BMVert *eve;
2195         BMEdge *eed;
2196         BMFace *efa;
2197         BMIter iter;
2198         float randfac =  RNA_float_get(op->ptr, "percent")/100.0f;
2199
2200         BLI_srand( BLI_rand() ); /* random seed */
2201         
2202         if(!RNA_boolean_get(op->ptr, "extend"))
2203                 EDBM_clear_flag_all(em, BM_SELECT);
2204
2205         if(em->selectmode & SCE_SELECT_VERTEX) {
2206                 BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
2207                         if (!BM_TestHFlag(eve, BM_HIDDEN) && BLI_frand() < randfac)
2208                                 BM_Select(em->bm, eve, 1);
2209                 }
2210                 EDBM_selectmode_flush(em);
2211         }
2212         else if(em->selectmode & SCE_SELECT_EDGE) {
2213                 BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
2214                         if (!BM_TestHFlag(eed, BM_HIDDEN) && BLI_frand() < randfac)
2215                                 BM_Select(em->bm, eed, 1);
2216                 }
2217                 EDBM_selectmode_flush(em);
2218         }
2219         else {
2220                 BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
2221                         if (!BM_TestHFlag(efa, BM_HIDDEN) && BLI_frand() < randfac)
2222                                 BM_Select(em->bm, efa, 1);
2223                 }
2224                 EDBM_selectmode_flush(em);
2225         }
2226         
2227         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
2228         
2229         return OPERATOR_FINISHED;       
2230 }
2231
2232 void MESH_OT_select_random(wmOperatorType *ot)
2233 {
2234         /* identifiers */
2235         ot->name= "Select Random";
2236         ot->description= "Randomly select vertices.";
2237         ot->idname= "MESH_OT_select_random";
2238
2239         /* api callbacks */
2240         ot->exec= mesh_select_random_exec;
2241         ot->poll= ED_operator_editmesh;
2242
2243         /* flags */
2244         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2245         
2246         /* props */
2247         RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f, "Percent", "Percentage of elements to select randomly.", 0.f, 100.0f);
2248         RNA_def_boolean(ot->srna, "extend", 0, "Extend Selection", "Extend selection instead of deselecting everything first.");
2249 }
2250
2251 static int select_next_loop(bContext *C, wmOperator *UNUSED(op))
2252 {
2253         Object *obedit= CTX_data_edit_object(C);
2254         BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh;
2255         BMFace *f;
2256         BMVert *v;
2257         BMIter iter;
2258         
2259         BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
2260                 BM_SetIndex(v, 0);
2261         }
2262         
2263         BM_ITER(f, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
2264                 BMLoop *l;
2265                 BMIter liter;
2266                 
2267                 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, f) {
2268                         if (BM_TestHFlag(l->v, BM_SELECT) && !BM_TestHFlag(l->v, BM_HIDDEN)) {
2269                                 BM_SetIndex(l->next->v, 1);
2270                                 BM_Select(em->bm, l->v, 0);
2271                         }
2272                 }
2273         }
2274
2275         BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
2276                 if (BM_GetIndex(v)) {
2277                         BM_Select(em->bm, v, 1);
2278                 }
2279         }
2280
2281         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit);
2282         return OPERATOR_FINISHED;
2283 }
2284
2285 void MESH_OT_select_next_loop(wmOperatorType *ot)
2286 {
2287         /* identifiers */
2288         ot->name= "Select Next Loop";
2289         ot->idname= "MESH_OT_select_next_loop";
2290         ot->description= "";
2291
2292         /* api callbacks */
2293         ot->exec= select_next_loop;
2294         ot->poll= ED_operator_editmesh;
2295         
2296         /* flags */
2297         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2298 }
2299
2300
2301 static int region_to_loop(bContext *C, wmOperator *UNUSED(op))
2302 {
2303         Object *obedit = CTX_data_edit_object(C);
2304         BMEditMesh *em = ((Mesh*)obedit->data)->edit_btmesh;
2305         BMFace *f;
2306         BMEdge *e;
2307         BMIter iter;
2308         
2309         BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
2310                 BM_SetIndex(e, 0);
2311         }
2312
2313         BM_ITER(f, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
2314                 BMLoop *l1, *l2;
2315                 BMIter liter1, liter2;
2316                 
2317                 BM_ITER(l1, &liter1, em->bm, BM_LOOPS_OF_FACE, f) {
2318                         int tot=0, totsel=0;
2319                         
2320                         BM_ITER(l2, &liter2, em->bm, BM_LOOPS_OF_EDGE, l1->e) {
2321                                 tot++;
2322                                 totsel += BM_TestHFlag(l2->f, BM_SELECT) != 0;
2323                         }
2324                         
2325                         if ((tot != totsel && totsel > 0) || (totsel == 1 && tot == 1))
2326                                 BM_SetIndex(l1->e, 1);
2327                 }
2328         }
2329
2330         EDBM_clear_flag_all(em, BM_SELECT);
2331         
2332         BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
2333                 if (BM_GetIndex(e) && !BM_TestHFlag(e, BM_HIDDEN))
2334                         BM_Select_Edge(em->bm, e, 1);
2335         }
2336         
2337         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
2338         return OPERATOR_FINISHED;
2339 }
2340
2341 void MESH_OT_region_to_loop(wmOperatorType *ot)
2342 {
2343         /* identifiers */
2344         ot->name= "Select Boundary Loop";
2345         ot->idname= "MESH_OT_region_to_loop";
2346
2347         /* api callbacks */
2348         ot->exec= region_to_loop;
2349         ot->poll= ED_operator_editmesh;
2350
2351         /* flags */
2352         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2353 }
2354
2355 static int loop_find_region(BMEditMesh *em, BMLoop *l, int flag, 
2356         SmallHash *fhash, BMFace ***region_out)
2357 {
2358         BLI_array_declare(region);
2359         BLI_array_declare(stack);
2360         BMFace **region = NULL, *f;
2361         BMFace **stack = NULL;
2362         
2363         BLI_array_append(stack, l->f);
2364         BLI_smallhash_insert(fhash, (uintptr_t)l->f, NULL);
2365         
2366         while (BLI_array_count(stack) > 0) {
2367                 BMIter liter1, liter2;
2368                 BMLoop *l1, *l2;
2369                 
2370                 f = BLI_array_pop(stack);
2371                 BLI_array_append(region, f);
2372                 
2373                 BM_ITER(l1, &liter1, em->bm, BM_LOOPS_OF_FACE, f) {
2374                         if (BM_TestHFlag(l1->e, flag))
2375                                 continue;
2376                         
2377                         BM_ITER(l2, &liter2, em->bm, BM_LOOPS_OF_EDGE, l1->e) {
2378                                 if (BLI_smallhash_haskey(fhash, (uintptr_t)l2->f))
2379                                         continue;
2380                                 
2381                                 BLI_array_append(stack, l2->f);
2382                                 BLI_smallhash_insert(fhash, (uintptr_t)l2->f, NULL);
2383                         }
2384                 }
2385         }
2386         
2387         BLI_array_free(stack);
2388         
2389         *region_out = region;
2390         return BLI_array_count(region);
2391 }
2392
2393 static int verg_radial(const void *va, const void *vb)
2394 {
2395         BMEdge *e1 = *((void**)va);
2396         BMEdge *e2 = *((void**)vb);
2397         int a, b;
2398         
2399         a = BM_Edge_FaceCount(e1);
2400         b = BM_Edge_FaceCount(e2);
2401         
2402         if (a > b) return -1;
2403         if (a == b) return 0;
2404         if (a < b) return 1;
2405         
2406         return -1;
2407 }
2408
2409 static int loop_find_regions(BMEditMesh *em, int selbigger)
2410 {
2411         SmallHash visithash;
2412         BMIter iter;
2413         BMEdge *e, **edges=NULL;
2414         BLI_array_declare(edges);
2415         BMFace *f;
2416         int count = 0, i;
2417         
2418         BLI_smallhash_init(&visithash);
2419         
2420         BM_ITER(f, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
2421                 BM_SetIndex(f, 0);
2422         }
2423
2424         BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
2425                 if (BM_TestHFlag(e, BM_SELECT)) {
2426                         BLI_array_append(edges, e);
2427                         BM_SetIndex(e, 1);
2428                 } else {
2429                         BM_SetIndex(e, 0);
2430                 }
2431         }
2432         
2433         /*sort edges by radial cycle length*/
2434         qsort(edges,  BLI_array_count(edges), sizeof(void*), verg_radial);
2435         
2436         for (i=0; i<BLI_array_count(edges); i++) {
2437                 BMIter liter;
2438                 BMLoop *l;
2439                 BMFace **region=NULL, **r;
2440                 int c, tot=0;
2441                 
2442                 e = edges[i];
2443                 
2444                 if (!BM_GetIndex(e))
2445                         continue;
2446                 
2447                 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_EDGE, e) {
2448                         if (BLI_smallhash_haskey(&visithash, (uintptr_t)l->f))
2449                                 continue;
2450                                                 
2451                         c = loop_find_region(em, l, BM_SELECT, &visithash, &r);
2452                         
2453                         if (!region || (selbigger ? c >= tot : c < tot)) {
2454                                 tot = c;
2455                                 if (region) 
2456                                         MEM_freeN(region);
2457                                 region = r;
2458                         }
2459                 }
2460                 
2461                 if (region) {
2462                         int j;
2463                         
2464                         for (j=0; j<tot; j++) {
2465                                 BM_SetIndex(region[j], 1);
2466                                 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, region[j]) {
2467                                         BM_SetIndex(l->e, 0);
2468                                 }
2469                         }
2470                         
2471                         count += tot;
2472                         
2473                         MEM_freeN(region);
2474                 }
2475         }
2476         
2477         BLI_array_free(edges);
2478         BLI_smallhash_release(&visithash);
2479         
2480         return count;
2481 }
2482
2483 static int loop_to_region(bContext *C, wmOperator *op)
2484 {
2485         Object *obedit = CTX_data_edit_object(C);
2486         BMEditMesh *em = ((Mesh*)obedit->data)->edit_btmesh;
2487         BMIter iter;
2488         BMFace *f;
2489         int selbigger = RNA_boolean_get(op->ptr, "select_bigger");
2490         int a, b;
2491         
2492         /*find the set of regions with smallest number of total faces*/
2493         a = loop_find_regions(em, selbigger);
2494         b = loop_find_regions(em, !selbigger);
2495         
2496         if ((a <= b) ^ selbigger) {
2497                 loop_find_regions(em, selbigger);
2498         }
2499         
2500         EDBM_clear_flag_all(em, BM_SELECT);
2501         
2502         BM_ITER(f, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
2503                 if (BM_GetIndex(f) && !BM_TestHFlag(f, BM_HIDDEN)) {
2504                         BM_Select_Face(em->bm, f, 1);
2505                 }
2506         }
2507         
2508         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
2509         return OPERATOR_FINISHED;
2510 }
2511
2512 void MESH_OT_loop_to_region(wmOperatorType *ot)
2513 {
2514         /* identifiers */
2515         ot->name= "Select Loop Inner-Region";
2516         ot->idname= "MESH_OT_loop_to_region";
2517
2518         /* api callbacks */
2519         ot->exec= loop_to_region;
2520         ot->poll= ED_operator_editmesh;
2521
2522         /* flags */
2523         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2524         
2525         RNA_def_boolean(ot->srna, "select_bigger", 0, "Select Bigger", "Select bigger regions instead of smaller ones");
2526 }