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