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