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