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