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