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