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