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