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