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