1. Moved Edgeloop Delete to Delete Menu out of Edge Specials
[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 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         if(select!=2) {
897                 for(efa= em->faces.first; efa; efa= efa->next) {
898                         if(efa->f1) EM_select_face(efa, select);
899                 }
900         }
901 }
902
903
904 /* helper for edgeloop_select, checks for eed->f2 tag in faces */
905 static int edge_not_in_tagged_face(EditEdge *eed)
906 {
907         EditMesh *em = G.editMesh;
908         EditFace *efa;
909         
910         for(efa= em->faces.first; efa; efa= efa->next) {
911                 if(efa->h==0) {
912                         if(efa->e1==eed || efa->e2==eed || efa->e3==eed || efa->e4==eed) {      // edge is in face
913                                 if(efa->e1->f2 || efa->e2->f2 || efa->e3->f2 || (efa->e4 && efa->e4->f2)) {     // face is tagged
914                                         return 0;
915                                 }
916                         }
917                 }
918         }
919         return 1;
920 }
921
922 /* selects or deselects edges that:
923 - if edges has 2 faces:
924         - has vertices with valence of 4
925         - not shares face with previous edge
926 - if edge has 1 face:
927         - has vertices with valence 4
928         - not shares face with previous edge
929         - but also only 1 face
930 - if edge no face:
931         - has vertices with valence 2
932 */
933 static void edgeloop_select(EditEdge *starteed, int select)
934 {
935         EditMesh *em = G.editMesh;
936         EditVert *eve;
937         EditEdge *eed;
938         EditFace *efa;
939         int looking= 1;
940         
941         /* in f1 we put the valence (amount of edges in a vertex, or faces in edge) */
942         /* in eed->f2 and efa->f1 we put tagged flag as correct loop */
943         for(eve= em->verts.first; eve; eve= eve->next) {
944                 eve->f1= 0;
945                 eve->f2= 0;
946         }
947         for(eed= em->edges.first; eed; eed= eed->next) {
948                 eed->f1= 0;
949                 eed->f2= 0;
950                 if((eed->h & 1)==0) {   // fgon edges add to valence too
951                         eed->v1->f1++; eed->v2->f1++;
952                 }
953         }
954         for(efa= em->faces.first; efa; efa= efa->next) {
955                 efa->f1= 0;
956                 if(efa->h==0) {
957                         efa->e1->f1++;
958                         efa->e2->f1++;
959                         efa->e3->f1++;
960                         if(efa->e4) efa->e4->f1++;
961                 }
962         }
963         
964         /* looped edges & vertices get tagged f2 */
965         starteed->f2= 1;
966         if(starteed->v1->f1<5) starteed->v1->f2= 1;
967         if(starteed->v2->f1<5) starteed->v2->f2= 1;
968         /* sorry, first edge isnt even ok */
969         if(starteed->v1->f2==0 && starteed->v2->f2==0) looking= 0;
970         
971         while(looking) {
972                 looking= 0;
973                 
974                 /* find correct valence edges which are not tagged yet, but connect to tagged one */
975                 for(eed= em->edges.first; eed; eed= eed->next) {
976                         if(eed->h==0 && eed->f2==0) { // edge not hidden, not tagged
977                                 if( (eed->v1->f1<5 && eed->v1->f2) || (eed->v2->f1<5 && eed->v2->f2)) { // valence of vertex OK, and is tagged
978                                         /* new edge is not allowed to be in face with tagged edge */
979                                         if(edge_not_in_tagged_face(eed)) {
980                                                 if(eed->f1==starteed->f1) {     // same amount of faces
981                                                         looking= 1;
982                                                         eed->f2= 1;
983                                                         if(eed->v2->f1<5) eed->v2->f2= 1;
984                                                         if(eed->v1->f1<5) eed->v1->f2= 1;
985                                                 }
986                                         }
987                                 }
988                         }
989                 }
990         }
991         /* and we do the select */
992         for(eed= em->edges.first; eed; eed= eed->next) {
993                 if(eed->f2) EM_select_edge(eed, select);
994         }
995 }
996
997 /* 
998    Almostly exactly the same code as faceloop select
999 */
1000 static void edgering_select(EditEdge *startedge, int select){
1001         EditMesh *em = G.editMesh;
1002         EditEdge *eed;
1003         EditFace *efa;
1004         int looking= 1;
1005         
1006         /* in eed->f1 we put the valence (amount of faces in edge) */
1007         /* in eed->f2 we put tagged flag as correct loop */
1008         /* in efa->f1 we put tagged flag as correct to select */
1009
1010         for(eed= em->edges.first; eed; eed= eed->next) {
1011                 eed->f1= 0;
1012                 eed->f2= 0;
1013         }
1014         for(efa= em->faces.first; efa; efa= efa->next) {
1015                 efa->f1= 0;
1016                 if(efa->h==0) {
1017                         efa->e1->f1++;
1018                         efa->e2->f1++;
1019                         efa->e3->f1++;
1020                         if(efa->e4) efa->e4->f1++;
1021                 }
1022         }
1023         
1024         // tag startedge OK
1025         startedge->f2= 1;
1026         
1027         while(looking) {
1028                 looking= 0;
1029                 
1030                 for(efa= em->faces.first; efa; efa= efa->next) {
1031                         if(efa->e4 && efa->f1==0) {     // not done quad
1032                                 if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { // valence ok
1033
1034                                         // if edge tagged, select opposing edge and mark face ok
1035                                         if(efa->e1->f2) {
1036                                                 efa->e3->f2= 1;
1037                                                 efa->f1= 1;
1038                                                 looking= 1;
1039                                         }
1040                                         else if(efa->e2->f2) {
1041                                                 efa->e4->f2= 1;
1042                                                 efa->f1= 1;
1043                                                 looking= 1;
1044                                         }
1045                                         if(efa->e3->f2) {
1046                                                 efa->e1->f2= 1;
1047                                                 efa->f1= 1;
1048                                                 looking= 1;
1049                                         }
1050                                         if(efa->e4->f2) {
1051                                                 efa->e2->f2= 1;
1052                                                 efa->f1= 1;
1053                                                 looking= 1;
1054                                         }
1055                                 }
1056                         }
1057                 }
1058         }
1059         
1060         /* (de)select the edges */
1061         for(eed= em->edges.first; eed; eed= eed->next) {
1062                 if(eed->f2) EM_select_edge(eed, select);
1063         }
1064 }
1065 /* ***************** MAIN MOUSE SELECTION ************** */
1066
1067 // just to have the functions nice together
1068 static void mouse_mesh_loop(void)
1069 {
1070         EditEdge *eed;
1071         short dist= 50;
1072         
1073         eed= findnearestedge(&dist);
1074         if(eed) {
1075                 
1076                 if((G.qual & LR_SHIFTKEY)==0) EM_clear_flag_all(SELECT);
1077                 
1078                 if((eed->f & SELECT)==0) EM_select_edge(eed, 1);
1079                 else if(G.qual & LR_SHIFTKEY) EM_select_edge(eed, 0);
1080
1081                 if(G.scene->selectmode & SCE_SELECT_FACE) {
1082                         faceloop_select(eed, eed->f & SELECT);
1083                 }
1084                 else if(G.scene->selectmode & SCE_SELECT_EDGE) {
1085             if(G.qual == (LR_CTRLKEY | LR_ALTKEY) || G.qual == (LR_CTRLKEY | LR_ALTKEY |LR_SHIFTKEY))
1086                         edgering_select(eed, eed->f & SELECT);
1087             else if(G.qual & LR_ALTKEY)
1088                         edgeloop_select(eed, eed->f & SELECT);
1089                 }
1090         else if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1091             if(G.qual == (LR_CTRLKEY | LR_ALTKEY) || G.qual == (LR_CTRLKEY | LR_ALTKEY |LR_SHIFTKEY))
1092                         edgering_select(eed, eed->f & SELECT);
1093             else if(G.qual & LR_ALTKEY)
1094                         edgeloop_select(eed, eed->f & SELECT);
1095                 }
1096
1097                 /* frontbuffer draw of last selected only */
1098                 unified_select_draw(NULL, eed, NULL);
1099                 
1100                 EM_selectmode_flush();
1101                 countall();
1102                 
1103                 allqueue(REDRAWVIEW3D, 0);
1104         }
1105 }
1106
1107
1108 /* here actual select happens */
1109 void mouse_mesh(void)
1110 {
1111         EditVert *eve;
1112         EditEdge *eed;
1113         EditFace *efa;
1114         
1115         if(G.qual & LR_ALTKEY) mouse_mesh_loop();
1116         else if(unified_findnearest(&eve, &eed, &efa)) {
1117                 
1118                 if((G.qual & LR_SHIFTKEY)==0) EM_clear_flag_all(SELECT);
1119                 
1120                 if(efa) {
1121                         
1122                         if( (efa->f & SELECT)==0 ) {
1123                                 EM_select_face_fgon(efa, 1);
1124                         }
1125                         else if(G.qual & LR_SHIFTKEY) {
1126                                 EM_select_face_fgon(efa, 0);
1127                         }
1128                 }
1129                 else if(eed) {
1130                         if((eed->f & SELECT)==0) {
1131                                 EM_select_edge(eed, 1);
1132                         }
1133                         else if(G.qual & LR_SHIFTKEY) {
1134                                 EM_select_edge(eed, 0);
1135                         }
1136                 }
1137                 else if(eve) {
1138                         if((eve->f & SELECT)==0) eve->f |= SELECT;
1139                         else if(G.qual & LR_SHIFTKEY) eve->f &= ~SELECT;
1140                 }
1141                 
1142                 /* frontbuffer draw of last selected only */
1143                 unified_select_draw(eve, eed, efa);
1144         
1145                 EM_selectmode_flush();
1146                 countall();
1147
1148                 allqueue(REDRAWVIEW3D, 0);
1149         }
1150
1151         rightmouse_transform();
1152 }
1153
1154
1155 static void selectconnectedAll(void)
1156 {
1157         EditMesh *em = G.editMesh;
1158         EditVert *v1,*v2;
1159         EditEdge *eed;
1160         short done=1, toggle=0;
1161
1162         if(em->edges.first==0) return;
1163         
1164         while(done==1) {
1165                 done= 0;
1166                 
1167                 toggle++;
1168                 if(toggle & 1) eed= em->edges.first;
1169                 else eed= em->edges.last;
1170                 
1171                 while(eed) {
1172                         v1= eed->v1;
1173                         v2= eed->v2;
1174                         if(eed->h==0) {
1175                                 if(v1->f & SELECT) {
1176                                         if( (v2->f & SELECT)==0 ) {
1177                                                 v2->f |= SELECT;
1178                                                 done= 1;
1179                                         }
1180                                 }
1181                                 else if(v2->f & SELECT) {
1182                                         if( (v1->f & SELECT)==0 ) {
1183                                                 v1->f |= SELECT;
1184                                                 done= 1;
1185                                         }
1186                                 }
1187                         }
1188                         if(toggle & 1) eed= eed->next;
1189                         else eed= eed->prev;
1190                 }
1191         }
1192
1193         /* now use vertex select flag to select rest */
1194         EM_select_flush();
1195         
1196         countall();
1197
1198         allqueue(REDRAWVIEW3D, 0);
1199         BIF_undo_push("Select Connected (All)");
1200 }
1201
1202 void selectconnected_mesh(int qual)
1203 {
1204         EditMesh *em = G.editMesh;
1205         EditVert *eve, *v1, *v2;
1206         EditEdge *eed;
1207         EditFace *efa;
1208         short done=1, sel, toggle=0;
1209
1210         if(em->edges.first==0) return;
1211
1212         if(qual & LR_CTRLKEY) {
1213                 selectconnectedAll();
1214                 return;
1215         }
1216
1217         
1218         if( unified_findnearest(&eve, &eed, &efa)==0 ) {
1219                 error("Nothing indicated ");
1220                 return;
1221         }
1222         
1223         sel= 1;
1224         if(qual & LR_SHIFTKEY) sel=0;
1225
1226         /* clear test flags */
1227         for(v1= em->verts.first; v1; v1= v1->next) v1->f1= 0;
1228         
1229         /* start vertex/face/edge */
1230         if(eve) eve->f1= 1;
1231         else if(eed) eed->v1->f1= eed->v2->f1= 1;
1232         else efa->v1->f1= efa->v2->f1= efa->v3->f1= 1;
1233         
1234         /* set flag f1 if affected */
1235         while(done==1) {
1236                 done= 0;
1237                 toggle++;
1238                 
1239                 if(toggle & 1) eed= em->edges.first;
1240                 else eed= em->edges.last;
1241                 
1242                 while(eed) {
1243                         v1= eed->v1;
1244                         v2= eed->v2;
1245                         
1246                         if(eed->h==0) {
1247                                 if(v1->f1 && v2->f1==0) {
1248                                         v2->f1= 1;
1249                                         done= 1;
1250                                 }
1251                                 else if(v1->f1==0 && v2->f1) {
1252                                         v1->f1= 1;
1253                                         done= 1;
1254                                 }
1255                         }
1256                         
1257                         if(toggle & 1) eed= eed->next;
1258                         else eed= eed->prev;
1259                 }
1260         }
1261         
1262         /* now use vertex f1 flag to select/deselect */
1263         for(eed= em->edges.first; eed; eed= eed->next) {
1264                 if(eed->v1->f1 && eed->v2->f1) 
1265                         EM_select_edge(eed, sel);
1266         }
1267         for(efa= em->faces.first; efa; efa= efa->next) {
1268                 if(efa->v1->f1 && efa->v2->f1 && efa->v3->f1 && (efa->v4==NULL || efa->v4->f1)) 
1269                         EM_select_face(efa, sel);
1270         }
1271         /* no flush needed, connected geometry is done */
1272         
1273         countall();
1274         
1275         allqueue(REDRAWVIEW3D, 0);
1276         BIF_undo_push("Select Linked");
1277         
1278 }
1279
1280 /* swap is 0 or 1, if 1 it hides not selected */
1281 void hide_mesh(int swap)
1282 {
1283         EditMesh *em = G.editMesh;
1284         EditVert *eve;
1285         EditEdge *eed;
1286         EditFace *efa;
1287         int a;
1288         
1289         if(G.obedit==0) return;
1290
1291         /* hide happens on least dominant select mode, and flushes up, not down! (helps preventing errors in subsurf) */
1292         /*  - vertex hidden, always means edge is hidden too
1293                 - edge hidden, always means face is hidden too
1294                 - face hidden, only set face hide
1295                 - then only flush back down what's absolute hidden
1296         */
1297         if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1298                 for(eve= em->verts.first; eve; eve= eve->next) {
1299                         if((eve->f & SELECT)!=swap) {
1300                                 eve->f &= ~SELECT;
1301                                 eve->h= 1;
1302                         }
1303                 }
1304         
1305                 for(eed= em->edges.first; eed; eed= eed->next) {
1306                         if(eed->v1->h || eed->v2->h) {
1307                                 eed->h |= 1;
1308                                 eed->f &= ~SELECT;
1309                         }
1310                 }
1311         
1312                 for(efa= em->faces.first; efa; efa= efa->next) {
1313                         if(efa->e1->h || efa->e2->h || efa->e3->h || (efa->e4 && efa->e4->h)) {
1314                                 efa->h= 1;
1315                                 efa->f &= ~SELECT;
1316                         }
1317                 }
1318         }
1319         else if(G.scene->selectmode & SCE_SELECT_EDGE) {
1320
1321                 for(eed= em->edges.first; eed; eed= eed->next) {
1322                         if((eed->f & SELECT)!=swap) {
1323                                 eed->h |= 1;
1324                                 EM_select_edge(eed, 0);
1325                         }
1326                 }
1327
1328                 for(efa= em->faces.first; efa; efa= efa->next) {
1329                         if(efa->e1->h || efa->e2->h || efa->e3->h || (efa->e4 && efa->e4->h)) {
1330                                 efa->h= 1;
1331                                 efa->f &= ~SELECT;
1332                         }
1333                 }
1334         }
1335         else {
1336
1337                 for(efa= em->faces.first; efa; efa= efa->next) {
1338                         if((efa->f & SELECT)!=swap) {
1339                                 efa->h= 1;
1340                                 EM_select_face(efa, 0);
1341                         }
1342                 }
1343         }
1344         
1345         /* flush down, only whats 100% hidden */
1346         for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1347         for(eed= em->edges.first; eed; eed= eed->next) eed->f1= 0;
1348         
1349         if(G.scene->selectmode & SCE_SELECT_FACE) {
1350                 for(efa= em->faces.first; efa; efa= efa->next) {
1351                         if(efa->h) a= 1; else a= 2;
1352                         efa->e1->f1 |= a;
1353                         efa->e2->f1 |= a;
1354                         efa->e3->f1 |= a;
1355                         if(efa->e4) efa->e4->f1 |= a;
1356                 }
1357         }
1358         
1359         if(G.scene->selectmode >= SCE_SELECT_EDGE) {
1360                 for(eed= em->edges.first; eed; eed= eed->next) {
1361                         if(eed->f1==1) eed->h |= 1;
1362                         if(eed->h & 1) a= 1; else a= 2;
1363                         eed->v1->f1 |= a;
1364                         eed->v2->f1 |= a;
1365                 }
1366         }
1367
1368         if(G.scene->selectmode >= SCE_SELECT_VERTEX) {
1369                 for(eve= em->verts.first; eve; eve= eve->next) {
1370                         if(eve->f1==1) eve->h= 1;
1371                 }
1372         }
1373                 
1374         allqueue(REDRAWVIEW3D, 0);
1375         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);     
1376         BIF_undo_push("Hide");
1377 }
1378
1379
1380 void reveal_mesh(void)
1381 {
1382         EditMesh *em = G.editMesh;
1383         EditVert *eve;
1384         EditEdge *eed;
1385         EditFace *efa;
1386         
1387         if(G.obedit==0) return;
1388
1389         for(eve= em->verts.first; eve; eve= eve->next) {
1390                 if(eve->h) {
1391                         eve->h= 0;
1392                         eve->f |= SELECT;
1393                 }
1394         }
1395         for(eed= em->edges.first; eed; eed= eed->next) {
1396                 if(eed->h & 1) {
1397                         eed->h &= ~1;
1398                         if(G.scene->selectmode & SCE_SELECT_VERTEX); 
1399                         else EM_select_edge(eed, 1);
1400                 }
1401         }
1402         for(efa= em->faces.first; efa; efa= efa->next) {
1403                 if(efa->h) {
1404                         efa->h= 0;
1405                         if(G.scene->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_VERTEX)); 
1406                         else EM_select_face(efa, 1);
1407                 }
1408         }
1409
1410         EM_fgon_flags();        // redo flags and indices for fgons
1411         EM_selectmode_flush();
1412         
1413         allqueue(REDRAWVIEW3D, 0);
1414         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);     
1415         BIF_undo_push("Reveal");
1416 }
1417
1418 void select_faces_by_numverts(int numverts)
1419 {
1420         EditMesh *em = G.editMesh;
1421         EditFace *efa;
1422
1423         /* Selects isolated verts, and edges that do not have 2 neighboring
1424          * faces
1425          */
1426         
1427         if(G.scene->selectmode!=SCE_SELECT_FACE) {
1428                 error("Only works in face selection mode");
1429                 return;
1430         }
1431
1432         efa= em->faces.first;
1433         while(efa) {
1434                 if (efa->e4) {
1435                         EM_select_face(efa, (numverts==4) );
1436                 }
1437                 else if (efa->e3) {
1438                         EM_select_face(efa, (numverts==3) );
1439                 }
1440                 else 
1441                         EM_select_face(efa, (numverts!=3) && (numverts!=4) );
1442                 efa= efa->next;
1443         }
1444
1445         countall();
1446         addqueue(curarea->win,  REDRAW, 0);
1447
1448         if (numverts==3)
1449                 BIF_undo_push("Select Triangles");
1450         else if (numverts==4)
1451                 BIF_undo_push("Select Quads");
1452         else
1453                 BIF_undo_push("Select non-Triangles/Quads");
1454 }
1455
1456 void select_non_manifold(void)
1457 {
1458         EditMesh *em = G.editMesh;
1459         EditVert *eve;
1460         EditEdge *eed;
1461         EditFace *efa;
1462
1463         /* Selects isolated verts, and edges that do not have 2 neighboring
1464          * faces
1465          */
1466         
1467         if(G.scene->selectmode==SCE_SELECT_FACE) {
1468                 error("Doesn't work in face selection mode");
1469                 return;
1470         }
1471
1472         eve= em->verts.first;
1473         while(eve) {
1474                 /* this will count how many edges are connected
1475                  * to this vert */
1476                 eve->f1= 0;
1477                 eve= eve->next;
1478         }
1479
1480         eed= em->edges.first;
1481         while(eed) {
1482                 /* this will count how many faces are connected to
1483                  * this edge */
1484                 eed->f1= 0;
1485                 /* increase edge count for verts */
1486                 ++eed->v1->f1;
1487                 ++eed->v2->f1;
1488                 eed= eed->next;
1489         }
1490
1491         efa= em->faces.first;
1492         while(efa) {
1493                 /* increase face count for edges */
1494                 ++efa->e1->f1;
1495                 ++efa->e2->f1;
1496                 ++efa->e3->f1;
1497                 if (efa->e4)
1498                         ++efa->e4->f1;                  
1499                 efa= efa->next;
1500         }
1501
1502         /* select verts that are attached to an edge that does not
1503          * have 2 neighboring faces */
1504         eed= em->edges.first;
1505         while(eed) {
1506                 if (eed->h==0 && eed->f1 != 2) {
1507                         EM_select_edge(eed, 1);
1508                 }
1509                 eed= eed->next;
1510         }
1511
1512         /* select isolated verts */
1513         eve= em->verts.first;
1514         while(eve) {
1515                 if (eve->f1 == 0) {
1516                         if (!eve->h) eve->f |= SELECT;
1517                 }
1518                 eve= eve->next;
1519         }
1520
1521         countall();
1522         addqueue(curarea->win,  REDRAW, 0);
1523         BIF_undo_push("Select Non Manifold");
1524 }
1525
1526 void selectswap_mesh(void) /* UI level */
1527 {
1528         EditMesh *em = G.editMesh;
1529         EditVert *eve;
1530         EditEdge *eed;
1531         EditFace *efa;
1532         
1533         if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1534
1535                 for(eve= em->verts.first; eve; eve= eve->next) {
1536                         if(eve->h==0) {
1537                                 if(eve->f & SELECT) eve->f &= ~SELECT;
1538                                 else eve->f|= SELECT;
1539                         }
1540                 }
1541         }
1542         else if(G.scene->selectmode & SCE_SELECT_EDGE) {
1543                 for(eed= em->edges.first; eed; eed= eed->next) {
1544                         if(eed->h==0) {
1545                                 EM_select_edge(eed, !(eed->f & SELECT));
1546                         }
1547                 }
1548         }
1549         else {
1550                 for(efa= em->faces.first; efa; efa= efa->next) {
1551                         if(efa->h==0) {
1552                                 EM_select_face(efa, !(efa->f & SELECT));
1553                         }
1554                 }
1555         }
1556
1557         EM_selectmode_flush();
1558         
1559         countall();
1560         allqueue(REDRAWVIEW3D, 0);
1561
1562         BIF_undo_push("Select Swap");
1563         
1564 }
1565
1566 void deselectall_mesh(void)      /* this toggles!!!, UI level */
1567 {
1568         
1569         if(G.obedit->lay & G.vd->lay) {
1570
1571                 if( EM_nvertices_selected() ) {
1572                         EM_clear_flag_all(SELECT);
1573                         BIF_undo_push("Deselect All");
1574                 }
1575                 else  {
1576                         EM_set_flag_all(SELECT);
1577                         BIF_undo_push("Select All");
1578                 }
1579                 
1580                 countall();
1581                 allqueue(REDRAWVIEW3D, 0);
1582         }
1583 }
1584
1585 void select_more(void)
1586 {
1587         EditMesh *em = G.editMesh;
1588         EditVert *eve;
1589         EditEdge *eed;
1590         EditFace *efa;
1591         
1592         for(eve= em->verts.first; eve; eve= eve->next) {
1593                 if(eve->f & SELECT) eve->f1= 1;
1594                 else eve->f1 = 0;
1595         }
1596         
1597         /* set f1 flags in vertices to select 'more' */
1598         for(eed= em->edges.first; eed; eed= eed->next) {
1599                 if(eed->h==0) {
1600                         if (eed->v1->f & SELECT)
1601                                 eed->v2->f1 = 1;
1602                         if (eed->v2->f & SELECT)
1603                                 eed->v1->f1 = 1;
1604                 }
1605         }
1606
1607         /* new selected edges, but not in facemode */
1608         if(G.scene->selectmode <= SCE_SELECT_EDGE) {
1609                 
1610                 for(eed= em->edges.first; eed; eed= eed->next) {
1611                         if(eed->h==0) {
1612                                 if(eed->v1->f1 && eed->v2->f1) EM_select_edge(eed, 1);
1613                         }
1614                 }
1615         }
1616         /* new selected faces */
1617         for(efa= em->faces.first; efa; efa= efa->next) {
1618                 if(efa->h==0) {
1619                         if(efa->v1->f1 && efa->v2->f1 && efa->v3->f1 && (efa->v4==NULL || efa->v4->f1)) 
1620                                 EM_select_face(efa, 1);
1621                 }
1622         }
1623
1624         countall();
1625         addqueue(curarea->win,  REDRAW, 0);
1626         BIF_undo_push("Select More");
1627 }
1628
1629 void select_less(void)
1630 {
1631         EditMesh *em = G.editMesh;
1632         EditEdge *eed;
1633         EditFace *efa;
1634
1635         if(G.scene->selectmode <= SCE_SELECT_EDGE) {
1636                 /* eed->f1 == 1:  edge with a selected and deselected vert */ 
1637
1638                 for(eed= em->edges.first; eed; eed= eed->next) {
1639                         eed->f1= 0;
1640                         if(eed->h==0) {
1641                                 
1642                                 if ( !(eed->v1->f & SELECT) && (eed->v2->f & SELECT) ) 
1643                                         eed->f1= 1;
1644                                 if ( (eed->v1->f & SELECT) && !(eed->v2->f & SELECT) ) 
1645                                         eed->f1= 1;
1646                         }
1647                 }
1648                 
1649                 /* deselect edges with flag set */
1650                 for(eed= em->edges.first; eed; eed= eed->next) {
1651                         if (eed->h==0 && eed->f1 == 1) {
1652                                 EM_select_edge(eed, 0);
1653                         }
1654                 }
1655                 EM_deselect_flush();
1656                 
1657         }
1658         else {
1659                 /* deselect faces with 1 or more deselect edges */
1660                 /* eed->f1 == mixed selection edge */
1661                 for(eed= em->edges.first; eed; eed= eed->next) eed->f1= 0;
1662
1663                 for(efa= em->faces.first; efa; efa= efa->next) {
1664                         if(efa->h==0) {
1665                                 if(efa->f & SELECT) {
1666                                         efa->e1->f1 |= 1;
1667                                         efa->e2->f1 |= 1;
1668                                         efa->e3->f1 |= 1;
1669                                         if(efa->e4) efa->e4->f1 |= 1;
1670                                 }
1671                                 else {
1672                                         efa->e1->f1 |= 2;
1673                                         efa->e2->f1 |= 2;
1674                                         efa->e3->f1 |= 2;
1675                                         if(efa->e4) efa->e4->f1 |= 2;
1676                                 }
1677                         }
1678                 }
1679                 for(efa= em->faces.first; efa; efa= efa->next) {
1680                         if(efa->h==0) {
1681                                 if(efa->e1->f1==3 || efa->e2->f1==3 || efa->e3->f1==3 || (efa->e4 && efa->e4->f1==3)) { 
1682                                         EM_select_face(efa, 0);
1683                                 }
1684                         }
1685                 }
1686                 EM_selectmode_flush();
1687                 
1688         }
1689         
1690         countall();
1691         allqueue(REDRAWVIEW3D, 0);
1692 }
1693
1694
1695 void selectrandom_mesh(void) /* randomly selects a user-set % of vertices/edges/faces */
1696 {
1697         EditMesh *em = G.editMesh;
1698         EditVert *eve;
1699         EditEdge *eed;
1700         EditFace *efa;
1701         short randfac = 50;
1702
1703         if(G.obedit==NULL || (G.obedit->lay & G.vd->lay)==0) return;
1704
1705         /* Get the percentage of vertices to randomly select as 'randfac' */
1706         if(button(&randfac,0, 100,"Percentage:")==0) return;
1707
1708         BLI_srand( BLI_rand() ); /* random seed */
1709         
1710         if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1711                 for(eve= em->verts.first; eve; eve= eve->next) {
1712                         if(eve->h==0) {
1713                                 if ( (BLI_frand() * 100) < randfac) 
1714                                         eve->f |= SELECT;
1715                         }
1716                 }
1717         }
1718         else if(G.scene->selectmode & SCE_SELECT_EDGE) {
1719                 for(eed= em->edges.first; eed; eed= eed->next) {
1720                         if(eed->h==0) {
1721                                 if ( (BLI_frand() * 100) < randfac) 
1722                                         EM_select_edge(eed, 1);
1723                         }
1724                 }
1725         }
1726         else {
1727                 for(efa= em->faces.first; efa; efa= efa->next) {
1728                         if(efa->h==0) {
1729                                 if ( (BLI_frand() * 100) < randfac) 
1730                                         EM_select_face(efa, 1);
1731                         }
1732                 }
1733         }
1734         
1735         EM_selectmode_flush();
1736
1737         countall();
1738         allqueue(REDRAWVIEW3D, 0);
1739 }
1740
1741 void editmesh_select_by_material(int index) 
1742 {
1743         EditMesh *em = G.editMesh;
1744         EditFace *efa;
1745         
1746         for (efa=em->faces.first; efa; efa= efa->next) {
1747                 if (efa->mat_nr==index) {
1748                         EM_select_face(efa, 1);
1749                 }
1750         }
1751
1752         EM_selectmode_flush();
1753 }
1754
1755 void editmesh_deselect_by_material(int index) 
1756 {
1757         EditMesh *em = G.editMesh;
1758         EditFace *efa;
1759         
1760         for (efa=em->faces.first; efa; efa= efa->next) {
1761                 if (efa->mat_nr==index) {
1762                         EM_select_face(efa, 0);
1763                 }
1764         }
1765
1766         EM_selectmode_flush();
1767 }
1768
1769 void EM_selectmode_menu(void)
1770 {
1771         int val;
1772         
1773         if(G.scene->selectmode & SCE_SELECT_VERTEX) pupmenu_set_active(1);
1774         else if(G.scene->selectmode & SCE_SELECT_EDGE) pupmenu_set_active(2);
1775         else pupmenu_set_active(3);
1776         
1777         val= pupmenu("Select Mode%t|Vertices|Edges|Faces");
1778         if(val>0) {
1779                 if(val==1) G.scene->selectmode= SCE_SELECT_VERTEX;
1780                 else if(val==2) G.scene->selectmode= SCE_SELECT_EDGE;
1781                 else G.scene->selectmode= SCE_SELECT_FACE;
1782         
1783                 EM_selectmode_set(); // when mode changes
1784                 allqueue(REDRAWVIEW3D, 1);
1785         }
1786 }
1787
1788 /* ************************* SEAMS AND EDGES **************** */
1789
1790 void editmesh_mark_seam(int clear)
1791 {
1792         EditMesh *em= G.editMesh;
1793         EditEdge *eed;
1794
1795         /* auto-enable seams drawing */
1796         if(clear==0) {
1797                 if(!(G.f & G_DRAWSEAMS)) {
1798                         G.f |= G_DRAWSEAMS;
1799                         allqueue(REDRAWBUTSEDIT, 0);
1800                 }
1801         }
1802
1803         if(clear) {
1804                 eed= em->edges.first;
1805                 while(eed) {
1806                         if((eed->h==0) && (eed->f & SELECT)) {
1807                                 eed->seam = 0;
1808                         }
1809                         eed= eed->next;
1810                 }
1811                 BIF_undo_push("Mark Seam");
1812         }
1813         else {
1814                 eed= em->edges.first;
1815                 while(eed) {
1816                         if((eed->h==0) && (eed->f & SELECT)) {
1817                                 eed->seam = 1;
1818                         }
1819                         eed= eed->next;
1820                 }
1821                 BIF_undo_push("Clear Seam");
1822         }
1823
1824         allqueue(REDRAWVIEW3D, 0);
1825 }
1826
1827 void Edge_Menu() {
1828         short ret;
1829
1830         ret= pupmenu("Edge Specials%t|Mark Seam %x1|Clear Seam %x2|Rotate Edge CW%x3|Rotate Edge CCW%x4|Loopcut%x6|Edge Slide%x5");
1831
1832         switch(ret)
1833         {
1834         case 1:
1835                 editmesh_mark_seam(0);
1836                 break;
1837         case 2:
1838                 editmesh_mark_seam(1);
1839                 break;
1840         case 3:
1841                 edge_rotate_selected(2);
1842                 break;
1843         case 4:
1844                 edge_rotate_selected(1);
1845                 break;
1846         case 5:
1847                 EdgeSlide(0,0.0);
1848                 BIF_undo_push("EdgeSlide");
1849                 break;
1850         case 6:
1851                 CutEdgeloop(1);
1852                 BIF_undo_push("Loopcut New");
1853                 break;
1854         }
1855 }
1856
1857
1858 /* **************** NORMALS ************** */
1859
1860 void righthandfaces(int select) /* makes faces righthand turning */
1861 {
1862         EditMesh *em = G.editMesh;
1863         EditEdge *eed, *ed1, *ed2, *ed3, *ed4;
1864         EditFace *efa, *startvl;
1865         float maxx, nor[3], cent[3];
1866         int totsel, found, foundone, direct, turn, tria_nr;
1867
1868    /* based at a select-connected to witness loose objects */
1869
1870         /* count per edge the amount of faces */
1871
1872         /* find the ultimate left, front, upper face (not manhattan dist!!) */
1873         /* also evaluate both triangle cases in quad, since these can be non-flat */
1874
1875         /* put normal to the outside, and set the first direction flags in edges */
1876
1877         /* then check the object, and set directions / direction-flags: but only for edges with 1 or 2 faces */
1878         /* this is in fact the 'select connected' */
1879         
1880         /* in case (selected) faces were not done: start over with 'find the ultimate ...' */
1881
1882         waitcursor(1);
1883         
1884         eed= em->edges.first;
1885         while(eed) {
1886                 eed->f2= 0;             // edge direction
1887                 eed->f1= 0;             // counter
1888                 eed= eed->next;
1889         }
1890
1891         /* count faces and edges */
1892         totsel= 0;
1893         efa= em->faces.first;
1894         while(efa) {
1895                 if(select==0 || (efa->f & SELECT) ) {
1896                         efa->f1= 1;
1897                         totsel++;
1898                         efa->e1->f1++;
1899                         efa->e2->f1++;
1900                         efa->e3->f1++;
1901                         if(efa->v4) efa->e4->f1++;
1902                 }
1903                 else efa->f1= 0;
1904
1905                 efa= efa->next;
1906         }
1907
1908         while(totsel>0) {
1909                 /* from the outside to the inside */
1910
1911                 efa= em->faces.first;
1912                 startvl= NULL;
1913                 maxx= -1.0e10;
1914                 tria_nr= 0;
1915
1916                 while(efa) {
1917                         if(efa->f1) {
1918                                 CalcCent3f(cent, efa->v1->co, efa->v2->co, efa->v3->co);
1919                                 cent[0]= cent[0]*cent[0] + cent[1]*cent[1] + cent[2]*cent[2];
1920                                 
1921                                 if(cent[0]>maxx) {
1922                                         maxx= cent[0];
1923                                         startvl= efa;
1924                                         tria_nr= 0;
1925                                 }
1926                                 if(efa->v4) {
1927                                         CalcCent3f(cent, efa->v1->co, efa->v3->co, efa->v4->co);
1928                                         cent[0]= cent[0]*cent[0] + cent[1]*cent[1] + cent[2]*cent[2];
1929                                         
1930                                         if(cent[0]>maxx) {
1931                                                 maxx= cent[0];
1932                                                 startvl= efa;
1933                                                 tria_nr= 1;
1934                                         }
1935                                 }
1936                         }
1937                         efa= efa->next;
1938                 }
1939                 
1940                 /* set first face correct: calc normal */
1941                 
1942                 if(tria_nr==1) {
1943                         CalcNormFloat(startvl->v1->co, startvl->v3->co, startvl->v4->co, nor);
1944                         CalcCent3f(cent, startvl->v1->co, startvl->v3->co, startvl->v4->co);
1945                 } else {
1946                         CalcNormFloat(startvl->v1->co, startvl->v2->co, startvl->v3->co, nor);
1947                         CalcCent3f(cent, startvl->v1->co, startvl->v2->co, startvl->v3->co);
1948                 }
1949                 /* first normal is oriented this way or the other */
1950                 if(select) {
1951                         if(select==2) {
1952                                 if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] > 0.0) flipface(startvl);
1953                         }
1954                         else {
1955                                 if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] < 0.0) flipface(startvl);
1956                         }
1957                 }
1958                 else if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] < 0.0) flipface(startvl);
1959
1960
1961                 eed= startvl->e1;
1962                 if(eed->v1==startvl->v1) eed->f2= 1; 
1963                 else eed->f2= 2;
1964                 
1965                 eed= startvl->e2;
1966                 if(eed->v1==startvl->v2) eed->f2= 1; 
1967                 else eed->f2= 2;
1968                 
1969                 eed= startvl->e3;
1970                 if(eed->v1==startvl->v3) eed->f2= 1; 
1971                 else eed->f2= 2;
1972                 
1973                 eed= startvl->e4;
1974                 if(eed) {
1975                         if(eed->v1==startvl->v4) eed->f2= 1; 
1976                         else eed->f2= 2;
1977                 }
1978                 
1979                 startvl->f1= 0;
1980                 totsel--;
1981
1982                 /* test normals */
1983                 found= 1;
1984                 direct= 1;
1985                 while(found) {
1986                         found= 0;
1987                         if(direct) efa= em->faces.first;
1988                         else efa= em->faces.last;
1989                         while(efa) {
1990                                 if(efa->f1) {
1991                                         turn= 0;
1992                                         foundone= 0;
1993
1994                                         ed1= efa->e1;
1995                                         ed2= efa->e2;
1996                                         ed3= efa->e3;
1997                                         ed4= efa->e4;
1998
1999                                         if(ed1->f2) {
2000                                                 if(ed1->v1==efa->v1 && ed1->f2==1) turn= 1;
2001                                                 if(ed1->v2==efa->v1 && ed1->f2==2) turn= 1;
2002                                                 foundone= 1;
2003                                         }
2004                                         else if(ed2->f2) {
2005                                                 if(ed2->v1==efa->v2 && ed2->f2==1) turn= 1;
2006                                                 if(ed2->v2==efa->v2 && ed2->f2==2) turn= 1;
2007                                                 foundone= 1;
2008                                         }
2009                                         else if(ed3->f2) {
2010                                                 if(ed3->v1==efa->v3 && ed3->f2==1) turn= 1;
2011                                                 if(ed3->v2==efa->v3 && ed3->f2==2) turn= 1;
2012                                                 foundone= 1;
2013                                         }
2014                                         else if(ed4 && ed4->f2) {
2015                                                 if(ed4->v1==efa->v4 && ed4->f2==1) turn= 1;
2016                                                 if(ed4->v2==efa->v4 && ed4->f2==2) turn= 1;
2017                                                 foundone= 1;
2018                                         }
2019
2020                                         if(foundone) {
2021                                                 found= 1;
2022                                                 totsel--;
2023                                                 efa->f1= 0;
2024
2025                                                 if(turn) {
2026                                                         if(ed1->v1==efa->v1) ed1->f2= 2; 
2027                                                         else ed1->f2= 1;
2028                                                         if(ed2->v1==efa->v2) ed2->f2= 2; 
2029                                                         else ed2->f2= 1;
2030                                                         if(ed3->v1==efa->v3) ed3->f2= 2; 
2031                                                         else ed3->f2= 1;
2032                                                         if(ed4) {
2033                                                                 if(ed4->v1==efa->v4) ed4->f2= 2; 
2034                                                                 else ed4->f2= 1;
2035                                                         }
2036
2037                                                         flipface(efa);
2038
2039                                                 }
2040                                                 else {
2041                                                         if(ed1->v1== efa->v1) ed1->f2= 1; 
2042                                                         else ed1->f2= 2;
2043                                                         if(ed2->v1==efa->v2) ed2->f2= 1; 
2044                                                         else ed2->f2= 2;
2045                                                         if(ed3->v1==efa->v3) ed3->f2= 1; 
2046                                                         else ed3->f2= 2;
2047                                                         if(ed4) {
2048                                                                 if(ed4->v1==efa->v4) ed4->f2= 1; 
2049                                                                 else ed4->f2= 2;
2050                                                         }
2051                                                 }
2052                                         }
2053                                 }
2054                                 if(direct) efa= efa->next;
2055                                 else efa= efa->prev;
2056                         }
2057                         direct= 1-direct;
2058                 }
2059         }
2060
2061         recalc_editnormals();
2062         
2063         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2064         
2065         waitcursor(0);
2066 }
2067
2068
2069 /* ********** ALIGN WITH VIEW **************** */
2070
2071
2072 static void editmesh_calc_selvert_center(float cent_r[3])
2073 {
2074         EditMesh *em = G.editMesh;
2075         EditVert *eve;
2076         int nsel= 0;
2077
2078         cent_r[0]= cent_r[1]= cent_r[0]= 0.0;
2079
2080         for (eve= em->verts.first; eve; eve= eve->next) {
2081                 if (eve->f & SELECT) {
2082                         cent_r[0]+= eve->co[0];
2083                         cent_r[1]+= eve->co[1];
2084                         cent_r[2]+= eve->co[2];
2085                         nsel++;
2086                 }
2087         }
2088
2089         if (nsel) {
2090                 cent_r[0]/= nsel;
2091                 cent_r[1]/= nsel;
2092                 cent_r[2]/= nsel;
2093         }
2094 }
2095
2096 static int tface_is_selected(TFace *tf)
2097 {
2098         return (!(tf->flag & TF_HIDE) && (tf->flag & TF_SELECT));
2099 }
2100
2101 static int faceselect_nfaces_selected(Mesh *me)
2102 {
2103         int i, count= 0;
2104
2105         for (i=0; i<me->totface; i++)
2106                 if (tface_is_selected(&me->tface[i]))
2107                         count++;
2108
2109         return count;
2110 }
2111
2112         /* XXX, code for both these functions should be abstract,
2113          * then unified, then written for other things (like objects,
2114          * which would use same as vertices method), then added
2115          * to interface! Hoera! - zr
2116          */
2117 void faceselect_align_view_to_selected(View3D *v3d, Mesh *me, int axis)
2118 {
2119         if (!faceselect_nfaces_selected(me)) {
2120                 error("No faces selected.");
2121         } else {
2122                 float norm[3];
2123                 int i;
2124
2125                 norm[0]= norm[1]= norm[2]= 0.0;
2126                 for (i=0; i<me->totface; i++) {
2127                         MFace *mf= ((MFace*) me->mface) + i;
2128                         TFace *tf= ((TFace*) me->tface) + i;
2129         
2130                         if (tface_is_selected(tf)) {
2131                                 float *v1, *v2, *v3, fno[3];
2132
2133                                 v1= me->mvert[mf->v1].co;
2134                                 v2= me->mvert[mf->v2].co;
2135                                 v3= me->mvert[mf->v3].co;
2136                                 if (mf->v4) {
2137                                         float *v4= me->mvert[mf->v4].co;
2138                                         CalcNormFloat4(v1, v2, v3, v4, fno);
2139                                 } else {
2140                                         CalcNormFloat(v1, v2, v3, fno);
2141                                 }
2142
2143                                 norm[0]+= fno[0];
2144                                 norm[1]+= fno[1];
2145                                 norm[2]+= fno[2];
2146                         }
2147                 }
2148
2149                 view3d_align_axis_to_vector(v3d, axis, norm);
2150         }
2151 }
2152
2153 void editmesh_align_view_to_selected(View3D *v3d, int axis)
2154 {
2155         EditMesh *em = G.editMesh;
2156         int nselverts= EM_nvertices_selected();
2157
2158         if (nselverts<3) {
2159                 if (nselverts==0) {
2160                         error("No faces or vertices selected.");
2161                 } else {
2162                         error("At least one face or three vertices must be selected.");
2163                 }
2164         } else if (EM_nfaces_selected()) {
2165                 float norm[3];
2166                 EditFace *efa;
2167
2168                 norm[0]= norm[1]= norm[2]= 0.0;
2169                 for (efa= em->faces.first; efa; efa= efa->next) {
2170                         if (faceselectedAND(efa, SELECT)) {
2171                                 float fno[3];
2172                                 if (efa->v4) CalcNormFloat4(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co, fno);
2173                                 else CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, fno);
2174                                                 /* XXX, fixme, should be flipped intp a 
2175                                                  * consistent direction. -zr
2176                                                  */
2177                                 norm[0]+= fno[0];
2178                                 norm[1]+= fno[1];
2179                                 norm[2]+= fno[2];
2180                         }
2181                 }
2182
2183                 Mat4Mul3Vecfl(G.obedit->obmat, norm);
2184                 view3d_align_axis_to_vector(v3d, axis, norm);
2185         } else {
2186                 float cent[3], norm[3];
2187                 EditVert *eve, *leve= NULL;
2188
2189                 norm[0]= norm[1]= norm[2]= 0.0;
2190                 editmesh_calc_selvert_center(cent);
2191                 for (eve= em->verts.first; eve; eve= eve->next) {
2192                         if (eve->f & SELECT) {
2193                                 if (leve) {
2194                                         float tno[3];
2195                                         CalcNormFloat(cent, leve->co, eve->co, tno);
2196                                         
2197                                                 /* XXX, fixme, should be flipped intp a 
2198                                                  * consistent direction. -zr
2199                                                  */
2200                                         norm[0]+= tno[0];
2201                                         norm[1]+= tno[1];
2202                                         norm[2]+= tno[2];
2203                                 }
2204                                 leve= eve;
2205                         }
2206                 }
2207
2208                 Mat4Mul3Vecfl(G.obedit->obmat, norm);
2209                 view3d_align_axis_to_vector(v3d, axis, norm);
2210         }
2211 }
2212
2213 /* **************** VERTEX DEFORMS *************** */
2214
2215 void vertexsmooth(void)
2216 {
2217         EditMesh *em = G.editMesh;
2218         EditVert *eve;
2219         EditEdge *eed;
2220         float *adror, *adr, fac;
2221         float fvec[3];
2222         int teller=0;
2223
2224         if(G.obedit==0) return;
2225
2226         /* count */
2227         eve= em->verts.first;
2228         while(eve) {
2229                 if(eve->f & SELECT) teller++;
2230                 eve= eve->next;
2231         }
2232         if(teller==0) return;
2233         
2234         adr=adror= (float *)MEM_callocN(3*sizeof(float *)*teller, "vertsmooth");
2235         eve= em->verts.first;
2236         while(eve) {
2237                 if(eve->f & SELECT) {
2238                         eve->vn= (EditVert *)adr;
2239                         eve->f1= 0;
2240                         adr+= 3;
2241                 }
2242                 eve= eve->next;
2243         }
2244         
2245         eed= em->edges.first;
2246         while(eed) {
2247                 if( (eed->v1->f & SELECT) || (eed->v2->f & SELECT) ) {
2248                         fvec[0]= (eed->v1->co[0]+eed->v2->co[0])/2.0;
2249                         fvec[1]= (eed->v1->co[1]+eed->v2->co[1])/2.0;
2250                         fvec[2]= (eed->v1->co[2]+eed->v2->co[2])/2.0;
2251                         
2252                         if((eed->v1->f & SELECT) && eed->v1->f1<255) {
2253                                 eed->v1->f1++;
2254                                 VecAddf((float *)eed->v1->vn, (float *)eed->v1->vn, fvec);
2255                         }
2256                         if((eed->v2->f & SELECT) && eed->v2->f1<255) {
2257                                 eed->v2->f1++;
2258                                 VecAddf((float *)eed->v2->vn, (float *)eed->v2->vn, fvec);
2259                         }
2260                 }
2261                 eed= eed->next;
2262         }
2263
2264         eve= em->verts.first;
2265         while(eve) {
2266                 if(eve->f & SELECT) {
2267                         if(eve->f1) {
2268                                 adr= (float *)eve->vn;
2269                                 fac= 0.5/(float)eve->f1;
2270                                 
2271                                 eve->co[0]= 0.5*eve->co[0]+fac*adr[0];
2272                                 eve->co[1]= 0.5*eve->co[1]+fac*adr[1];
2273                                 eve->co[2]= 0.5*eve->co[2]+fac*adr[2];
2274                         }
2275                         eve->vn= 0;
2276                 }
2277                 eve= eve->next;
2278         }
2279         MEM_freeN(adror);
2280
2281         recalc_editnormals();
2282
2283         allqueue(REDRAWVIEW3D, 0);
2284         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2285         BIF_undo_push("Vertex Smooth");
2286 }
2287
2288 void vertexnoise(void)
2289 {
2290         EditMesh *em = G.editMesh;
2291         Material *ma;
2292         Tex *tex;
2293         EditVert *eve;
2294         float b2, ofs, vec[3];
2295
2296         if(G.obedit==0) return;
2297         
2298         ma= give_current_material(G.obedit, G.obedit->actcol);
2299         if(ma==0 || ma->mtex[0]==0 || ma->mtex[0]->tex==0) {
2300                 return;
2301         }
2302         tex= ma->mtex[0]->tex;
2303         
2304         ofs= tex->turbul/200.0;
2305         
2306         eve= (struct EditVert *)em->verts.first;
2307         while(eve) {
2308                 if(eve->f & SELECT) {
2309                         
2310                         if(tex->type==TEX_STUCCI) {
2311                                 
2312                                 b2= BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1], eve->co[2]);
2313                                 if(tex->stype) ofs*=(b2*b2);
2314                                 vec[0]= 0.2*(b2-BLI_hnoise(tex->noisesize, eve->co[0]+ofs, eve->co[1], eve->co[2]));
2315                                 vec[1]= 0.2*(b2-BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1]+ofs, eve->co[2]));
2316                                 vec[2]= 0.2*(b2-BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1], eve->co[2]+ofs));
2317                                 
2318                                 VecAddf(eve->co, eve->co, vec);
2319                         }
2320                         else {
2321                                 float tin, dum;
2322                                 externtex(ma->mtex[0], eve->co, &tin, &dum, &dum, &dum, &dum);
2323                                 eve->co[2]+= 0.05*tin;
2324                         }
2325                 }
2326                 eve= eve->next;
2327         }
2328
2329         recalc_editnormals();
2330         allqueue(REDRAWVIEW3D, 0);
2331         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2332         BIF_undo_push("Vertex Noise");
2333 }
2334
2335 void vertices_to_sphere(void)
2336 {
2337         EditMesh *em = G.editMesh;
2338         EditVert *eve;
2339         Object *ob= OBACT;
2340         float *curs, len, vec[3], cent[3], fac, facm, imat[3][3], bmat[3][3];
2341         int tot;
2342         short perc=100;
2343         
2344         if(ob==0) return;
2345         TEST_EDITMESH
2346         
2347         if(button(&perc, 1, 100, "Percentage:")==0) return;
2348         
2349         fac= perc/100.0;
2350         facm= 1.0-fac;
2351         
2352         Mat3CpyMat4(bmat, ob->obmat);
2353         Mat3Inv(imat, bmat);
2354
2355         /* centre */
2356         curs= give_cursor();
2357         cent[0]= curs[0]-ob->obmat[3][0];
2358         cent[1]= curs[1]-ob->obmat[3][1];
2359         cent[2]= curs[2]-ob->obmat[3][2];
2360         Mat3MulVecfl(imat, cent);
2361
2362         len= 0.0;
2363         tot= 0;
2364         eve= em->verts.first;
2365         while(eve) {
2366                 if(eve->f & SELECT) {
2367                         tot++;
2368                         len+= VecLenf(cent, eve->co);
2369                 }
2370                 eve= eve->next;
2371         }
2372         len/=tot;
2373         
2374         if(len==0.0) len= 10.0;
2375         
2376         eve= em->verts.first;
2377         while(eve) {
2378                 if(eve->f & SELECT) {
2379                         vec[0]= eve->co[0]-cent[0];
2380                         vec[1]= eve->co[1]-cent[1];
2381                         vec[2]= eve->co[2]-cent[2];
2382                         
2383                         Normalise(vec);
2384                         
2385                         eve->co[0]= fac*(cent[0]+vec[0]*len) + facm*eve->co[0];
2386                         eve->co[1]= fac*(cent[1]+vec[1]*len) + facm*eve->co[1];
2387                         eve->co[2]= fac*(cent[2]+vec[2]*len) + facm*eve->co[2];
2388                         
2389                 }
2390                 eve= eve->next;
2391         }
2392         
2393         recalc_editnormals();
2394         allqueue(REDRAWVIEW3D, 0);
2395         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2396         BIF_undo_push("To Sphere");
2397 }
2398