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