Bugfix #3237
[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 #ifdef HAVE_CONFIG_H
44 #include <config.h>
45 #endif
46
47 #include "MEM_guardedalloc.h"
48
49 #include "MTC_matrixops.h"
50
51 #include "DNA_mesh_types.h"
52 #include "DNA_material_types.h"
53 #include "DNA_meshdata_types.h"
54 #include "DNA_object_types.h"
55 #include "DNA_texture_types.h"
56 #include "DNA_scene_types.h"
57 #include "DNA_screen_types.h"
58 #include "DNA_view3d_types.h"
59
60 #include "BLI_blenlib.h"
61 #include "BLI_arithb.h"
62 #include "BLI_editVert.h"
63 #include "BLI_rand.h"
64
65 #include "BKE_displist.h"
66 #include "BKE_depsgraph.h"
67 #include "BKE_DerivedMesh.h"
68 #include "BKE_global.h"
69 #include "BKE_mesh.h"
70 #include "BKE_material.h"
71 #include "BKE_texture.h"
72 #include "BKE_utildefines.h"
73
74 #include "BIF_editmesh.h"
75 #include "BIF_resources.h"
76 #include "BIF_gl.h"
77 #include "BIF_glutil.h"
78 #include "BIF_graphics.h"
79 #include "BIF_interface.h"
80 #include "BIF_meshtools.h"
81 #include "BIF_mywindow.h"
82 #include "BIF_resources.h"
83 #include "BIF_screen.h"
84 #include "BIF_space.h"
85 #include "BIF_toolbox.h"
86
87 #include "BDR_drawobject.h"
88 #include "BDR_editobject.h"
89
90 #include "BSE_drawview.h"
91 #include "BSE_edit.h"
92 #include "BSE_view.h"
93
94 #include "IMB_imbuf.h"
95
96 #include "mydevice.h"
97 #include "blendef.h"
98 #include "render.h"  // externtex
99
100 #include "editmesh.h"
101
102
103 /* ****************************** MIRROR **************** */
104
105 static EditVert *get_x_mirror_vert(EditVert *eve)
106 {
107         int index;
108         
109         index= mesh_get_x_mirror_vert(G.obedit, POINTER_TO_INT(eve));
110         if(index != -1)
111                 return INT_TO_POINTER(index);
112         return NULL;
113 }
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= get_x_mirror_vert(eve);
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 static void check_backbuf(void)
138 {
139         if(G.vd->flag & V3D_NEEDBACKBUFDRAW) {
140                 backdrawview3d(0);
141         }
142 }
143
144 /* samples a single pixel (copied from vpaint) */
145 static unsigned int sample_backbuf(int x, int y)
146 {
147         unsigned int col;
148         
149         if(x>=curarea->winx || y>=curarea->winy) return 0;
150         x+= curarea->winrct.xmin;
151         y+= curarea->winrct.ymin;
152         
153         check_backbuf(); // actually not needed for apple
154
155 #ifdef __APPLE__
156         glReadBuffer(GL_AUX0);
157 #endif
158         glReadPixels(x,  y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,  &col);
159         glReadBuffer(GL_BACK);  
160         
161         if(G.order==B_ENDIAN) SWITCH_INT(col);
162         
163         return framebuffer_to_index(col);
164 }
165
166 /* reads full rect, converts indices */
167 static unsigned int *read_backbuf(short xmin, short ymin, short xmax, short ymax)
168 {
169         unsigned int *dr, *buf;
170         int a;
171         short xminc, yminc, xmaxc, ymaxc;
172         
173         /* clip */
174         if(xmin<0) xminc= 0; else xminc= xmin;
175         if(xmax>=curarea->winx) xmaxc= curarea->winx-1; else xmaxc= xmax;
176         if(xminc > xmaxc) return NULL;
177
178         if(ymin<0) yminc= 0; else yminc= ymin;
179         if(ymax>=curarea->winy) ymaxc= curarea->winy-1; else ymaxc= ymax;
180         if(yminc > ymaxc) return NULL;
181         
182         buf= MEM_mallocN( (xmaxc-xminc+1)*(ymaxc-yminc+1)*sizeof(int), "sample rect");
183
184         check_backbuf(); // actually not needed for apple
185         
186 #ifdef __APPLE__
187         glReadBuffer(GL_AUX0);
188 #endif
189         glReadPixels(curarea->winrct.xmin+xminc, curarea->winrct.ymin+yminc, (xmaxc-xminc+1), (ymaxc-yminc+1), GL_RGBA, GL_UNSIGNED_BYTE, buf);
190         glReadBuffer(GL_BACK);  
191
192         if(G.order==B_ENDIAN) IMB_convert_rgba_to_abgr((xmaxc-xminc+1)*(ymaxc-yminc+1), buf);
193
194         a= (xmaxc-xminc+1)*(ymaxc-yminc+1);
195         dr= buf;
196         while(a--) {
197                 if(*dr) *dr= framebuffer_to_index(*dr);
198                 dr++;
199         }
200         
201         /* put clipped result back, if needed */
202         if(xminc==xmin && xmaxc==xmax && yminc==ymin && ymaxc==ymax) return buf;
203         else {
204                 unsigned int *buf1= MEM_callocN( (xmax-xmin+1)*(ymax-ymin+1)*sizeof(int), "sample rect2");
205                 unsigned int *rd;
206                 short xs, ys;
207
208                 rd= buf;
209                 dr= buf1;
210                 
211                 for(ys= ymin; ys<=ymax; ys++) {
212                         for(xs= xmin; xs<=xmax; xs++, dr++) {
213                                 if( xs>=xminc && xs<=xmaxc && ys>=yminc && ys<=ymaxc) {
214                                         *dr= *rd;
215                                         rd++;
216                                 }
217                         }
218                 }
219                 MEM_freeN(buf);
220                 return buf1;
221         }
222         
223         return buf;
224 }
225
226
227 /* smart function to sample a rect spiralling outside, nice for backbuf selection */
228 static unsigned int sample_backbuf_rect(short mval[2], int size, unsigned int min, unsigned int max, short *dist)
229 {
230         unsigned int *buf, *bufmin, *bufmax;
231         int minx, miny;
232         int a, b, rc, nr, amount, dirvec[4][2];
233         short distance=0;
234         unsigned int index = 0;
235         
236         amount= (size-1)/2;
237
238         minx = mval[0]-(amount+1);
239         miny = mval[1]-(amount+1);
240         buf = read_backbuf(minx, miny, minx+size-1, miny+size-1);
241         if (!buf)
242                 return 0;
243
244         rc= 0;
245         
246         dirvec[0][0]= 1; dirvec[0][1]= 0;
247         dirvec[1][0]= 0; dirvec[1][1]= -size;
248         dirvec[2][0]= -1; dirvec[2][1]= 0;
249         dirvec[3][0]= 0; dirvec[3][1]= size;
250         
251         bufmin= buf;
252         bufmax= buf+ size*size;
253         buf+= amount*size+ amount;
254         
255         for(nr=1; nr<=size; nr++) {
256                 
257                 for(a=0; a<2; a++) {
258                         for(b=0; b<nr; b++, distance++) {
259                                 if (*buf && *buf>=min && *buf<max) {
260                                         *dist= (short) sqrt( (float)distance ); // XXX, this distance is wrong - zr
261                                         index = *buf - min+1; // messy yah, but indices start at 1
262                                         goto exit;
263                                 }
264                                 
265                                 buf+= (dirvec[rc][0]+dirvec[rc][1]);
266                                 
267                                 if(buf<bufmin || buf>=bufmax) {
268                                         goto exit;
269                                 }
270                         }
271                         rc++;
272                         rc &= 3;
273                 }
274         }
275
276 exit:
277         MEM_freeN(bufmin);
278         return index;
279 }
280
281 /* facilities for border select and circle select */
282 static char *selbuf= NULL;
283
284 /* opengl doesn't support concave... */
285 static void draw_triangulated(short mcords[][2], short tot)
286 {
287         ListBase lb={NULL, NULL};
288         DispList *dl;
289         float *fp;
290         int a;
291         
292         /* make displist */
293         dl= MEM_callocN(sizeof(DispList), "poly disp");
294         dl->type= DL_POLY;
295         dl->parts= 1;
296         dl->nr= tot;
297         dl->verts= fp=  MEM_callocN(tot*3*sizeof(float), "poly verts");
298         BLI_addtail(&lb, dl);
299         
300         for(a=0; a<tot; a++, fp+=3) {
301                 fp[0]= (float)mcords[a][0];
302                 fp[1]= (float)mcords[a][1];
303         }
304         
305         /* do the fill */
306         filldisplist(&lb, &lb);
307
308         /* do the draw */
309         dl= lb.first;   // filldisplist adds in head of list
310         if(dl->type==DL_INDEX3) {
311                 int *index;
312                 
313                 a= dl->parts;
314                 fp= dl->verts;
315                 index= dl->index;
316                 glBegin(GL_TRIANGLES);
317                 while(a--) {
318                         glVertex3fv(fp+3*index[0]);
319                         glVertex3fv(fp+3*index[1]);
320                         glVertex3fv(fp+3*index[2]);
321                         index+= 3;
322                 }
323                 glEnd();
324         }
325         
326         freedisplist(&lb);
327 }
328
329
330 /* reads rect, and builds selection array for quick lookup */
331 /* returns if all is OK */
332 int EM_init_backbuf_border(short xmin, short ymin, short xmax, short ymax)
333 {
334         unsigned int *buf, *dr;
335         int a;
336         
337         if(G.obedit==NULL || G.vd->drawtype<OB_SOLID || (G.vd->flag & V3D_ZBUF_SELECT)==0) return 0;
338         if(em_vertoffs==0) return 0;
339         
340         dr= buf= read_backbuf(xmin, ymin, xmax, ymax);
341         if(buf==NULL) return 0;
342         
343         /* build selection lookup */
344         selbuf= MEM_callocN(em_vertoffs+1, "selbuf");
345         
346         a= (xmax-xmin+1)*(ymax-ymin+1);
347         while(a--) {
348                 if(*dr>0 && *dr<=em_vertoffs) 
349                         selbuf[*dr]= 1;
350                 dr++;
351         }
352         MEM_freeN(buf);
353         return 1;
354 }
355
356 int EM_check_backbuf(unsigned int index)
357 {
358         if(selbuf==NULL) return 1;
359         if(index>0 && index<=em_vertoffs)
360                 return selbuf[index];
361         return 0;
362 }
363
364 void EM_free_backbuf(void)
365 {
366         if(selbuf) MEM_freeN(selbuf);
367         selbuf= NULL;
368 }
369
370 /* mcords is a polygon mask
371    - grab backbuffer,
372    - draw with black in backbuffer, 
373    - grab again and compare
374    returns 'OK' 
375 */
376 int EM_mask_init_backbuf_border(short mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax)
377 {
378         unsigned int *buf, *bufmask, *dr, *drm;
379         int a;
380         
381         /* method in use for face selecting too */
382         if(G.obedit==NULL) {
383                 if(G.f & G_FACESELECT);
384                 else return 0;
385         }
386         else if(G.vd->drawtype<OB_SOLID || (G.vd->flag & V3D_ZBUF_SELECT)==0) return 0;
387
388         if(em_vertoffs==0) return 0;
389         
390         dr= buf= read_backbuf(xmin, ymin, xmax, ymax);
391         if(buf==NULL) return 0;
392
393         /* draw the mask */
394 #ifdef __APPLE__
395         glDrawBuffer(GL_AUX0);
396 #endif
397         glDisable(GL_DEPTH_TEST);
398         
399         persp(PERSP_WIN);
400         glColor3ub(0, 0, 0);
401         
402         /* yah, opengl doesn't do concave... tsk! */
403         draw_triangulated(mcords, tot); 
404         
405         glBegin(GL_LINE_LOOP);  // for zero sized masks, lines
406         for(a=0; a<tot; a++) glVertex2s(mcords[a][0], mcords[a][1]);
407         glEnd();
408         
409         persp(PERSP_VIEW);
410         glFinish();     // to be sure readpixels sees mask
411         
412         glDrawBuffer(GL_BACK);
413         
414         /* grab mask */
415         drm= bufmask= read_backbuf(xmin, ymin, xmax, ymax);
416         if(bufmask==NULL) return 0; // only when mem alloc fails, go crash somewhere else!
417         
418         /* build selection lookup */
419         selbuf= MEM_callocN(em_vertoffs+1, "selbuf");
420         
421         a= (xmax-xmin+1)*(ymax-ymin+1);
422         while(a--) {
423                 if(*dr>0 && *dr<=em_vertoffs && *drm==0) selbuf[*dr]= 1;
424                 dr++; drm++;
425         }
426         MEM_freeN(buf);
427         MEM_freeN(bufmask);
428         return 1;
429         
430 }
431
432 /* circle shaped sample area */
433 int EM_init_backbuf_circle(short xs, short ys, short rads)
434 {
435         unsigned int *buf, *dr;
436         short xmin, ymin, xmax, ymax, xc, yc;
437         int radsq;
438         
439         /* method in use for face selecting too */
440         if(G.obedit==NULL) {
441                 if(G.f & G_FACESELECT);
442                 else return 0;
443         }
444         else if(G.vd->drawtype<OB_SOLID || (G.vd->flag & V3D_ZBUF_SELECT)==0) return 0;
445         if(em_vertoffs==0) return 0;
446         
447         xmin= xs-rads; xmax= xs+rads;
448         ymin= ys-rads; ymax= ys+rads;
449         dr= buf= read_backbuf(xmin, ymin, xmax, ymax);
450         if(buf==NULL) return 0;
451         
452         /* build selection lookup */
453         selbuf= MEM_callocN(em_vertoffs+1, "selbuf");
454         radsq= rads*rads;
455         for(yc= -rads; yc<=rads; yc++) {
456                 for(xc= -rads; xc<=rads; xc++, dr++) {
457                         if(xc*xc + yc*yc < radsq) {
458                                 if(*dr>0 && *dr<=em_vertoffs) selbuf[*dr]= 1;
459                         }
460                 }
461         }
462
463         MEM_freeN(buf);
464         return 1;
465         
466 }
467
468 static void findnearestvert__doClosest(void *userData, EditVert *eve, int x, int y, int index)
469 {
470         struct { short mval[2], pass, select, dist; int lastIndex, closestIndex; EditVert *closest; } *data = userData;
471
472         if (data->pass==0) {
473                 if (index<=data->lastIndex)
474                         return;
475         } else {
476                 if (index>data->lastIndex)
477                         return;
478         }
479
480         if (data->dist>3) {
481                 short temp = abs(data->mval[0] - x) + abs(data->mval[1]- y);
482                 if ((eve->f&1)==data->select) temp += 5;
483
484                 if (temp<data->dist) {
485                         data->dist = temp;
486                         data->closest = eve;
487                         data->closestIndex = index;
488                 }
489         }
490 }
491 static EditVert *findnearestvert(short *dist, short sel)
492 {
493         short mval[2];
494
495         getmouseco_areawin(mval);
496                 
497         if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) {
498                 short distance;
499                 unsigned int index = sample_backbuf_rect(mval, 50, em_wireoffs, 0xFFFFFF, &distance);
500                 EditVert *eve = BLI_findlink(&G.editMesh->verts, index-1);
501
502                 if (eve && distance < *dist) {
503                         *dist = distance;
504                         return eve;
505                 } else {
506                         return NULL;
507                 }
508         }
509         else {
510                 struct { short mval[2], pass, select, dist; int lastIndex, closestIndex; EditVert *closest; } data;
511                 static int lastSelectedIndex=0;
512                 static EditVert *lastSelected=NULL;
513
514                 if (lastSelected && BLI_findlink(&G.editMesh->verts, lastSelectedIndex)!=lastSelected) {
515                         lastSelectedIndex = 0;
516                         lastSelected = NULL;
517                 }
518
519                 data.lastIndex = lastSelectedIndex;
520                 data.mval[0] = mval[0];
521                 data.mval[1] = mval[1];
522                 data.select = sel;
523                 data.dist = *dist;
524                 data.closest = NULL;
525                 data.closestIndex = 0;
526
527                 data.pass = 0;
528                 mesh_foreachScreenVert(findnearestvert__doClosest, &data, 1);
529
530                 if (data.dist>3) {
531                         data.pass = 1;
532                         mesh_foreachScreenVert(findnearestvert__doClosest, &data, 1);
533                 }
534
535                 *dist = data.dist;
536                 lastSelected = data.closest;
537                 lastSelectedIndex = data.closestIndex;
538
539                 return data.closest;
540         }
541 }
542
543 /* returns labda for closest distance v1 to line-piece v2-v3 */
544 static float labda_PdistVL2Dfl( float *v1, float *v2, float *v3) 
545 {
546         float rc[2], len;
547         
548         rc[0]= v3[0]-v2[0];
549         rc[1]= v3[1]-v2[1];
550         len= rc[0]*rc[0]+ rc[1]*rc[1];
551         if(len==0.0f)
552                 return 0.0f;
553         
554         return ( rc[0]*(v1[0]-v2[0]) + rc[1]*(v1[1]-v2[1]) )/len;
555 }
556
557 /* note; uses G.vd, so needs active 3d window */
558 static void findnearestedge__doClosest(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index)
559 {
560         struct { float mval[2]; short dist; EditEdge *closest; } *data = userData;
561         float v1[2], v2[2];
562         short distance;
563                 
564         v1[0] = x0;
565         v1[1] = y0;
566         v2[0] = x1;
567         v2[1] = y1;
568                 
569         distance= PdistVL2Dfl(data->mval, v1, v2);
570                 
571         if(eed->f & SELECT) distance+=5;
572         if(distance < data->dist) {
573                 if(G.vd->flag & V3D_CLIPPING) {
574                         float labda= labda_PdistVL2Dfl(data->mval, v1, v2);
575                         float vec[3];
576
577                         vec[0]= eed->v1->co[0] + labda*(eed->v2->co[0] - eed->v1->co[0]);
578                         vec[1]= eed->v1->co[1] + labda*(eed->v2->co[1] - eed->v1->co[1]);
579                         vec[2]= eed->v1->co[2] + labda*(eed->v2->co[2] - eed->v1->co[2]);
580                         Mat4MulVecfl(G.obedit->obmat, vec);
581
582                         if(view3d_test_clipping(G.vd, vec)==0) {
583                                 data->dist = distance;
584                                 data->closest = eed;
585                         }
586                 }
587                 else {
588                         data->dist = distance;
589                         data->closest = eed;
590                 }
591         }
592 }
593 EditEdge *findnearestedge(short *dist)
594 {
595         short mval[2];
596                 
597         getmouseco_areawin(mval);
598
599         if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) {
600                 short distance;
601                 unsigned int index = sample_backbuf_rect(mval, 50, em_solidoffs, em_wireoffs, &distance);
602                 EditEdge *eed = BLI_findlink(&G.editMesh->edges, index-1);
603
604                 if (eed && distance<*dist) {
605                         *dist = distance;
606                         return eed;
607                 } else {
608                         return NULL;
609                 }
610         }
611         else {
612                 struct { float mval[2]; short dist; EditEdge *closest; } data;
613
614                 data.mval[0] = mval[0];
615                 data.mval[1] = mval[1];
616                 data.dist = *dist;
617                 data.closest = NULL;
618
619                 mesh_foreachScreenEdge(findnearestedge__doClosest, &data, 2);
620
621                 *dist = data.dist;
622                 return data.closest;
623         }
624 }
625
626 static void findnearestface__getDistance(void *userData, EditFace *efa, int x, int y, int index)
627 {
628         struct { short mval[2], dist; EditFace *toFace; } *data = userData;
629
630         if (efa==data->toFace) {
631                 short temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
632
633                 if (temp<data->dist)
634                         data->dist = temp;
635         }
636 }
637 static void findnearestface__doClosest(void *userData, EditFace *efa, int x, int y, int index)
638 {
639         struct { short mval[2], pass, dist; int lastIndex, closestIndex; EditFace *closest; } *data = userData;
640
641         if (data->pass==0) {
642                 if (index<=data->lastIndex)
643                         return;
644         } else {
645                 if (index>data->lastIndex)
646                         return;
647         }
648
649         if (data->dist>3) {
650                 short temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
651
652                 if (temp<data->dist) {
653                         data->dist = temp;
654                         data->closest = efa;
655                         data->closestIndex = index;
656                 }
657         }
658 }
659 static EditFace *findnearestface(short *dist)
660 {
661         short mval[2];
662
663         getmouseco_areawin(mval);
664
665         if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) {
666                 unsigned int index = sample_backbuf(mval[0], mval[1]);
667                 EditFace *efa = BLI_findlink(&G.editMesh->faces, index-1);
668
669                 if (efa) {
670                         struct { short mval[2], dist; EditFace *toFace; } data;
671
672                         data.mval[0] = mval[0];
673                         data.mval[1] = mval[1];
674                         data.dist = 0x7FFF;             // largest short
675                         data.toFace = efa;
676
677                         mesh_foreachScreenFace(findnearestface__getDistance, &data);
678
679                         if(G.scene->selectmode == SCE_SELECT_FACE || data.dist<*dist) { // only faces, no dist check
680                                 *dist= data.dist;
681                                 return efa;
682                         }
683                 }
684                 
685                 return NULL;
686         }
687         else {
688                 struct { short mval[2], pass, dist; int lastIndex, closestIndex; EditFace *closest; } data;
689                 static int lastSelectedIndex=0;
690                 static EditFace *lastSelected=NULL;
691
692                 if (lastSelected && BLI_findlink(&G.editMesh->faces, lastSelectedIndex)!=lastSelected) {
693                         lastSelectedIndex = 0;
694                         lastSelected = NULL;
695                 }
696
697                 data.lastIndex = lastSelectedIndex;
698                 data.mval[0] = mval[0];
699                 data.mval[1] = mval[1];
700                 data.dist = *dist;
701                 data.closest = NULL;
702                 data.closestIndex = 0;
703
704                 data.pass = 0;
705                 mesh_foreachScreenFace(findnearestface__doClosest, &data);
706
707                 if (data.dist>3) {
708                         data.pass = 1;
709                         mesh_foreachScreenFace(findnearestface__doClosest, &data);
710                 }
711
712                 *dist = data.dist;
713                 lastSelected = data.closest;
714                 lastSelectedIndex = data.closestIndex;
715
716                 return data.closest;
717         }
718 }
719
720 /* for interactivity, frontbuffer draw in current window */
721 static void draw_dm_mapped_vert__mapFunc(void *theVert, int index, float *co, float *no_f, short *no_s)
722 {
723         if (EM_get_vert_for_index(index)==theVert) {
724                 bglVertex3fv(co);
725         }
726 }
727 static void draw_dm_mapped_vert(DerivedMesh *dm, EditVert *eve)
728 {
729         EM_init_index_arrays(1, 0, 0);
730         bglBegin(GL_POINTS);
731         dm->foreachMappedVert(dm, draw_dm_mapped_vert__mapFunc, eve);
732         bglEnd();
733         EM_free_index_arrays();
734 }
735
736 static int draw_dm_mapped_edge__setDrawOptions(void *theEdge, int index)
737 {
738         return EM_get_edge_for_index(index)==theEdge;
739 }
740 static void draw_dm_mapped_edge(DerivedMesh *dm, EditEdge *eed)
741 {
742         EM_init_index_arrays(0, 1, 0);
743         dm->drawMappedEdges(dm, draw_dm_mapped_edge__setDrawOptions, eed);
744         EM_free_index_arrays();
745 }
746
747 static void draw_dm_mapped_face_center__mapFunc(void *theFace, int index, float *cent, float *no)
748 {
749         if (EM_get_face_for_index(index)==theFace) {
750                 bglVertex3fv(cent);
751         }
752 }
753 static void draw_dm_mapped_face_center(DerivedMesh *dm, EditFace *efa)
754 {
755         EM_init_index_arrays(0, 0, 1);
756         bglBegin(GL_POINTS);
757         dm->foreachMappedFaceCenter(dm, draw_dm_mapped_face_center__mapFunc, efa);
758         bglEnd();
759         EM_free_index_arrays();
760 }
761
762 static void unified_select_draw(EditVert *eve, EditEdge *eed, EditFace *efa)
763 {
764         int dmNeedsFree;
765         DerivedMesh *dm = editmesh_get_derived_cage(&dmNeedsFree);
766
767         glDrawBuffer(GL_FRONT);
768
769         persp(PERSP_VIEW);
770         
771         if(G.vd->flag & V3D_CLIPPING)
772                 view3d_set_clipping(G.vd);
773         
774         glPushMatrix();
775         mymultmatrix(G.obedit->obmat);
776         
777         /* face selected */
778         if(efa) {
779                 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
780                         glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
781                         
782                         if(efa->f & SELECT) BIF_ThemeColor(TH_VERTEX_SELECT);
783                         else BIF_ThemeColor(TH_VERTEX);
784                         
785                         bglBegin(GL_POINTS);
786                         bglVertex3fv(efa->v1->co);
787                         bglVertex3fv(efa->v2->co);
788                         bglVertex3fv(efa->v3->co);
789                         if(efa->v4) bglVertex3fv(efa->v4->co);
790                         bglEnd();
791                 }
792
793                 if(G.scene->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_FACE)) {
794                         if(efa->fgonf==0) {
795                                 BIF_ThemeColor((efa->f & SELECT)?TH_EDGE_SELECT:TH_WIRE);
796         
797                                 draw_dm_mapped_edge(dm, efa->e1);
798                                 draw_dm_mapped_edge(dm, efa->e2);
799                                 draw_dm_mapped_edge(dm, efa->e3);
800                                 if (efa->e4) {
801                                         draw_dm_mapped_edge(dm, efa->e4);
802                                 }
803                         }
804                 }
805                 
806                 if(G.scene->selectmode & SCE_SELECT_FACE) {
807                         if(efa->fgonf==0) {
808                                 glPointSize(BIF_GetThemeValuef(TH_FACEDOT_SIZE));
809                                 BIF_ThemeColor((efa->f & SELECT)?TH_FACE_DOT:TH_WIRE);
810
811                                 draw_dm_mapped_face_center(dm, efa);
812                         }
813                 }
814         }
815         /* edge selected */
816         if(eed) {
817                 if(G.scene->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_FACE)) {
818                         BIF_ThemeColor((eed->f & SELECT)?TH_EDGE_SELECT:TH_WIRE);
819
820                         draw_dm_mapped_edge(dm, eed);
821                 }
822                 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
823                         glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
824                         
825                         BIF_ThemeColor((eed->f & SELECT)?TH_VERTEX_SELECT:TH_VERTEX);
826                         
827                         draw_dm_mapped_vert(dm, eed->v1);
828                         draw_dm_mapped_vert(dm, eed->v2);
829                 }
830         }
831         if(eve) {
832                 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
833                         glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
834                         
835                         BIF_ThemeColor((eve->f & SELECT)?TH_VERTEX_SELECT:TH_VERTEX);
836                         
837                         draw_dm_mapped_vert(dm, eve);
838                 }
839         }
840
841         glPointSize(1.0);
842         glPopMatrix();
843
844         glFlush();
845         glDrawBuffer(GL_BACK);
846
847         if(G.vd->flag & V3D_CLIPPING)
848                 view3d_clr_clipping();
849         
850         /* signal that frontbuf differs from back */
851         curarea->win_swap= WIN_FRONT_OK;
852
853         if (dmNeedsFree) {
854                 dm->release(dm);
855         }
856 }
857
858
859 /* best distance based on screen coords. 
860    use g.scene->selectmode to define how to use 
861    selected vertices and edges get disadvantage
862    return 1 if found one
863 */
864 static int unified_findnearest(EditVert **eve, EditEdge **eed, EditFace **efa) 
865 {
866         short dist= 75;
867         
868         *eve= NULL;
869         *eed= NULL;
870         *efa= NULL;
871         
872         if(G.scene->selectmode & SCE_SELECT_VERTEX)
873                 *eve= findnearestvert(&dist, SELECT);
874         if(G.scene->selectmode & SCE_SELECT_FACE)
875                 *efa= findnearestface(&dist);
876
877         dist-= 20;      // since edges select lines, we give dots advantage of 20 pix
878         if(G.scene->selectmode & SCE_SELECT_EDGE)
879                 *eed= findnearestedge(&dist);
880
881         /* return only one of 3 pointers, for frontbuffer redraws */
882         if(*eed) {
883                 *efa= NULL; *eve= NULL;
884         }
885         else if(*efa) {
886                 *eve= NULL;
887         }
888         
889         return (*eve || *eed || *efa);
890 }
891
892 /* ****************  LOOP SELECTS *************** */
893
894 /* selects quads in loop direction of indicated edge */
895 /* only flush over edges with valence <= 2 */
896 void faceloop_select(EditEdge *startedge, int select)
897 {
898         EditMesh *em = G.editMesh;
899         EditEdge *eed;
900         EditFace *efa;
901         int looking= 1;
902         
903         /* in eed->f1 we put the valence (amount of faces in edge) */
904         /* in eed->f2 we put tagged flag as correct loop */
905         /* in efa->f1 we put tagged flag as correct to select */
906
907         for(eed= em->edges.first; eed; eed= eed->next) {
908                 eed->f1= 0;
909                 eed->f2= 0;
910         }
911         for(efa= em->faces.first; efa; efa= efa->next) {
912                 efa->f1= 0;
913                 if(efa->h==0) {
914                         efa->e1->f1++;
915                         efa->e2->f1++;
916                         efa->e3->f1++;
917                         if(efa->e4) efa->e4->f1++;
918                 }
919         }
920         
921         // tag startedge OK
922         startedge->f2= 1;
923         
924         while(looking) {
925                 looking= 0;
926                 
927                 for(efa= em->faces.first; efa; efa= efa->next) {
928                         if(efa->e4 && efa->f1==0) {     // not done quad
929                                 if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { // valence ok
930
931                                         // if edge tagged, select opposing edge and mark face ok
932                                         if(efa->e1->f2) {
933                                                 efa->e3->f2= 1;
934                                                 efa->f1= 1;
935                                                 looking= 1;
936                                         }
937                                         else if(efa->e2->f2) {
938                                                 efa->e4->f2= 1;
939                                                 efa->f1= 1;
940                                                 looking= 1;
941                                         }
942                                         if(efa->e3->f2) {
943                                                 efa->e1->f2= 1;
944                                                 efa->f1= 1;
945                                                 looking= 1;
946                                         }
947                                         if(efa->e4->f2) {
948                                                 efa->e2->f2= 1;
949                                                 efa->f1= 1;
950                                                 looking= 1;
951                                         }
952                                 }
953                         }
954                 }
955         }
956         
957         /* (de)select the faces */
958         if(select!=2) {
959                 for(efa= em->faces.first; efa; efa= efa->next) {
960                         if(efa->f1) EM_select_face(efa, select);
961                 }
962         }
963 }
964
965
966 /* helper for edgeloop_select, checks for eed->f2 tag in faces */
967 static int edge_not_in_tagged_face(EditEdge *eed)
968 {
969         EditMesh *em = G.editMesh;
970         EditFace *efa;
971         
972         for(efa= em->faces.first; efa; efa= efa->next) {
973                 if(efa->h==0) {
974                         if(efa->e1==eed || efa->e2==eed || efa->e3==eed || efa->e4==eed) {      // edge is in face
975                                 if(efa->e1->f2 || efa->e2->f2 || efa->e3->f2 || (efa->e4 && efa->e4->f2)) {     // face is tagged
976                                         return 0;
977                                 }
978                         }
979                 }
980         }
981         return 1;
982 }
983
984 /* selects or deselects edges that:
985 - if edges has 2 faces:
986         - has vertices with valence of 4
987         - not shares face with previous edge
988 - if edge has 1 face:
989         - has vertices with valence 4
990         - not shares face with previous edge
991         - but also only 1 face
992 - if edge no face:
993         - has vertices with valence 2
994 */
995 static void edgeloop_select(EditEdge *starteed, int select)
996 {
997         EditMesh *em = G.editMesh;
998         EditVert *eve;
999         EditEdge *eed;
1000         EditFace *efa;
1001         int looking= 1;
1002         
1003         /* in f1 we put the valence (amount of edges in a vertex, or faces in edge) */
1004         /* in eed->f2 and efa->f1 we put tagged flag as correct loop */
1005         for(eve= em->verts.first; eve; eve= eve->next) {
1006                 eve->f1= 0;
1007                 eve->f2= 0;
1008         }
1009         for(eed= em->edges.first; eed; eed= eed->next) {
1010                 eed->f1= 0;
1011                 eed->f2= 0;
1012                 if((eed->h & 1)==0) {   // fgon edges add to valence too
1013                         eed->v1->f1++; eed->v2->f1++;
1014                 }
1015         }
1016         for(efa= em->faces.first; efa; efa= efa->next) {
1017                 efa->f1= 0;
1018                 if(efa->h==0) {
1019                         efa->e1->f1++;
1020                         efa->e2->f1++;
1021                         efa->e3->f1++;
1022                         if(efa->e4) efa->e4->f1++;
1023                 }
1024         }
1025         
1026         /* looped edges & vertices get tagged f2 */
1027         starteed->f2= 1;
1028         if(starteed->v1->f1<5) starteed->v1->f2= 1;
1029         if(starteed->v2->f1<5) starteed->v2->f2= 1;
1030         /* sorry, first edge isnt even ok */
1031         if(starteed->v1->f2==0 && starteed->v2->f2==0) looking= 0;
1032         
1033         while(looking) {
1034                 looking= 0;
1035                 
1036                 /* find correct valence edges which are not tagged yet, but connect to tagged one */
1037                 for(eed= em->edges.first; eed; eed= eed->next) {
1038                         if(eed->h==0 && eed->f2==0) { // edge not hidden, not tagged
1039                                 if( (eed->v1->f1<5 && eed->v1->f2) || (eed->v2->f1<5 && eed->v2->f2)) { // valence of vertex OK, and is tagged
1040                                         /* new edge is not allowed to be in face with tagged edge */
1041                                         if(edge_not_in_tagged_face(eed)) {
1042                                                 if(eed->f1==starteed->f1) {     // same amount of faces
1043                                                         looking= 1;
1044                                                         eed->f2= 1;
1045                                                         if(eed->v2->f1<5) eed->v2->f2= 1;
1046                                                         if(eed->v1->f1<5) eed->v1->f2= 1;
1047                                                 }
1048                                         }
1049                                 }
1050                         }
1051                 }
1052         }
1053         /* and we do the select */
1054         for(eed= em->edges.first; eed; eed= eed->next) {
1055                 if(eed->f2) EM_select_edge(eed, select);
1056         }
1057 }
1058
1059 /* 
1060    Almostly exactly the same code as faceloop select
1061 */
1062 static void edgering_select(EditEdge *startedge, int select){
1063         EditMesh *em = G.editMesh;
1064         EditEdge *eed;
1065         EditFace *efa;
1066         int looking= 1;
1067         
1068         /* in eed->f1 we put the valence (amount of faces in edge) */
1069         /* in eed->f2 we put tagged flag as correct loop */
1070         /* in efa->f1 we put tagged flag as correct to select */
1071
1072         for(eed= em->edges.first; eed; eed= eed->next) {
1073                 eed->f1= 0;
1074                 eed->f2= 0;
1075         }
1076         for(efa= em->faces.first; efa; efa= efa->next) {
1077                 efa->f1= 0;
1078                 if(efa->h==0) {
1079                         efa->e1->f1++;
1080                         efa->e2->f1++;
1081                         efa->e3->f1++;
1082                         if(efa->e4) efa->e4->f1++;
1083                 }
1084         }
1085         
1086         // tag startedge OK
1087         startedge->f2= 1;
1088         
1089         while(looking) {
1090                 looking= 0;
1091                 
1092                 for(efa= em->faces.first; efa; efa= efa->next) {
1093                         if(efa->e4 && efa->f1==0) {     // not done quad
1094                                 if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { // valence ok
1095
1096                                         // if edge tagged, select opposing edge and mark face ok
1097                                         if(efa->e1->f2) {
1098                                                 efa->e3->f2= 1;
1099                                                 efa->f1= 1;
1100                                                 looking= 1;
1101                                         }
1102                                         else if(efa->e2->f2) {
1103                                                 efa->e4->f2= 1;
1104                                                 efa->f1= 1;
1105                                                 looking= 1;
1106                                         }
1107                                         if(efa->e3->f2) {
1108                                                 efa->e1->f2= 1;
1109                                                 efa->f1= 1;
1110                                                 looking= 1;
1111                                         }
1112                                         if(efa->e4->f2) {
1113                                                 efa->e2->f2= 1;
1114                                                 efa->f1= 1;
1115                                                 looking= 1;
1116                                         }
1117                                 }
1118                         }
1119                 }
1120         }
1121         
1122         /* (de)select the edges */
1123         for(eed= em->edges.first; eed; eed= eed->next) {
1124                 if(eed->f2) EM_select_edge(eed, select);
1125         }
1126 }
1127 /* ***************** MAIN MOUSE SELECTION ************** */
1128
1129 // just to have the functions nice together
1130 static void mouse_mesh_loop(void)
1131 {
1132         EditEdge *eed;
1133         short dist= 50;
1134         
1135         eed= findnearestedge(&dist);
1136         if(eed) {
1137                 
1138                 if((G.qual & LR_SHIFTKEY)==0) EM_clear_flag_all(SELECT);
1139                 
1140                 if((eed->f & SELECT)==0) EM_select_edge(eed, 1);
1141                 else if(G.qual & LR_SHIFTKEY) EM_select_edge(eed, 0);
1142
1143                 if(G.scene->selectmode & SCE_SELECT_FACE) {
1144                         faceloop_select(eed, eed->f & SELECT);
1145                 }
1146                 else if(G.scene->selectmode & SCE_SELECT_EDGE) {
1147             if(G.qual == (LR_CTRLKEY | LR_ALTKEY) || G.qual == (LR_CTRLKEY | LR_ALTKEY |LR_SHIFTKEY))
1148                         edgering_select(eed, eed->f & SELECT);
1149             else if(G.qual & LR_ALTKEY)
1150                         edgeloop_select(eed, eed->f & SELECT);
1151                 }
1152         else if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1153             if(G.qual == (LR_CTRLKEY | LR_ALTKEY) || G.qual == (LR_CTRLKEY | LR_ALTKEY |LR_SHIFTKEY))
1154                         edgering_select(eed, eed->f & SELECT);
1155             else if(G.qual & LR_ALTKEY)
1156                         edgeloop_select(eed, eed->f & SELECT);
1157                 }
1158
1159                 /* frontbuffer draw of last selected only */
1160                 unified_select_draw(NULL, eed, NULL);
1161                 
1162                 EM_selectmode_flush();
1163                 countall();
1164                 
1165                 allqueue(REDRAWVIEW3D, 0);
1166         }
1167 }
1168
1169
1170 /* here actual select happens */
1171 void mouse_mesh(void)
1172 {
1173         EditVert *eve;
1174         EditEdge *eed;
1175         EditFace *efa;
1176         
1177         if(G.qual & LR_ALTKEY) mouse_mesh_loop();
1178         else if(unified_findnearest(&eve, &eed, &efa)) {
1179                 
1180                 if((G.qual & LR_SHIFTKEY)==0) EM_clear_flag_all(SELECT);
1181                 
1182                 if(efa) {
1183                         
1184                         if( (efa->f & SELECT)==0 ) {
1185                                 EM_select_face_fgon(efa, 1);
1186                         }
1187                         else if(G.qual & LR_SHIFTKEY) {
1188                                 EM_select_face_fgon(efa, 0);
1189                         }
1190                 }
1191                 else if(eed) {
1192                         if((eed->f & SELECT)==0) {
1193                                 EM_select_edge(eed, 1);
1194                         }
1195                         else if(G.qual & LR_SHIFTKEY) {
1196                                 EM_select_edge(eed, 0);
1197                         }
1198                 }
1199                 else if(eve) {
1200                         if((eve->f & SELECT)==0) eve->f |= SELECT;
1201                         else if(G.qual & LR_SHIFTKEY) eve->f &= ~SELECT;
1202                 }
1203                 
1204                 /* frontbuffer draw of last selected only */
1205                 unified_select_draw(eve, eed, efa);
1206         
1207                 EM_selectmode_flush();
1208                 countall();
1209
1210                 allqueue(REDRAWVIEW3D, 0);
1211         }
1212
1213         rightmouse_transform();
1214 }
1215
1216
1217 static void selectconnectedAll(void)
1218 {
1219         EditMesh *em = G.editMesh;
1220         EditVert *v1,*v2;
1221         EditEdge *eed;
1222         short done=1, toggle=0;
1223
1224         if(em->edges.first==0) return;
1225         
1226         while(done==1) {
1227                 done= 0;
1228                 
1229                 toggle++;
1230                 if(toggle & 1) eed= em->edges.first;
1231                 else eed= em->edges.last;
1232                 
1233                 while(eed) {
1234                         v1= eed->v1;
1235                         v2= eed->v2;
1236                         if(eed->h==0) {
1237                                 if(v1->f & SELECT) {
1238                                         if( (v2->f & SELECT)==0 ) {
1239                                                 v2->f |= SELECT;
1240                                                 done= 1;
1241                                         }
1242                                 }
1243                                 else if(v2->f & SELECT) {
1244                                         if( (v1->f & SELECT)==0 ) {
1245                                                 v1->f |= SELECT;
1246                                                 done= 1;
1247                                         }
1248                                 }
1249                         }
1250                         if(toggle & 1) eed= eed->next;
1251                         else eed= eed->prev;
1252                 }
1253         }
1254
1255         /* now use vertex select flag to select rest */
1256         EM_select_flush();
1257         
1258         countall();
1259
1260         allqueue(REDRAWVIEW3D, 0);
1261         BIF_undo_push("Select Connected (All)");
1262 }
1263
1264 void selectconnected_mesh(int qual)
1265 {
1266         EditMesh *em = G.editMesh;
1267         EditVert *eve, *v1, *v2;
1268         EditEdge *eed;
1269         EditFace *efa;
1270         short done=1, sel, toggle=0;
1271
1272         if(em->edges.first==0) return;
1273
1274         if(qual & LR_CTRLKEY) {
1275                 selectconnectedAll();
1276                 return;
1277         }
1278
1279         
1280         if( unified_findnearest(&eve, &eed, &efa)==0 ) {
1281                 error("Nothing indicated ");
1282                 return;
1283         }
1284         
1285         sel= 1;
1286         if(qual & LR_SHIFTKEY) sel=0;
1287
1288         /* clear test flags */
1289         for(v1= em->verts.first; v1; v1= v1->next) v1->f1= 0;
1290         
1291         /* start vertex/face/edge */
1292         if(eve) eve->f1= 1;
1293         else if(eed) eed->v1->f1= eed->v2->f1= 1;
1294         else efa->v1->f1= efa->v2->f1= efa->v3->f1= 1;
1295         
1296         /* set flag f1 if affected */
1297         while(done==1) {
1298                 done= 0;
1299                 toggle++;
1300                 
1301                 if(toggle & 1) eed= em->edges.first;
1302                 else eed= em->edges.last;
1303                 
1304                 while(eed) {
1305                         v1= eed->v1;
1306                         v2= eed->v2;
1307                         
1308                         if(eed->h==0) {
1309                                 if(v1->f1 && v2->f1==0) {
1310                                         v2->f1= 1;
1311                                         done= 1;
1312                                 }
1313                                 else if(v1->f1==0 && v2->f1) {
1314                                         v1->f1= 1;
1315                                         done= 1;
1316                                 }
1317                         }
1318                         
1319                         if(toggle & 1) eed= eed->next;
1320                         else eed= eed->prev;
1321                 }
1322         }
1323         
1324         /* now use vertex f1 flag to select/deselect */
1325         for(eed= em->edges.first; eed; eed= eed->next) {
1326                 if(eed->v1->f1 && eed->v2->f1) 
1327                         EM_select_edge(eed, sel);
1328         }
1329         for(efa= em->faces.first; efa; efa= efa->next) {
1330                 if(efa->v1->f1 && efa->v2->f1 && efa->v3->f1 && (efa->v4==NULL || efa->v4->f1)) 
1331                         EM_select_face(efa, sel);
1332         }
1333         /* no flush needed, connected geometry is done */
1334         
1335         countall();
1336         
1337         allqueue(REDRAWVIEW3D, 0);
1338         BIF_undo_push("Select Linked");
1339         
1340 }
1341
1342 /* swap is 0 or 1, if 1 it hides not selected */
1343 void hide_mesh(int swap)
1344 {
1345         EditMesh *em = G.editMesh;
1346         EditVert *eve;
1347         EditEdge *eed;
1348         EditFace *efa;
1349         int a;
1350         
1351         if(G.obedit==0) return;
1352
1353         /* hide happens on least dominant select mode, and flushes up, not down! (helps preventing errors in subsurf) */
1354         /*  - vertex hidden, always means edge is hidden too
1355                 - edge hidden, always means face is hidden too
1356                 - face hidden, only set face hide
1357                 - then only flush back down what's absolute hidden
1358         */
1359         if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1360                 for(eve= em->verts.first; eve; eve= eve->next) {
1361                         if((eve->f & SELECT)!=swap) {
1362                                 eve->f &= ~SELECT;
1363                                 eve->h= 1;
1364                         }
1365                 }
1366         
1367                 for(eed= em->edges.first; eed; eed= eed->next) {
1368                         if(eed->v1->h || eed->v2->h) {
1369                                 eed->h |= 1;
1370                                 eed->f &= ~SELECT;
1371                         }
1372                 }
1373         
1374                 for(efa= em->faces.first; efa; efa= efa->next) {
1375                         if(efa->e1->h || efa->e2->h || efa->e3->h || (efa->e4 && efa->e4->h)) {
1376                                 efa->h= 1;
1377                                 efa->f &= ~SELECT;
1378                         }
1379                 }
1380         }
1381         else if(G.scene->selectmode & SCE_SELECT_EDGE) {
1382
1383                 for(eed= em->edges.first; eed; eed= eed->next) {
1384                         if((eed->f & SELECT)!=swap) {
1385                                 eed->h |= 1;
1386                                 EM_select_edge(eed, 0);
1387                         }
1388                 }
1389
1390                 for(efa= em->faces.first; efa; efa= efa->next) {
1391                         if(efa->e1->h || efa->e2->h || efa->e3->h || (efa->e4 && efa->e4->h)) {
1392                                 efa->h= 1;
1393                                 efa->f &= ~SELECT;
1394                         }
1395                 }
1396         }
1397         else {
1398
1399                 for(efa= em->faces.first; efa; efa= efa->next) {
1400                         if((efa->f & SELECT)!=swap) {
1401                                 efa->h= 1;
1402                                 EM_select_face(efa, 0);
1403                         }
1404                 }
1405         }
1406         
1407         /* flush down, only whats 100% hidden */
1408         for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1409         for(eed= em->edges.first; eed; eed= eed->next) eed->f1= 0;
1410         
1411         if(G.scene->selectmode & SCE_SELECT_FACE) {
1412                 for(efa= em->faces.first; efa; efa= efa->next) {
1413                         if(efa->h) a= 1; else a= 2;
1414                         efa->e1->f1 |= a;
1415                         efa->e2->f1 |= a;
1416                         efa->e3->f1 |= a;
1417                         if(efa->e4) efa->e4->f1 |= a;
1418                 }
1419         }
1420         
1421         if(G.scene->selectmode >= SCE_SELECT_EDGE) {
1422                 for(eed= em->edges.first; eed; eed= eed->next) {
1423                         if(eed->f1==1) eed->h |= 1;
1424                         if(eed->h & 1) a= 1; else a= 2;
1425                         eed->v1->f1 |= a;
1426                         eed->v2->f1 |= a;
1427                 }
1428         }
1429
1430         if(G.scene->selectmode >= SCE_SELECT_VERTEX) {
1431                 for(eve= em->verts.first; eve; eve= eve->next) {
1432                         if(eve->f1==1) eve->h= 1;
1433                 }
1434         }
1435                 
1436         allqueue(REDRAWVIEW3D, 0);
1437         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);     
1438         BIF_undo_push("Hide");
1439 }
1440
1441
1442 void reveal_mesh(void)
1443 {
1444         EditMesh *em = G.editMesh;
1445         EditVert *eve;
1446         EditEdge *eed;
1447         EditFace *efa;
1448         
1449         if(G.obedit==0) return;
1450
1451         for(eve= em->verts.first; eve; eve= eve->next) {
1452                 if(eve->h) {
1453                         eve->h= 0;
1454                         eve->f |= SELECT;
1455                 }
1456         }
1457         for(eed= em->edges.first; eed; eed= eed->next) {
1458                 if(eed->h & 1) {
1459                         eed->h &= ~1;
1460                         if(G.scene->selectmode & SCE_SELECT_VERTEX); 
1461                         else EM_select_edge(eed, 1);
1462                 }
1463         }
1464         for(efa= em->faces.first; efa; efa= efa->next) {
1465                 if(efa->h) {
1466                         efa->h= 0;
1467                         if(G.scene->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_VERTEX)); 
1468                         else EM_select_face(efa, 1);
1469                 }
1470         }
1471
1472         EM_fgon_flags();        // redo flags and indices for fgons
1473         EM_selectmode_flush();
1474         
1475         allqueue(REDRAWVIEW3D, 0);
1476         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);     
1477         BIF_undo_push("Reveal");
1478 }
1479
1480 void select_faces_by_numverts(int numverts)
1481 {
1482         EditMesh *em = G.editMesh;
1483         EditFace *efa;
1484
1485         /* Selects isolated verts, and edges that do not have 2 neighboring
1486          * faces
1487          */
1488         
1489         if(G.scene->selectmode!=SCE_SELECT_FACE) {
1490                 error("Only works in face selection mode");
1491                 return;
1492         }
1493
1494         efa= em->faces.first;
1495         while(efa) {
1496                 if (efa->e4) {
1497                         EM_select_face(efa, (numverts==4) );
1498                 }
1499                 else if (efa->e3) {
1500                         EM_select_face(efa, (numverts==3) );
1501                 }
1502                 else 
1503                         EM_select_face(efa, (numverts!=3) && (numverts!=4) );
1504                 efa= efa->next;
1505         }
1506
1507         countall();
1508         addqueue(curarea->win,  REDRAW, 0);
1509
1510         if (numverts==3)
1511                 BIF_undo_push("Select Triangles");
1512         else if (numverts==4)
1513                 BIF_undo_push("Select Quads");
1514         else
1515                 BIF_undo_push("Select non-Triangles/Quads");
1516 }
1517
1518 void select_non_manifold(void)
1519 {
1520         EditMesh *em = G.editMesh;
1521         EditVert *eve;
1522         EditEdge *eed;
1523         EditFace *efa;
1524
1525         /* Selects isolated verts, and edges that do not have 2 neighboring
1526          * faces
1527          */
1528         
1529         if(G.scene->selectmode==SCE_SELECT_FACE) {
1530                 error("Doesn't work in face selection mode");
1531                 return;
1532         }
1533
1534         eve= em->verts.first;
1535         while(eve) {
1536                 /* this will count how many edges are connected
1537                  * to this vert */
1538                 eve->f1= 0;
1539                 eve= eve->next;
1540         }
1541
1542         eed= em->edges.first;
1543         while(eed) {
1544                 /* this will count how many faces are connected to
1545                  * this edge */
1546                 eed->f1= 0;
1547                 /* increase edge count for verts */
1548                 ++eed->v1->f1;
1549                 ++eed->v2->f1;
1550                 eed= eed->next;
1551         }
1552
1553         efa= em->faces.first;
1554         while(efa) {
1555                 /* increase face count for edges */
1556                 ++efa->e1->f1;
1557                 ++efa->e2->f1;
1558                 ++efa->e3->f1;
1559                 if (efa->e4)
1560                         ++efa->e4->f1;                  
1561                 efa= efa->next;
1562         }
1563
1564         /* select verts that are attached to an edge that does not
1565          * have 2 neighboring faces */
1566         eed= em->edges.first;
1567         while(eed) {
1568                 if (eed->h==0 && eed->f1 != 2) {
1569                         EM_select_edge(eed, 1);
1570                 }
1571                 eed= eed->next;
1572         }
1573
1574         /* select isolated verts */
1575         eve= em->verts.first;
1576         while(eve) {
1577                 if (eve->f1 == 0) {
1578                         if (!eve->h) eve->f |= SELECT;
1579                 }
1580                 eve= eve->next;
1581         }
1582
1583         countall();
1584         addqueue(curarea->win,  REDRAW, 0);
1585         BIF_undo_push("Select Non Manifold");
1586 }
1587
1588 void selectswap_mesh(void) /* UI level */
1589 {
1590         EditMesh *em = G.editMesh;
1591         EditVert *eve;
1592         EditEdge *eed;
1593         EditFace *efa;
1594         
1595         if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1596
1597                 for(eve= em->verts.first; eve; eve= eve->next) {
1598                         if(eve->h==0) {
1599                                 if(eve->f & SELECT) eve->f &= ~SELECT;
1600                                 else eve->f|= SELECT;
1601                         }
1602                 }
1603         }
1604         else if(G.scene->selectmode & SCE_SELECT_EDGE) {
1605                 for(eed= em->edges.first; eed; eed= eed->next) {
1606                         if(eed->h==0) {
1607                                 EM_select_edge(eed, !(eed->f & SELECT));
1608                         }
1609                 }
1610         }
1611         else {
1612                 for(efa= em->faces.first; efa; efa= efa->next) {
1613                         if(efa->h==0) {
1614                                 EM_select_face(efa, !(efa->f & SELECT));
1615                         }
1616                 }
1617         }
1618
1619         EM_selectmode_flush();
1620         
1621         countall();
1622         allqueue(REDRAWVIEW3D, 0);
1623
1624         BIF_undo_push("Select Swap");
1625         
1626 }
1627
1628 void deselectall_mesh(void)      /* this toggles!!!, UI level */
1629 {
1630         
1631         if(G.obedit->lay & G.vd->lay) {
1632
1633                 if( EM_nvertices_selected() ) {
1634                         EM_clear_flag_all(SELECT);
1635                         BIF_undo_push("Deselect All");
1636                 }
1637                 else  {
1638                         EM_set_flag_all(SELECT);
1639                         BIF_undo_push("Select All");
1640                 }
1641                 
1642                 countall();
1643                 allqueue(REDRAWVIEW3D, 0);
1644         }
1645 }
1646
1647 void select_more(void)
1648 {
1649         EditMesh *em = G.editMesh;
1650         EditVert *eve;
1651         EditEdge *eed;
1652         EditFace *efa;
1653         
1654         for(eve= em->verts.first; eve; eve= eve->next) {
1655                 if(eve->f & SELECT) eve->f1= 1;
1656                 else eve->f1 = 0;
1657         }
1658         
1659         /* set f1 flags in vertices to select 'more' */
1660         for(eed= em->edges.first; eed; eed= eed->next) {
1661                 if(eed->h==0) {
1662                         if (eed->v1->f & SELECT)
1663                                 eed->v2->f1 = 1;
1664                         if (eed->v2->f & SELECT)
1665                                 eed->v1->f1 = 1;
1666                 }
1667         }
1668
1669         /* new selected edges, but not in facemode */
1670         if(G.scene->selectmode <= SCE_SELECT_EDGE) {
1671                 
1672                 for(eed= em->edges.first; eed; eed= eed->next) {
1673                         if(eed->h==0) {
1674                                 if(eed->v1->f1 && eed->v2->f1) EM_select_edge(eed, 1);
1675                         }
1676                 }
1677         }
1678         /* new selected faces */
1679         for(efa= em->faces.first; efa; efa= efa->next) {
1680                 if(efa->h==0) {
1681                         if(efa->v1->f1 && efa->v2->f1 && efa->v3->f1 && (efa->v4==NULL || efa->v4->f1)) 
1682                                 EM_select_face(efa, 1);
1683                 }
1684         }
1685
1686         countall();
1687         addqueue(curarea->win,  REDRAW, 0);
1688         BIF_undo_push("Select More");
1689 }
1690
1691 void select_less(void)
1692 {
1693         EditMesh *em = G.editMesh;
1694         EditEdge *eed;
1695         EditFace *efa;
1696
1697         if(G.scene->selectmode <= SCE_SELECT_EDGE) {
1698                 /* eed->f1 == 1:  edge with a selected and deselected vert */ 
1699
1700                 for(eed= em->edges.first; eed; eed= eed->next) {
1701                         eed->f1= 0;
1702                         if(eed->h==0) {
1703                                 
1704                                 if ( !(eed->v1->f & SELECT) && (eed->v2->f & SELECT) ) 
1705                                         eed->f1= 1;
1706                                 if ( (eed->v1->f & SELECT) && !(eed->v2->f & SELECT) ) 
1707                                         eed->f1= 1;
1708                         }
1709                 }
1710                 
1711                 /* deselect edges with flag set */
1712                 for(eed= em->edges.first; eed; eed= eed->next) {
1713                         if (eed->h==0 && eed->f1 == 1) {
1714                                 EM_select_edge(eed, 0);
1715                         }
1716                 }
1717                 EM_deselect_flush();
1718                 
1719         }
1720         else {
1721                 /* deselect faces with 1 or more deselect edges */
1722                 /* eed->f1 == mixed selection edge */
1723                 for(eed= em->edges.first; eed; eed= eed->next) eed->f1= 0;
1724
1725                 for(efa= em->faces.first; efa; efa= efa->next) {
1726                         if(efa->h==0) {
1727                                 if(efa->f & SELECT) {
1728                                         efa->e1->f1 |= 1;
1729                                         efa->e2->f1 |= 1;
1730                                         efa->e3->f1 |= 1;
1731                                         if(efa->e4) efa->e4->f1 |= 1;
1732                                 }
1733                                 else {
1734                                         efa->e1->f1 |= 2;
1735                                         efa->e2->f1 |= 2;
1736                                         efa->e3->f1 |= 2;
1737                                         if(efa->e4) efa->e4->f1 |= 2;
1738                                 }
1739                         }
1740                 }
1741                 for(efa= em->faces.first; efa; efa= efa->next) {
1742                         if(efa->h==0) {
1743                                 if(efa->e1->f1==3 || efa->e2->f1==3 || efa->e3->f1==3 || (efa->e4 && efa->e4->f1==3)) { 
1744                                         EM_select_face(efa, 0);
1745                                 }
1746                         }
1747                 }
1748                 EM_selectmode_flush();
1749                 
1750         }
1751         
1752         countall();
1753         allqueue(REDRAWVIEW3D, 0);
1754 }
1755
1756
1757 void selectrandom_mesh(void) /* randomly selects a user-set % of vertices/edges/faces */
1758 {
1759         EditMesh *em = G.editMesh;
1760         EditVert *eve;
1761         EditEdge *eed;
1762         EditFace *efa;
1763         short randfac = 50;
1764
1765         if(G.obedit==NULL || (G.obedit->lay & G.vd->lay)==0) return;
1766
1767         /* Get the percentage of vertices to randomly select as 'randfac' */
1768         if(button(&randfac,0, 100,"Percentage:")==0) return;
1769
1770         BLI_srand( BLI_rand() ); /* random seed */
1771         
1772         if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1773                 for(eve= em->verts.first; eve; eve= eve->next) {
1774                         if(eve->h==0) {
1775                                 if ( (BLI_frand() * 100) < randfac) 
1776                                         eve->f |= SELECT;
1777                         }
1778                 }
1779         }
1780         else if(G.scene->selectmode & SCE_SELECT_EDGE) {
1781                 for(eed= em->edges.first; eed; eed= eed->next) {
1782                         if(eed->h==0) {
1783                                 if ( (BLI_frand() * 100) < randfac) 
1784                                         EM_select_edge(eed, 1);
1785                         }
1786                 }
1787         }
1788         else {
1789                 for(efa= em->faces.first; efa; efa= efa->next) {
1790                         if(efa->h==0) {
1791                                 if ( (BLI_frand() * 100) < randfac) 
1792                                         EM_select_face(efa, 1);
1793                         }
1794                 }
1795         }
1796         
1797         EM_selectmode_flush();
1798
1799         countall();
1800         allqueue(REDRAWVIEW3D, 0);
1801 }
1802
1803 void editmesh_select_by_material(int index) 
1804 {
1805         EditMesh *em = G.editMesh;
1806         EditFace *efa;
1807         
1808         for (efa=em->faces.first; efa; efa= efa->next) {
1809                 if (efa->mat_nr==index) {
1810                         EM_select_face(efa, 1);
1811                 }
1812         }
1813
1814         EM_selectmode_flush();
1815 }
1816
1817 void editmesh_deselect_by_material(int index) 
1818 {
1819         EditMesh *em = G.editMesh;
1820         EditFace *efa;
1821         
1822         for (efa=em->faces.first; efa; efa= efa->next) {
1823                 if (efa->mat_nr==index) {
1824                         EM_select_face(efa, 0);
1825                 }
1826         }
1827
1828         EM_selectmode_flush();
1829 }
1830
1831 void EM_selectmode_menu(void)
1832 {
1833         int val;
1834         
1835         if(G.scene->selectmode & SCE_SELECT_VERTEX) pupmenu_set_active(1);
1836         else if(G.scene->selectmode & SCE_SELECT_EDGE) pupmenu_set_active(2);
1837         else pupmenu_set_active(3);
1838         
1839         val= pupmenu("Select Mode%t|Vertices|Edges|Faces");
1840         if(val>0) {
1841                 if(val==1) G.scene->selectmode= SCE_SELECT_VERTEX;
1842                 else if(val==2) G.scene->selectmode= SCE_SELECT_EDGE;
1843                 else G.scene->selectmode= SCE_SELECT_FACE;
1844         
1845                 EM_selectmode_set(); // when mode changes
1846                 allqueue(REDRAWVIEW3D, 1);
1847         }
1848 }
1849
1850 /* ************************* SEAMS AND EDGES **************** */
1851
1852 void editmesh_mark_seam(int clear)
1853 {
1854         EditMesh *em= G.editMesh;
1855         EditEdge *eed;
1856
1857         /* auto-enable seams drawing */
1858         if(clear==0) {
1859                 if(!(G.f & G_DRAWSEAMS)) {
1860                         G.f |= G_DRAWSEAMS;
1861                         allqueue(REDRAWBUTSEDIT, 0);
1862                 }
1863         }
1864
1865         if(clear) {
1866                 eed= em->edges.first;
1867                 while(eed) {
1868                         if((eed->h==0) && (eed->f & SELECT)) {
1869                                 eed->seam = 0;
1870                         }
1871                         eed= eed->next;
1872                 }
1873                 BIF_undo_push("Mark Seam");
1874         }
1875         else {
1876                 eed= em->edges.first;
1877                 while(eed) {
1878                         if((eed->h==0) && (eed->f & SELECT)) {
1879                                 eed->seam = 1;
1880                         }
1881                         eed= eed->next;
1882                 }
1883                 BIF_undo_push("Clear Seam");
1884         }
1885
1886         allqueue(REDRAWVIEW3D, 0);
1887 }
1888
1889 void Edge_Menu() {
1890         short ret;
1891
1892         ret= pupmenu("Edge Specials%t|Mark Seam %x1|Clear Seam %x2|Rotate Edge CW%x3|Rotate Edge CCW%x4|Loopcut%x6|Edge Slide%x5");
1893
1894         switch(ret)
1895         {
1896         case 1:
1897                 editmesh_mark_seam(0);
1898                 break;
1899         case 2:
1900                 editmesh_mark_seam(1);
1901                 break;
1902         case 3:
1903                 edge_rotate_selected(2);
1904                 break;
1905         case 4:
1906                 edge_rotate_selected(1);
1907                 break;
1908         case 5:
1909                 EdgeSlide(0,0.0);
1910                 BIF_undo_push("EdgeSlide");
1911                 break;
1912         case 6:
1913                 CutEdgeloop(1);
1914                 BIF_undo_push("Loopcut New");
1915                 break;
1916         }
1917 }
1918
1919
1920 /* **************** NORMALS ************** */
1921
1922 void righthandfaces(int select) /* makes faces righthand turning */
1923 {
1924         EditMesh *em = G.editMesh;
1925         EditEdge *eed, *ed1, *ed2, *ed3, *ed4;
1926         EditFace *efa, *startvl;
1927         float maxx, nor[3], cent[3];
1928         int totsel, found, foundone, direct, turn, tria_nr;
1929
1930    /* based at a select-connected to witness loose objects */
1931
1932         /* count per edge the amount of faces */
1933
1934         /* find the ultimate left, front, upper face (not manhattan dist!!) */
1935         /* also evaluate both triangle cases in quad, since these can be non-flat */
1936
1937         /* put normal to the outside, and set the first direction flags in edges */
1938
1939         /* then check the object, and set directions / direction-flags: but only for edges with 1 or 2 faces */
1940         /* this is in fact the 'select connected' */
1941         
1942         /* in case (selected) faces were not done: start over with 'find the ultimate ...' */
1943
1944         waitcursor(1);
1945         
1946         eed= em->edges.first;
1947         while(eed) {
1948                 eed->f2= 0;             // edge direction
1949                 eed->f1= 0;             // counter
1950                 eed= eed->next;
1951         }
1952
1953         /* count faces and edges */
1954         totsel= 0;
1955         efa= em->faces.first;
1956         while(efa) {
1957                 if(select==0 || (efa->f & SELECT) ) {
1958                         efa->f1= 1;
1959                         totsel++;
1960                         efa->e1->f1++;
1961                         efa->e2->f1++;
1962                         efa->e3->f1++;
1963                         if(efa->v4) efa->e4->f1++;
1964                 }
1965                 else efa->f1= 0;
1966
1967                 efa= efa->next;
1968         }
1969
1970         while(totsel>0) {
1971                 /* from the outside to the inside */
1972
1973                 efa= em->faces.first;
1974                 startvl= NULL;
1975                 maxx= -1.0e10;
1976                 tria_nr= 0;
1977
1978                 while(efa) {
1979                         if(efa->f1) {
1980                                 CalcCent3f(cent, efa->v1->co, efa->v2->co, efa->v3->co);
1981                                 cent[0]= cent[0]*cent[0] + cent[1]*cent[1] + cent[2]*cent[2];
1982                                 
1983                                 if(cent[0]>maxx) {
1984                                         maxx= cent[0];
1985                                         startvl= efa;
1986                                         tria_nr= 0;
1987                                 }
1988                                 if(efa->v4) {
1989                                         CalcCent3f(cent, efa->v1->co, efa->v3->co, efa->v4->co);
1990                                         cent[0]= cent[0]*cent[0] + cent[1]*cent[1] + cent[2]*cent[2];
1991                                         
1992                                         if(cent[0]>maxx) {
1993                                                 maxx= cent[0];
1994                                                 startvl= efa;
1995                                                 tria_nr= 1;
1996                                         }
1997                                 }
1998                         }
1999                         efa= efa->next;
2000                 }
2001                 
2002                 /* set first face correct: calc normal */
2003                 
2004                 if(tria_nr==1) {
2005                         CalcNormFloat(startvl->v1->co, startvl->v3->co, startvl->v4->co, nor);
2006                         CalcCent3f(cent, startvl->v1->co, startvl->v3->co, startvl->v4->co);
2007                 } else {
2008                         CalcNormFloat(startvl->v1->co, startvl->v2->co, startvl->v3->co, nor);
2009                         CalcCent3f(cent, startvl->v1->co, startvl->v2->co, startvl->v3->co);
2010                 }
2011                 /* first normal is oriented this way or the other */
2012                 if(select) {
2013                         if(select==2) {
2014                                 if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] > 0.0) flipface(startvl);
2015                         }
2016                         else {
2017                                 if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] < 0.0) flipface(startvl);
2018                         }
2019                 }
2020                 else if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] < 0.0) flipface(startvl);
2021
2022
2023                 eed= startvl->e1;
2024                 if(eed->v1==startvl->v1) eed->f2= 1; 
2025                 else eed->f2= 2;
2026                 
2027                 eed= startvl->e2;
2028                 if(eed->v1==startvl->v2) eed->f2= 1; 
2029                 else eed->f2= 2;
2030                 
2031                 eed= startvl->e3;
2032                 if(eed->v1==startvl->v3) eed->f2= 1; 
2033                 else eed->f2= 2;
2034                 
2035                 eed= startvl->e4;
2036                 if(eed) {
2037                         if(eed->v1==startvl->v4) eed->f2= 1; 
2038                         else eed->f2= 2;
2039                 }
2040                 
2041                 startvl->f1= 0;
2042                 totsel--;
2043
2044                 /* test normals */
2045                 found= 1;
2046                 direct= 1;
2047                 while(found) {
2048                         found= 0;
2049                         if(direct) efa= em->faces.first;
2050                         else efa= em->faces.last;
2051                         while(efa) {
2052                                 if(efa->f1) {
2053                                         turn= 0;
2054                                         foundone= 0;
2055
2056                                         ed1= efa->e1;
2057                                         ed2= efa->e2;
2058                                         ed3= efa->e3;
2059                                         ed4= efa->e4;
2060
2061                                         if(ed1->f2) {
2062                                                 if(ed1->v1==efa->v1 && ed1->f2==1) turn= 1;
2063                                                 if(ed1->v2==efa->v1 && ed1->f2==2) turn= 1;
2064                                                 foundone= 1;
2065                                         }
2066                                         else if(ed2->f2) {
2067                                                 if(ed2->v1==efa->v2 && ed2->f2==1) turn= 1;
2068                                                 if(ed2->v2==efa->v2 && ed2->f2==2) turn= 1;
2069                                                 foundone= 1;
2070                                         }
2071                                         else if(ed3->f2) {
2072                                                 if(ed3->v1==efa->v3 && ed3->f2==1) turn= 1;
2073                                                 if(ed3->v2==efa->v3 && ed3->f2==2) turn= 1;
2074                                                 foundone= 1;
2075                                         }
2076                                         else if(ed4 && ed4->f2) {
2077                                                 if(ed4->v1==efa->v4 && ed4->f2==1) turn= 1;
2078                                                 if(ed4->v2==efa->v4 && ed4->f2==2) turn= 1;
2079                                                 foundone= 1;
2080                                         }
2081
2082                                         if(foundone) {
2083                                                 found= 1;
2084                                                 totsel--;
2085                                                 efa->f1= 0;
2086
2087                                                 if(turn) {
2088                                                         if(ed1->v1==efa->v1) ed1->f2= 2; 
2089                                                         else ed1->f2= 1;
2090                                                         if(ed2->v1==efa->v2) ed2->f2= 2; 
2091                                                         else ed2->f2= 1;
2092                                                         if(ed3->v1==efa->v3) ed3->f2= 2; 
2093                                                         else ed3->f2= 1;
2094                                                         if(ed4) {
2095                                                                 if(ed4->v1==efa->v4) ed4->f2= 2; 
2096                                                                 else ed4->f2= 1;
2097                                                         }
2098
2099                                                         flipface(efa);
2100
2101                                                 }
2102                                                 else {
2103                                                         if(ed1->v1== efa->v1) ed1->f2= 1; 
2104                                                         else ed1->f2= 2;
2105                                                         if(ed2->v1==efa->v2) ed2->f2= 1; 
2106                                                         else ed2->f2= 2;
2107                                                         if(ed3->v1==efa->v3) ed3->f2= 1; 
2108                                                         else ed3->f2= 2;
2109                                                         if(ed4) {
2110                                                                 if(ed4->v1==efa->v4) ed4->f2= 1; 
2111                                                                 else ed4->f2= 2;
2112                                                         }
2113                                                 }
2114                                         }
2115                                 }
2116                                 if(direct) efa= efa->next;
2117                                 else efa= efa->prev;
2118                         }
2119                         direct= 1-direct;
2120                 }
2121         }
2122
2123         recalc_editnormals();
2124         
2125         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2126         
2127         waitcursor(0);
2128 }
2129
2130
2131 /* ********** ALIGN WITH VIEW **************** */
2132
2133
2134 static void editmesh_calc_selvert_center(float cent_r[3])
2135 {
2136         EditMesh *em = G.editMesh;
2137         EditVert *eve;
2138         int nsel= 0;
2139
2140         cent_r[0]= cent_r[1]= cent_r[0]= 0.0;
2141
2142         for (eve= em->verts.first; eve; eve= eve->next) {
2143                 if (eve->f & SELECT) {
2144                         cent_r[0]+= eve->co[0];
2145                         cent_r[1]+= eve->co[1];
2146                         cent_r[2]+= eve->co[2];
2147                         nsel++;
2148                 }
2149         }
2150
2151         if (nsel) {
2152                 cent_r[0]/= nsel;
2153                 cent_r[1]/= nsel;
2154                 cent_r[2]/= nsel;
2155         }
2156 }
2157
2158 static int tface_is_selected(TFace *tf)
2159 {
2160         return (!(tf->flag & TF_HIDE) && (tf->flag & TF_SELECT));
2161 }
2162
2163 static int faceselect_nfaces_selected(Mesh *me)
2164 {
2165         int i, count= 0;
2166
2167         for (i=0; i<me->totface; i++)
2168                 if (tface_is_selected(&me->tface[i]))
2169                         count++;
2170
2171         return count;
2172 }
2173
2174         /* XXX, code for both these functions should be abstract,
2175          * then unified, then written for other things (like objects,
2176          * which would use same as vertices method), then added
2177          * to interface! Hoera! - zr
2178          */
2179 void faceselect_align_view_to_selected(View3D *v3d, Mesh *me, int axis)
2180 {
2181         if (!faceselect_nfaces_selected(me)) {
2182                 error("No faces selected.");
2183         } else {
2184                 float norm[3];
2185                 int i;
2186
2187                 norm[0]= norm[1]= norm[2]= 0.0;
2188                 for (i=0; i<me->totface; i++) {
2189                         MFace *mf= ((MFace*) me->mface) + i;
2190                         TFace *tf= ((TFace*) me->tface) + i;
2191         
2192                         if (tface_is_selected(tf)) {
2193                                 float *v1, *v2, *v3, fno[3];
2194
2195                                 v1= me->mvert[mf->v1].co;
2196                                 v2= me->mvert[mf->v2].co;
2197                                 v3= me->mvert[mf->v3].co;
2198                                 if (mf->v4) {
2199                                         float *v4= me->mvert[mf->v4].co;
2200                                         CalcNormFloat4(v1, v2, v3, v4, fno);
2201                                 } else {
2202                                         CalcNormFloat(v1, v2, v3, fno);
2203                                 }
2204
2205                                 norm[0]+= fno[0];
2206                                 norm[1]+= fno[1];
2207                                 norm[2]+= fno[2];
2208                         }
2209                 }
2210
2211                 view3d_align_axis_to_vector(v3d, axis, norm);
2212         }
2213 }
2214
2215 void editmesh_align_view_to_selected(View3D *v3d, int axis)
2216 {
2217         EditMesh *em = G.editMesh;
2218         int nselverts= EM_nvertices_selected();
2219
2220         if (nselverts<3) {
2221                 if (nselverts==0) {
2222                         error("No faces or vertices selected.");
2223                 } else {
2224                         error("At least one face or three vertices must be selected.");
2225                 }
2226         } else if (EM_nfaces_selected()) {
2227                 float norm[3];
2228                 EditFace *efa;
2229
2230                 norm[0]= norm[1]= norm[2]= 0.0;
2231                 for (efa= em->faces.first; efa; efa= efa->next) {
2232                         if (faceselectedAND(efa, SELECT)) {
2233                                 float fno[3];
2234                                 if (efa->v4) CalcNormFloat4(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co, fno);
2235                                 else CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, fno);
2236                                                 /* XXX, fixme, should be flipped intp a 
2237                                                  * consistent direction. -zr
2238                                                  */
2239                                 norm[0]+= fno[0];
2240                                 norm[1]+= fno[1];
2241                                 norm[2]+= fno[2];
2242                         }
2243                 }
2244
2245                 Mat4Mul3Vecfl(G.obedit->obmat, norm);
2246                 view3d_align_axis_to_vector(v3d, axis, norm);
2247         } else {
2248                 float cent[3], norm[3];
2249                 EditVert *eve, *leve= NULL;
2250
2251                 norm[0]= norm[1]= norm[2]= 0.0;
2252                 editmesh_calc_selvert_center(cent);
2253                 for (eve= em->verts.first; eve; eve= eve->next) {
2254                         if (eve->f & SELECT) {
2255                                 if (leve) {
2256                                         float tno[3];
2257                                         CalcNormFloat(cent, leve->co, eve->co, tno);
2258                                         
2259                                                 /* XXX, fixme, should be flipped intp a 
2260                                                  * consistent direction. -zr
2261                                                  */
2262                                         norm[0]+= tno[0];
2263                                         norm[1]+= tno[1];
2264                                         norm[2]+= tno[2];
2265                                 }
2266                                 leve= eve;
2267                         }
2268                 }
2269
2270                 Mat4Mul3Vecfl(G.obedit->obmat, norm);
2271                 view3d_align_axis_to_vector(v3d, axis, norm);
2272         }
2273 }
2274
2275 /* **************** VERTEX DEFORMS *************** */
2276
2277 void vertexsmooth(void)
2278 {
2279         EditMesh *em = G.editMesh;
2280         EditVert *eve;
2281         EditEdge *eed;
2282         float *adror, *adr, fac;
2283         float fvec[3];
2284         int teller=0;
2285
2286         if(G.obedit==0) return;
2287
2288         /* count */
2289         eve= em->verts.first;
2290         while(eve) {
2291                 if(eve->f & SELECT) teller++;
2292                 eve= eve->next;
2293         }
2294         if(teller==0) return;
2295         
2296         adr=adror= (float *)MEM_callocN(3*sizeof(float *)*teller, "vertsmooth");
2297         eve= em->verts.first;
2298         while(eve) {
2299                 if(eve->f & SELECT) {
2300                         eve->vn= (EditVert *)adr;
2301                         eve->f1= 0;
2302                         adr+= 3;
2303                 }
2304                 eve= eve->next;
2305         }
2306         
2307         eed= em->edges.first;
2308         while(eed) {
2309                 if( (eed->v1->f & SELECT) || (eed->v2->f & SELECT) ) {
2310                         fvec[0]= (eed->v1->co[0]+eed->v2->co[0])/2.0;
2311                         fvec[1]= (eed->v1->co[1]+eed->v2->co[1])/2.0;
2312                         fvec[2]= (eed->v1->co[2]+eed->v2->co[2])/2.0;
2313                         
2314                         if((eed->v1->f & SELECT) && eed->v1->f1<255) {
2315                                 eed->v1->f1++;
2316                                 VecAddf((float *)eed->v1->vn, (float *)eed->v1->vn, fvec);
2317                         }
2318                         if((eed->v2->f & SELECT) && eed->v2->f1<255) {
2319                                 eed->v2->f1++;
2320                                 VecAddf((float *)eed->v2->vn, (float *)eed->v2->vn, fvec);
2321                         }
2322                 }
2323                 eed= eed->next;
2324         }
2325
2326         eve= em->verts.first;
2327         while(eve) {
2328                 if(eve->f & SELECT) {
2329                         if(eve->f1) {
2330                                 adr= (float *)eve->vn;
2331                                 fac= 0.5/(float)eve->f1;
2332                                 
2333                                 eve->co[0]= 0.5*eve->co[0]+fac*adr[0];
2334                                 eve->co[1]= 0.5*eve->co[1]+fac*adr[1];
2335                                 eve->co[2]= 0.5*eve->co[2]+fac*adr[2];
2336                         }
2337                         eve->vn= 0;
2338                 }
2339                 eve= eve->next;
2340         }
2341         MEM_freeN(adror);
2342
2343         recalc_editnormals();
2344
2345         allqueue(REDRAWVIEW3D, 0);
2346         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2347         BIF_undo_push("Vertex Smooth");
2348 }
2349
2350 void vertexnoise(void)
2351 {
2352         EditMesh *em = G.editMesh;
2353         Material *ma;
2354         Tex *tex;
2355         EditVert *eve;
2356         float b2, ofs, vec[3];
2357
2358         if(G.obedit==0) return;
2359         
2360         ma= give_current_material(G.obedit, G.obedit->actcol);
2361         if(ma==0 || ma->mtex[0]==0 || ma->mtex[0]->tex==0) {
2362                 return;
2363         }
2364         tex= ma->mtex[0]->tex;
2365         
2366         ofs= tex->turbul/200.0;
2367         
2368         eve= (struct EditVert *)em->verts.first;
2369         while(eve) {
2370                 if(eve->f & SELECT) {
2371                         
2372                         if(tex->type==TEX_STUCCI) {
2373                                 
2374                                 b2= BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1], eve->co[2]);
2375                                 if(tex->stype) ofs*=(b2*b2);
2376                                 vec[0]= 0.2*(b2-BLI_hnoise(tex->noisesize, eve->co[0]+ofs, eve->co[1], eve->co[2]));
2377                                 vec[1]= 0.2*(b2-BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1]+ofs, eve->co[2]));
2378                                 vec[2]= 0.2*(b2-BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1], eve->co[2]+ofs));
2379                                 
2380                                 VecAddf(eve->co, eve->co, vec);
2381                         }
2382                         else {
2383                                 float tin, dum;
2384                                 externtex(ma->mtex[0], eve->co, &tin, &dum, &dum, &dum, &dum);
2385                                 eve->co[2]+= 0.05*tin;
2386                         }
2387                 }
2388                 eve= eve->next;
2389         }
2390
2391         recalc_editnormals();
2392         allqueue(REDRAWVIEW3D, 0);
2393         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2394         BIF_undo_push("Vertex Noise");
2395 }
2396
2397 void vertices_to_sphere(void)
2398 {
2399         EditMesh *em = G.editMesh;
2400         EditVert *eve;
2401         Object *ob= OBACT;
2402         float *curs, len, vec[3], cent[3], fac, facm, imat[3][3], bmat[3][3];
2403         int tot;
2404         short perc=100;
2405         
2406         if(ob==0) return;
2407         TEST_EDITMESH
2408         
2409         if(button(&perc, 1, 100, "Percentage:")==0) return;
2410         
2411         fac= perc/100.0;
2412         facm= 1.0-fac;
2413         
2414         Mat3CpyMat4(bmat, ob->obmat);
2415         Mat3Inv(imat, bmat);
2416
2417         /* centre */
2418         curs= give_cursor();
2419         cent[0]= curs[0]-ob->obmat[3][0];
2420         cent[1]= curs[1]-ob->obmat[3][1];
2421         cent[2]= curs[2]-ob->obmat[3][2];
2422         Mat3MulVecfl(imat, cent);
2423
2424         len= 0.0;
2425         tot= 0;
2426         eve= em->verts.first;
2427         while(eve) {
2428                 if(eve->f & SELECT) {
2429                         tot++;
2430                         len+= VecLenf(cent, eve->co);
2431                 }
2432                 eve= eve->next;
2433         }
2434         len/=tot;
2435         
2436         if(len==0.0) len= 10.0;
2437         
2438         eve= em->verts.first;
2439         while(eve) {
2440                 if(eve->f & SELECT) {
2441                         vec[0]= eve->co[0]-cent[0];
2442                         vec[1]= eve->co[1]-cent[1];
2443                         vec[2]= eve->co[2]-cent[2];
2444                         
2445                         Normalise(vec);
2446                         
2447                         eve->co[0]= fac*(cent[0]+vec[0]*len) + facm*eve->co[0];
2448                         eve->co[1]= fac*(cent[1]+vec[1]*len) + facm*eve->co[1];
2449                         eve->co[2]= fac*(cent[2]+vec[2]*len) + facm*eve->co[2];
2450                         
2451                 }
2452                 eve= eve->next;
2453         }
2454         
2455         recalc_editnormals();
2456         allqueue(REDRAWVIEW3D, 0);
2457         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2458         BIF_undo_push("To Sphere");
2459 }
2460