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