* corrective UV transformation - only works with UV edge slide right now. but should...
[blender.git] / source / blender / src / editmesh_mods.c
1 /**
2  * $Id: 
3  *
4  * ***** BEGIN GPL 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.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2004 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /*
31
32 editmesh_mods.c, UI level access, no geometry changes 
33
34 */
35
36 #include <stdlib.h>
37 #include <string.h>
38 #include <math.h>
39
40 #include "MEM_guardedalloc.h"
41
42 #include "MTC_matrixops.h"
43
44 #include "DNA_mesh_types.h"
45 #include "DNA_material_types.h"
46 #include "DNA_meshdata_types.h"
47 #include "DNA_modifier_types.h"
48 #include "DNA_object_types.h"
49 #include "DNA_texture_types.h"
50 #include "DNA_scene_types.h"
51 #include "DNA_screen_types.h"
52 #include "DNA_space_types.h"
53 #include "DNA_view3d_types.h"
54
55 #include "BLI_blenlib.h"
56 #include "BLI_arithb.h"
57 #include "BLI_editVert.h"
58 #include "BLI_rand.h"
59
60 #include "BKE_displist.h"
61 #include "BKE_depsgraph.h"
62 #include "BKE_DerivedMesh.h"
63 #include "BKE_customdata.h"
64 #include "BKE_global.h"
65 #include "BKE_mesh.h"
66 #include "BKE_material.h"
67 #include "BKE_texture.h"
68 #include "BKE_utildefines.h"
69
70 #ifdef WITH_VERSE
71 #include "BKE_verse.h"
72 #endif
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_previewrender.h"
83 #include "BIF_resources.h"
84 #include "BIF_screen.h"
85 #include "BIF_space.h"
86 #include "BIF_toolbox.h"
87 #include "BIF_editsima.h"
88
89 #ifdef WITH_VERSE
90 #include "BIF_verse.h"
91 #endif
92
93 #include "BDR_drawobject.h"
94 #include "BDR_editobject.h"
95 #include "BDR_editface.h"
96
97 #include "BSE_drawview.h"
98 #include "BSE_edit.h"
99 #include "BSE_view.h"
100
101 #include "IMB_imbuf_types.h"
102 #include "IMB_imbuf.h"
103
104 #include "RE_render_ext.h"  /* externtex */
105
106 #include "multires.h"
107 #include "mydevice.h"
108 #include "blendef.h"
109
110 #include "editmesh.h"
111
112 #include "BLO_sys_types.h" // for intptr_t support
113
114 /* ****************************** MIRROR **************** */
115
116 void EM_select_mirrored(void)
117 {
118         if(G.scene->selectmode & SCE_SELECT_VERTEX) {
119                 EditMesh *em = G.editMesh;
120                 EditVert *eve, *v1;
121                 
122                 for(eve= em->verts.first; eve; eve= eve->next) {
123                         if(eve->f & SELECT) {
124                                 v1= editmesh_get_x_mirror_vert(G.obedit, eve->co);
125                                 if(v1) {
126                                         eve->f &= ~SELECT;
127                                         v1->f |= SELECT;
128                                 }
129                         }
130                 }
131         }
132 }
133
134 void EM_automerge(int update) {
135         int len;
136         if ((G.scene->automerge) &&
137                 (G.obedit && G.obedit->type==OB_MESH) &&
138                 (((Mesh*)G.obedit->data)->mr==NULL)
139           ) {
140                 len = removedoublesflag(1, 1, G.scene->toolsettings->doublimit);
141                 if (len) {
142                         G.totvert -= len; /* saves doing a countall */
143                         if (update) {
144                                 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
145                         }
146                 }
147         }
148 }
149
150 /* ****************************** SELECTION ROUTINES **************** */
151
152 unsigned int em_solidoffs=0, em_wireoffs=0, em_vertoffs=0;      /* set in drawobject.c ... for colorindices */
153
154 /* facilities for border select and circle select */
155 static char *selbuf= NULL;
156
157 /* opengl doesn't support concave... */
158 static void draw_triangulated(short mcords[][2], short tot)
159 {
160         ListBase lb={NULL, NULL};
161         DispList *dl;
162         float *fp;
163         int a;
164         
165         /* make displist */
166         dl= MEM_callocN(sizeof(DispList), "poly disp");
167         dl->type= DL_POLY;
168         dl->parts= 1;
169         dl->nr= tot;
170         dl->verts= fp=  MEM_callocN(tot*3*sizeof(float), "poly verts");
171         BLI_addtail(&lb, dl);
172         
173         for(a=0; a<tot; a++, fp+=3) {
174                 fp[0]= (float)mcords[a][0];
175                 fp[1]= (float)mcords[a][1];
176         }
177         
178         /* do the fill */
179         filldisplist(&lb, &lb);
180
181         /* do the draw */
182         dl= lb.first;   /* filldisplist adds in head of list */
183         if(dl->type==DL_INDEX3) {
184                 int *index;
185                 
186                 a= dl->parts;
187                 fp= dl->verts;
188                 index= dl->index;
189                 glBegin(GL_TRIANGLES);
190                 while(a--) {
191                         glVertex3fv(fp+3*index[0]);
192                         glVertex3fv(fp+3*index[1]);
193                         glVertex3fv(fp+3*index[2]);
194                         index+= 3;
195                 }
196                 glEnd();
197         }
198         
199         freedisplist(&lb);
200 }
201
202
203 /* reads rect, and builds selection array for quick lookup */
204 /* returns if all is OK */
205 int EM_init_backbuf_border(short xmin, short ymin, short xmax, short ymax)
206 {
207         struct ImBuf *buf;
208         unsigned int *dr;
209         int a;
210         
211         if(G.obedit==NULL || G.vd->drawtype<OB_SOLID || (G.vd->flag & V3D_ZBUF_SELECT)==0) return 0;
212         if(em_vertoffs==0) return 0;
213         
214         buf= read_backbuf(xmin, ymin, xmax, ymax);
215         if(buf==NULL) return 0;
216
217         dr = buf->rect;
218         
219         /* build selection lookup */
220         selbuf= MEM_callocN(em_vertoffs+1, "selbuf");
221         
222         a= (xmax-xmin+1)*(ymax-ymin+1);
223         while(a--) {
224                 if(*dr>0 && *dr<=em_vertoffs) 
225                         selbuf[*dr]= 1;
226                 dr++;
227         }
228         IMB_freeImBuf(buf);
229         return 1;
230 }
231
232 int EM_check_backbuf(unsigned int index)
233 {
234         if(selbuf==NULL) return 1;
235         if(index>0 && index<=em_vertoffs)
236                 return selbuf[index];
237         return 0;
238 }
239
240 void EM_free_backbuf(void)
241 {
242         if(selbuf) MEM_freeN(selbuf);
243         selbuf= NULL;
244 }
245
246 /* mcords is a polygon mask
247    - grab backbuffer,
248    - draw with black in backbuffer, 
249    - grab again and compare
250    returns 'OK' 
251 */
252 int EM_mask_init_backbuf_border(short mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax)
253 {
254         unsigned int *dr, *drm;
255         struct ImBuf *buf, *bufmask;
256         int a;
257         
258         /* method in use for face selecting too */
259         if(G.obedit==NULL) {
260                 if(FACESEL_PAINT_TEST);
261                 else return 0;
262         }
263         else if(G.vd->drawtype<OB_SOLID || (G.vd->flag & V3D_ZBUF_SELECT)==0) return 0;
264
265         if(em_vertoffs==0) return 0;
266         
267         buf= read_backbuf(xmin, ymin, xmax, ymax);
268         if(buf==NULL) return 0;
269
270         dr = buf->rect;
271
272         /* draw the mask */
273 #ifdef __APPLE__
274         glDrawBuffer(GL_AUX0);
275 #endif
276         glDisable(GL_DEPTH_TEST);
277         
278         persp(PERSP_WIN);
279         glColor3ub(0, 0, 0);
280         
281         /* yah, opengl doesn't do concave... tsk! */
282         draw_triangulated(mcords, tot); 
283         
284         glBegin(GL_LINE_LOOP);  /* for zero sized masks, lines */
285         for(a=0; a<tot; a++) glVertex2s(mcords[a][0], mcords[a][1]);
286         glEnd();
287         
288         persp(PERSP_VIEW);
289         glFinish();     /* to be sure readpixels sees mask */
290         
291         glDrawBuffer(GL_BACK);
292         
293         /* grab mask */
294         bufmask= read_backbuf(xmin, ymin, xmax, ymax);
295         drm = bufmask->rect;
296         if(bufmask==NULL) return 0; /* only when mem alloc fails, go crash somewhere else! */
297         
298         /* build selection lookup */
299         selbuf= MEM_callocN(em_vertoffs+1, "selbuf");
300         
301         a= (xmax-xmin+1)*(ymax-ymin+1);
302         while(a--) {
303                 if(*dr>0 && *dr<=em_vertoffs && *drm==0) selbuf[*dr]= 1;
304                 dr++; drm++;
305         }
306         IMB_freeImBuf(buf);
307         IMB_freeImBuf(bufmask);
308         return 1;
309         
310 }
311
312 /* circle shaped sample area */
313 int EM_init_backbuf_circle(short xs, short ys, short rads)
314 {
315         struct ImBuf *buf;
316         unsigned int *dr;
317         short xmin, ymin, xmax, ymax, xc, yc;
318         int radsq;
319         
320         /* method in use for face selecting too */
321         if(G.obedit==NULL) {
322                 if(FACESEL_PAINT_TEST);
323                 else return 0;
324         }
325         else if(G.vd->drawtype<OB_SOLID || (G.vd->flag & V3D_ZBUF_SELECT)==0) return 0;
326         if(em_vertoffs==0) return 0;
327         
328         xmin= xs-rads; xmax= xs+rads;
329         ymin= ys-rads; ymax= ys+rads;
330         buf= read_backbuf(xmin, ymin, xmax, ymax);
331         if(buf==NULL) return 0;
332
333         dr = buf->rect;
334         
335         /* build selection lookup */
336         selbuf= MEM_callocN(em_vertoffs+1, "selbuf");
337         radsq= rads*rads;
338         for(yc= -rads; yc<=rads; yc++) {
339                 for(xc= -rads; xc<=rads; xc++, dr++) {
340                         if(xc*xc + yc*yc < radsq) {
341                                 if(*dr>0 && *dr<=em_vertoffs) selbuf[*dr]= 1;
342                         }
343                 }
344         }
345
346         IMB_freeImBuf(buf);
347         return 1;
348         
349 }
350
351 static void findnearestvert__doClosest(void *userData, EditVert *eve, int x, int y, int index)
352 {
353         struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; EditVert *closest; } *data = userData;
354
355         if (data->pass==0) {
356                 if (index<=data->lastIndex)
357                         return;
358         } else {
359                 if (index>data->lastIndex)
360                         return;
361         }
362
363         if (data->dist>3) {
364                 int temp = abs(data->mval[0] - x) + abs(data->mval[1]- y);
365                 if ((eve->f&1) == data->select) {
366                         if (data->strict == 1)
367                                 return;
368                         else
369                                 temp += 5;
370                 }
371
372                 if (temp<data->dist) {
373                         data->dist = temp;
374                         data->closest = eve;
375                         data->closestIndex = index;
376                 }
377         }
378 }
379
380
381
382
383 static unsigned int findnearestvert__backbufIndextest(unsigned int index){
384                 EditVert *eve = BLI_findlink(&G.editMesh->verts, index-1);
385                 if(eve && (eve->f & SELECT)) return 0;
386                 return 1; 
387 }
388 /**
389  * findnearestvert
390  * 
391  * dist (in/out): minimal distance to the nearest and at the end, actual distance
392  * sel: selection bias
393  *              if SELECT, selected vertice are given a 5 pixel bias to make them farter than unselect verts
394  *              if 0, unselected vertice are given the bias
395  * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased 
396  */
397 EditVert *findnearestvert(int *dist, short sel, short strict)
398 {
399         short mval[2];
400
401         getmouseco_areawin(mval);
402         if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)){
403                 int distance;
404                 unsigned int index;
405                 EditVert *eve;
406                 
407                 if(strict) index = sample_backbuf_rect(mval, 50, em_wireoffs, 0xFFFFFF, &distance, strict, findnearestvert__backbufIndextest); 
408                 else index = sample_backbuf_rect(mval, 50, em_wireoffs, 0xFFFFFF, &distance, 0, NULL); 
409                 
410                 eve = BLI_findlink(&G.editMesh->verts, index-1);
411                 
412                 if(eve && distance < *dist) {
413                         *dist = distance;
414                         return eve;
415                 } else {
416                         return NULL;
417                 }
418                         
419         }
420         else {
421                 struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; EditVert *closest; } data;
422                 static int lastSelectedIndex=0;
423                 static EditVert *lastSelected=NULL;
424
425                 if (lastSelected && BLI_findlink(&G.editMesh->verts, lastSelectedIndex)!=lastSelected) {
426                         lastSelectedIndex = 0;
427                         lastSelected = NULL;
428                 }
429
430                 data.lastIndex = lastSelectedIndex;
431                 data.mval[0] = mval[0];
432                 data.mval[1] = mval[1];
433                 data.select = sel;
434                 data.dist = *dist;
435                 data.strict = strict;
436                 data.closest = NULL;
437                 data.closestIndex = 0;
438
439                 data.pass = 0;
440                 mesh_foreachScreenVert(findnearestvert__doClosest, &data, 1);
441
442                 if (data.dist>3) {
443                         data.pass = 1;
444                         mesh_foreachScreenVert(findnearestvert__doClosest, &data, 1);
445                 }
446
447                 *dist = data.dist;
448                 lastSelected = data.closest;
449                 lastSelectedIndex = data.closestIndex;
450
451                 return data.closest;
452         }
453 }
454
455 /* returns labda for closest distance v1 to line-piece v2-v3 */
456 static float labda_PdistVL2Dfl( float *v1, float *v2, float *v3) 
457 {
458         float rc[2], len;
459         
460         rc[0]= v3[0]-v2[0];
461         rc[1]= v3[1]-v2[1];
462         len= rc[0]*rc[0]+ rc[1]*rc[1];
463         if(len==0.0f)
464                 return 0.0f;
465         
466         return ( rc[0]*(v1[0]-v2[0]) + rc[1]*(v1[1]-v2[1]) )/len;
467 }
468
469 /* note; uses G.vd, so needs active 3d window */
470 static void findnearestedge__doClosest(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index)
471 {
472         struct { float mval[2]; int dist; EditEdge *closest; } *data = userData;
473         float v1[2], v2[2];
474         int distance;
475                 
476         v1[0] = x0;
477         v1[1] = y0;
478         v2[0] = x1;
479         v2[1] = y1;
480                 
481         distance= PdistVL2Dfl(data->mval, v1, v2);
482                 
483         if(eed->f & SELECT) distance+=5;
484         if(distance < data->dist) {
485                 if(G.vd->flag & V3D_CLIPPING) {
486                         float labda= labda_PdistVL2Dfl(data->mval, v1, v2);
487                         float vec[3];
488
489                         vec[0]= eed->v1->co[0] + labda*(eed->v2->co[0] - eed->v1->co[0]);
490                         vec[1]= eed->v1->co[1] + labda*(eed->v2->co[1] - eed->v1->co[1]);
491                         vec[2]= eed->v1->co[2] + labda*(eed->v2->co[2] - eed->v1->co[2]);
492                         Mat4MulVecfl(G.obedit->obmat, vec);
493
494                         if(view3d_test_clipping(G.vd, vec)==0) {
495                                 data->dist = distance;
496                                 data->closest = eed;
497                         }
498                 }
499                 else {
500                         data->dist = distance;
501                         data->closest = eed;
502                 }
503         }
504 }
505 EditEdge *findnearestedge(int *dist)
506 {
507         short mval[2];
508                 
509         getmouseco_areawin(mval);
510
511         if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) {
512                 int distance;
513                 unsigned int index = sample_backbuf_rect(mval, 50, em_solidoffs, em_wireoffs, &distance,0, NULL);
514                 EditEdge *eed = BLI_findlink(&G.editMesh->edges, index-1);
515
516                 if (eed && distance<*dist) {
517                         *dist = distance;
518                         return eed;
519                 } else {
520                         return NULL;
521                 }
522         }
523         else {
524                 struct { float mval[2]; int dist; EditEdge *closest; } data;
525
526                 data.mval[0] = mval[0];
527                 data.mval[1] = mval[1];
528                 data.dist = *dist;
529                 data.closest = NULL;
530
531                 mesh_foreachScreenEdge(findnearestedge__doClosest, &data, 2);
532
533                 *dist = data.dist;
534                 return data.closest;
535         }
536 }
537
538 static void findnearestface__getDistance(void *userData, EditFace *efa, int x, int y, int index)
539 {
540         struct { short mval[2]; int dist; EditFace *toFace; } *data = userData;
541
542         if (efa==data->toFace) {
543                 int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
544
545                 if (temp<data->dist)
546                         data->dist = temp;
547         }
548 }
549 static void findnearestface__doClosest(void *userData, EditFace *efa, int x, int y, int index)
550 {
551         struct { short mval[2], pass; int dist, lastIndex, closestIndex; EditFace *closest; } *data = userData;
552
553         if (data->pass==0) {
554                 if (index<=data->lastIndex)
555                         return;
556         } else {
557                 if (index>data->lastIndex)
558                         return;
559         }
560
561         if (data->dist>3) {
562                 int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
563
564                 if (temp<data->dist) {
565                         data->dist = temp;
566                         data->closest = efa;
567                         data->closestIndex = index;
568                 }
569         }
570 }
571 static EditFace *findnearestface(int *dist)
572 {
573         short mval[2];
574
575         getmouseco_areawin(mval);
576
577         if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) {
578                 unsigned int index = sample_backbuf(mval[0], mval[1]);
579                 EditFace *efa = BLI_findlink(&G.editMesh->faces, index-1);
580
581                 if (efa) {
582                         struct { short mval[2]; int dist; EditFace *toFace; } data;
583
584                         data.mval[0] = mval[0];
585                         data.mval[1] = mval[1];
586                         data.dist = 0x7FFF;             /* largest short */
587                         data.toFace = efa;
588
589                         mesh_foreachScreenFace(findnearestface__getDistance, &data);
590
591                         if(G.scene->selectmode == SCE_SELECT_FACE || data.dist<*dist) { /* only faces, no dist check */
592                                 *dist= data.dist;
593                                 return efa;
594                         }
595                 }
596                 
597                 return NULL;
598         }
599         else {
600                 struct { short mval[2], pass; int dist, lastIndex, closestIndex; EditFace *closest; } data;
601                 static int lastSelectedIndex=0;
602                 static EditFace *lastSelected=NULL;
603
604                 if (lastSelected && BLI_findlink(&G.editMesh->faces, lastSelectedIndex)!=lastSelected) {
605                         lastSelectedIndex = 0;
606                         lastSelected = NULL;
607                 }
608
609                 data.lastIndex = lastSelectedIndex;
610                 data.mval[0] = mval[0];
611                 data.mval[1] = mval[1];
612                 data.dist = *dist;
613                 data.closest = NULL;
614                 data.closestIndex = 0;
615
616                 data.pass = 0;
617                 mesh_foreachScreenFace(findnearestface__doClosest, &data);
618
619                 if (data.dist>3) {
620                         data.pass = 1;
621                         mesh_foreachScreenFace(findnearestface__doClosest, &data);
622                 }
623
624                 *dist = data.dist;
625                 lastSelected = data.closest;
626                 lastSelectedIndex = data.closestIndex;
627
628                 return data.closest;
629         }
630 }
631
632 /* for interactivity, frontbuffer draw in current window */
633 static void draw_dm_mapped_vert__mapFunc(void *theVert, int index, float *co, float *no_f, short *no_s)
634 {
635         if (EM_get_vert_for_index(index)==theVert) {
636                 bglVertex3fv(co);
637         }
638 }
639 static void draw_dm_mapped_vert(DerivedMesh *dm, EditVert *eve)
640 {
641         EM_init_index_arrays(1, 0, 0);
642         bglBegin(GL_POINTS);
643         dm->foreachMappedVert(dm, draw_dm_mapped_vert__mapFunc, eve);
644         bglEnd();
645         EM_free_index_arrays();
646 }
647
648 static int draw_dm_mapped_edge__setDrawOptions(void *theEdge, int index)
649 {
650         return EM_get_edge_for_index(index)==theEdge;
651 }
652 static void draw_dm_mapped_edge(DerivedMesh *dm, EditEdge *eed)
653 {
654         EM_init_index_arrays(0, 1, 0);
655         dm->drawMappedEdges(dm, draw_dm_mapped_edge__setDrawOptions, eed);
656         EM_free_index_arrays();
657 }
658
659 static void draw_dm_mapped_face_center__mapFunc(void *theFace, int index, float *cent, float *no)
660 {
661         if (EM_get_face_for_index(index)==theFace) {
662                 bglVertex3fv(cent);
663         }
664 }
665 static void draw_dm_mapped_face_center(DerivedMesh *dm, EditFace *efa)
666 {
667         EM_init_index_arrays(0, 0, 1);
668         bglBegin(GL_POINTS);
669         dm->foreachMappedFaceCenter(dm, draw_dm_mapped_face_center__mapFunc, efa);
670         bglEnd();
671         EM_free_index_arrays();
672 }
673
674 static void unified_select_draw(EditVert *eve, EditEdge *eed, EditFace *efa)
675 {
676         DerivedMesh *dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
677
678         glDrawBuffer(GL_FRONT);
679
680         persp(PERSP_VIEW);
681         
682         if(G.vd->flag & V3D_CLIPPING)
683                 view3d_set_clipping(G.vd);
684         
685         glPushMatrix();
686         mymultmatrix(G.obedit->obmat);
687         
688         /* face selected */
689         if(efa) {
690                 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
691                         glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
692                         
693                         if(efa->f & SELECT) BIF_ThemeColor(TH_VERTEX_SELECT);
694                         else BIF_ThemeColor(TH_VERTEX);
695                         
696                         bglBegin(GL_POINTS);
697                         bglVertex3fv(efa->v1->co);
698                         bglVertex3fv(efa->v2->co);
699                         bglVertex3fv(efa->v3->co);
700                         if(efa->v4) bglVertex3fv(efa->v4->co);
701                         bglEnd();
702                 }
703
704                 if(G.scene->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_FACE)) {
705                         if(efa->fgonf==0) {
706                                 BIF_ThemeColor((efa->f & SELECT)?TH_EDGE_SELECT:TH_WIRE);
707         
708                                 draw_dm_mapped_edge(dm, efa->e1);
709                                 draw_dm_mapped_edge(dm, efa->e2);
710                                 draw_dm_mapped_edge(dm, efa->e3);
711                                 if (efa->e4) {
712                                         draw_dm_mapped_edge(dm, efa->e4);
713                                 }
714                         }
715                 }
716                 
717                 if( CHECK_OB_DRAWFACEDOT(G.scene, G.vd, G.obedit->dt) ) {
718                         if(efa->fgonf==0) {
719                                 glPointSize(BIF_GetThemeValuef(TH_FACEDOT_SIZE));
720                                 BIF_ThemeColor((efa->f & SELECT)?TH_FACE_DOT:TH_WIRE);
721
722                                 draw_dm_mapped_face_center(dm, efa);
723                         }
724                 }
725         }
726         /* edge selected */
727         if(eed) {
728                 if(G.scene->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_FACE)) {
729                         BIF_ThemeColor((eed->f & SELECT)?TH_EDGE_SELECT:TH_WIRE);
730
731                         draw_dm_mapped_edge(dm, eed);
732                 }
733                 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
734                         glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
735                         
736                         BIF_ThemeColor((eed->f & SELECT)?TH_VERTEX_SELECT:TH_VERTEX);
737                         
738                         draw_dm_mapped_vert(dm, eed->v1);
739                         draw_dm_mapped_vert(dm, eed->v2);
740                 }
741         }
742         if(eve) {
743                 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
744                         glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
745                         
746                         BIF_ThemeColor((eve->f & SELECT)?TH_VERTEX_SELECT:TH_VERTEX);
747                         
748                         draw_dm_mapped_vert(dm, eve);
749                 }
750         }
751
752         glPointSize(1.0);
753         glPopMatrix();
754
755         bglFlush();
756         glDrawBuffer(GL_BACK);
757
758         if(G.vd->flag & V3D_CLIPPING)
759                 view3d_clr_clipping();
760         
761         /* signal that frontbuf differs from back */
762         curarea->win_swap= WIN_FRONT_OK;
763
764         dm->release(dm);
765 }
766
767
768 /* best distance based on screen coords. 
769    use g.scene->selectmode to define how to use 
770    selected vertices and edges get disadvantage
771    return 1 if found one
772 */
773 static int unified_findnearest(EditVert **eve, EditEdge **eed, EditFace **efa) 
774 {
775         int dist= 75;
776         
777         *eve= NULL;
778         *eed= NULL;
779         *efa= NULL;
780         
781         if(G.scene->selectmode & SCE_SELECT_VERTEX)
782                 *eve= findnearestvert(&dist, SELECT, 0);
783         if(G.scene->selectmode & SCE_SELECT_FACE)
784                 *efa= findnearestface(&dist);
785
786         dist-= 20;      /* since edges select lines, we give dots advantage of 20 pix */
787         if(G.scene->selectmode & SCE_SELECT_EDGE)
788                 *eed= findnearestedge(&dist);
789
790         /* return only one of 3 pointers, for frontbuffer redraws */
791         if(*eed) {
792                 *efa= NULL; *eve= NULL;
793         }
794         else if(*efa) {
795                 *eve= NULL;
796         }
797         
798         return (*eve || *eed || *efa);
799 }
800
801 /* this as a way to compare the ares, perim  of 2 faces thay will scale to different sizes
802  *0.5 so smaller faces arnt ALWAYS selected with a thresh of 1.0 */
803 #define SCALE_CMP(a,b) ((a+a*thresh >= b) && (a-(a*thresh*0.5) <= b))
804
805 /* ****************  GROUP SELECTS ************** */
806 /* selects new faces/edges/verts based on the
807  existing selection
808
809 FACES GROUP
810  mode 1: same material
811  mode 2: same image
812  mode 3: same area
813  mode 4: same perimeter
814  mode 5: same normal
815  mode 6: same co-planer
816 */
817 int facegroup_select(short mode)
818 {
819         EditMesh *em = G.editMesh;
820         EditFace *efa, *base_efa=NULL;
821         unsigned int selcount=0; /*count how many new faces we select*/
822         
823         /*deselcount, count how many deselected faces are left, so we can bail out early
824         also means that if there are no deselected faces, we can avoid a lot of looping */
825         unsigned int deselcount=0; 
826         
827         short ok=0;
828         float thresh=G.scene->toolsettings->select_thresh;
829         
830         for(efa= em->faces.first; efa; efa= efa->next) {
831                 if (!efa->h) {
832                         if (efa->f & SELECT) {
833                                 efa->f1=1;
834                                 ok=1;
835                         } else {
836                                 efa->f1=0;
837                                 deselcount++; /* a deselected face we may select later */
838                         }
839                 }
840         }
841         
842         if (!ok || !deselcount) /* no data selected OR no more data to select */
843                 return 0;
844         
845         /*if mode is 3 then record face areas, 4 record perimeter */
846         if (mode==3) {
847                 for(efa= em->faces.first; efa; efa= efa->next) {
848                         efa->tmp.fp= EM_face_area(efa);
849                 }
850         } else if (mode==4) {
851                 for(efa= em->faces.first; efa; efa= efa->next) {
852                         efa->tmp.fp= EM_face_perimeter(efa);
853                 }
854         }
855         
856         for(base_efa= em->faces.first; base_efa; base_efa= base_efa->next) {
857                 if (base_efa->f1) { /* This was one of the faces originaly selected */
858                         if (mode==1) { /* same material */
859                                 for(efa= em->faces.first; efa; efa= efa->next) {
860                                         if (
861                                                 !(efa->f & SELECT) &&
862                                                 !efa->h &&
863                                                 base_efa->mat_nr == efa->mat_nr
864                                         ) {
865                                                 EM_select_face(efa, 1);
866                                                 selcount++;
867                                                 deselcount--;
868                                                 if (!deselcount) /*have we selected all posible faces?, if so return*/
869                                                         return selcount;
870                                         }
871                                 }
872                         } else if (mode==2) { /* same image */
873                                 MTFace *tf, *base_tf;
874
875                                 base_tf = (MTFace*)CustomData_em_get(&em->fdata, base_efa->data,
876                                                                      CD_MTFACE);
877
878                                 if(!base_tf)
879                                         return selcount;
880
881                                 for(efa= em->faces.first; efa; efa= efa->next) {
882                                         if (!(efa->f & SELECT) && !efa->h) {
883                                                 tf = (MTFace*)CustomData_em_get(&em->fdata, efa->data,
884                                                                                 CD_MTFACE);
885
886                                                 if(base_tf->tpage == tf->tpage) {
887                                                         EM_select_face(efa, 1);
888                                                         selcount++;
889                                                         deselcount--;
890                                                         if (!deselcount) /*have we selected all posible faces?, if so return*/
891                                                                 return selcount;
892                                                 }
893                                         }
894                                 }
895                         } else if (mode==3 || mode==4) { /* same area OR same perimeter, both use the same temp var */
896                                 for(efa= em->faces.first; efa; efa= efa->next) {
897                                         if (
898                                                 (!(efa->f & SELECT) && !efa->h) &&
899                                                 SCALE_CMP(base_efa->tmp.fp, efa->tmp.fp)
900                                         ) {
901                                                 EM_select_face(efa, 1);
902                                                 selcount++;
903                                                 deselcount--;
904                                                 if (!deselcount) /*have we selected all posible faces?, if so return*/
905                                                         return selcount;
906                                         }
907                                 }
908                         } else if (mode==5) { /* same normal */
909                                 float angle;
910                                 for(efa= em->faces.first; efa; efa= efa->next) {
911                                         if (!(efa->f & SELECT) && !efa->h) {
912                                                 angle= VecAngle2(base_efa->n, efa->n);
913                                                 if (angle/180.0<=thresh) {
914                                                         EM_select_face(efa, 1);
915                                                         selcount++;
916                                                         deselcount--;
917                                                         if (!deselcount) /*have we selected all posible faces?, if so return*/
918                                                                 return selcount;
919                                                 }
920                                         }
921                                 }
922                         } else if (mode==6) { /* same planer */
923                                 float angle, base_dot, dot;
924                                 base_dot= Inpf(base_efa->cent, base_efa->n);
925                                 for(efa= em->faces.first; efa; efa= efa->next) {
926                                         if (!(efa->f & SELECT) && !efa->h) {
927                                                 angle= VecAngle2(base_efa->n, efa->n);
928                                                 if (angle/180.0<=thresh) {
929                                                         dot=Inpf(efa->cent, base_efa->n);
930                                                         if (fabs(base_dot-dot) <= thresh) {
931                                                                 EM_select_face(efa, 1);
932                                                                 selcount++;
933                                                                 deselcount--;
934                                                                 if (!deselcount) /*have we selected all posible faces?, if so return*/
935                                                                         return selcount;
936                                                         }
937                                                 }
938                                         }
939                                 }
940                         }
941                 }
942         } /* end base_efa loop */
943         return selcount;
944 }
945
946
947 /*
948 EDGE GROUP
949  mode 1: same length
950  mode 2: same direction
951  mode 3: same number of face users
952  mode 4: similar face angles.
953  mode 5: similar crease
954  mode 6: similar seam
955  mode 7: similar sharp
956 */
957
958 /* this function is only used by edgegroup_select's edge angle */
959
960
961
962 static int edgegroup_select__internal(short mode)
963 {
964         EditMesh *em = G.editMesh;
965         EditEdge *eed, *base_eed=NULL;
966         unsigned int selcount=0; /* count how many new edges we select*/
967         
968         /*count how many visible selected edges there are,
969         so we can return when there are none left */
970         unsigned int deselcount=0;
971         
972         short ok=0;
973         float thresh=G.scene->toolsettings->select_thresh;
974         
975         for(eed= em->edges.first; eed; eed= eed->next) {
976                 if (!eed->h) {
977                         if (eed->f & SELECT) {
978                                 eed->f1=1;
979                                 ok=1;
980                         } else {
981                                 eed->f1=0;
982                                 deselcount++;
983                         }
984                         /* set all eed->tmp.l to 0 we use it later.
985                         for counting face users*/
986                         eed->tmp.l=0;
987                         eed->f2=0; /* only for mode 4, edge animations */
988                 }
989         }
990         
991         if (!ok || !deselcount) /* no data selected OR no more data to select*/
992                 return 0;
993         
994         if (mode==1) { /*store length*/
995                 for(eed= em->edges.first; eed; eed= eed->next) {
996                         if (!eed->h) /* dont calc data for hidden edges*/
997                                 eed->tmp.fp= VecLenf(eed->v1->co, eed->v2->co);
998                 }
999         } else if (mode==3) { /*store face users*/
1000                 EditFace *efa;
1001                 /* cound how many faces each edge uses use tmp->l */
1002                 for(efa= em->faces.first; efa; efa= efa->next) {
1003                         efa->e1->tmp.l++;
1004                         efa->e2->tmp.l++;
1005                         efa->e3->tmp.l++;
1006                         if (efa->e4) efa->e4->tmp.l++;
1007                 }
1008         } else if (mode==4) { /*store edge angles */
1009                 EditFace *efa;
1010                 int j;
1011                 /* cound how many faces each edge uses use tmp.l */
1012                 for(efa= em->faces.first; efa; efa= efa->next) {
1013                         /* here we use the edges temp data to assign a face
1014                         if a face has alredy been assigned (eed->f2==1)
1015                         we calculate the angle between the current face and
1016                         the edges previously found face.
1017                         store the angle in eed->tmp.fp (loosing the face eed->tmp.f)
1018                         but tagging eed->f2==2, so we know not to look at it again.
1019                         This only works for edges that connect to 2 faces. but its good enough
1020                         */
1021                         
1022                         /* se we can loop through face edges*/
1023                         j=0;
1024                         eed= efa->e1;
1025                         while (j<4) {
1026                                 if (j==1) eed= efa->e2;
1027                                 else if (j==2) eed= efa->e3;
1028                                 else if (j==3) {
1029                                         eed= efa->e4;
1030                                         if (!eed)
1031                                                 break;
1032                                 } /* done looping */
1033                                 
1034                                 if (!eed->h) { /* dont calc data for hidden edges*/
1035                                         if (eed->f2==2)
1036                                                 break;
1037                                         else if (eed->f2==0) /* first access, assign the face */
1038                                                 eed->tmp.f= efa;
1039                                         else if (eed->f2==1) /* second, we assign the angle*/
1040                                                 eed->tmp.fp= VecAngle2(eed->tmp.f->n, efa->n)/180;
1041                                         eed->f2++; /* f2==0 no face assigned. f2==1 one face found. f2==2 angle calculated.*/
1042                                 }
1043                                 j++;
1044                         }
1045                 }
1046         }
1047         
1048         for(base_eed= em->edges.first; base_eed; base_eed= base_eed->next) {
1049                 if (base_eed->f1) {
1050                         if (mode==1) { /* same length */
1051                                 for(eed= em->edges.first; eed; eed= eed->next) {
1052                                         if (
1053                                                 !(eed->f & SELECT) &&
1054                                                 !eed->h &&
1055                                                 SCALE_CMP(base_eed->tmp.fp, eed->tmp.fp)
1056                                         ) {
1057                                                 EM_select_edge(eed, 1);
1058                                                 selcount++;
1059                                                 deselcount--;
1060                                                 if (!deselcount) /*have we selected all posible faces?, if so return*/
1061                                                         return selcount;
1062                                         }
1063                                 }
1064                         } else if (mode==2) { /* same direction */
1065                                 float base_dir[3], dir[3], angle;
1066                                 VecSubf(base_dir, base_eed->v1->co, base_eed->v2->co);
1067                                 for(eed= em->edges.first; eed; eed= eed->next) {
1068                                         if (!(eed->f & SELECT) && !eed->h) {
1069                                                 VecSubf(dir, eed->v1->co, eed->v2->co);
1070                                                 angle= VecAngle2(base_dir, dir);
1071                                                 
1072                                                 if (angle>90) /* use the smallest angle between the edges */
1073                                                         angle= fabs(angle-180.0f);
1074                                                 
1075                                                 if (angle/90.0<=thresh) {
1076                                                         EM_select_edge(eed, 1);
1077                                                         selcount++;
1078                                                         deselcount--;
1079                                                         if (!deselcount) /*have we selected all posible faces?, if so return*/
1080                                                                 return selcount;
1081                                                 }
1082                                         }
1083                                 }
1084                         } else if (mode==3) { /* face users */                          
1085                                 for(eed= em->edges.first; eed; eed= eed->next) {
1086                                         if (
1087                                                 !(eed->f & SELECT) &&
1088                                                 !eed->h &&
1089                                                 base_eed->tmp.l==eed->tmp.l
1090                                         ) {
1091                                                 EM_select_edge(eed, 1);
1092                                                 selcount++;
1093                                                 deselcount--;
1094                                                 if (!deselcount) /*have we selected all posible faces?, if so return*/
1095                                                         return selcount;
1096                                         }
1097                                 }
1098                         } else if (mode==4 && base_eed->f2==2) { /* edge angles, f2==2 means the edge has an angle. */                          
1099                                 for(eed= em->edges.first; eed; eed= eed->next) {
1100                                         if (
1101                                                 !(eed->f & SELECT) &&
1102                                                 !eed->h &&
1103                                                 eed->f2==2 &&
1104                                                 (fabs(base_eed->tmp.fp-eed->tmp.fp)<=thresh)
1105                                         ) {
1106                                                 EM_select_edge(eed, 1);
1107                                                 selcount++;
1108                                                 deselcount--;
1109                                                 if (!deselcount) /*have we selected all posible faces?, if so return*/
1110                                                         return selcount;
1111                                         }
1112                                 }
1113                         } else if (mode==5) { /* edge crease */
1114                                 for(eed= em->edges.first; eed; eed= eed->next) {
1115                                         if (
1116                                                 !(eed->f & SELECT) &&
1117                                                 !eed->h &&
1118                                                 (fabs(base_eed->crease-eed->crease) <= thresh)
1119                                         ) {
1120                                                 EM_select_edge(eed, 1);
1121                                                 selcount++;
1122                                                 deselcount--;
1123                                                 if (!deselcount) /*have we selected all posible faces?, if so return*/
1124                                                         return selcount;
1125                                         }
1126                                 }
1127                         } else if (mode==6) { /* edge seam */
1128                                 for(eed= em->edges.first; eed; eed= eed->next) {
1129                                         if (
1130                                                 !(eed->f & SELECT) &&
1131                                                 !eed->h &&
1132                                                 (eed->seam == base_eed->seam)
1133                                         ) {
1134                                                 EM_select_edge(eed, 1);
1135                                                 selcount++;
1136                                                 deselcount--;
1137                                                 if (!deselcount) /*have we selected all posible faces?, if so return*/
1138                                                         return selcount;
1139                                         }
1140                                 }
1141                         } else if (mode==7) { /* edge sharp */
1142                                 for(eed= em->edges.first; eed; eed= eed->next) {
1143                                         if (
1144                                                 !(eed->f & SELECT) &&
1145                                                 !eed->h &&
1146                                                 (eed->sharp == base_eed->sharp)
1147                                         ) {
1148                                                 EM_select_edge(eed, 1);
1149                                                 selcount++;
1150                                                 deselcount--;
1151                                                 if (!deselcount) /*have we selected all posible faces?, if so return*/
1152                                                         return selcount;
1153                                         }
1154                                 }
1155                         }
1156                 }
1157         }       
1158         return selcount;
1159 }
1160 /* wrap the above function but do selection flushing edge to face */
1161 int edgegroup_select(short mode)
1162 {
1163         int selcount = edgegroup_select__internal(mode);
1164         
1165         if (selcount) {
1166                 /* Could run a generic flush function,
1167                  * but the problem is only that all edges of a face
1168                  * can be selected without the face becoming selected */
1169                 EditMesh *em = G.editMesh;
1170                 EditFace *efa;
1171                 for(efa= em->faces.first; efa; efa= efa->next) {
1172                         if (efa->v4) {
1173                                 if (efa->e1->f&SELECT && efa->e2->f&SELECT && efa->e3->f&SELECT && efa->e4->f&SELECT)
1174                                         efa->f |= SELECT;
1175                         }  else {
1176                                 if (efa->e1->f&SELECT && efa->e2->f&SELECT && efa->e3->f&SELECT)
1177                                         efa->f |= SELECT;
1178                         }
1179                 }
1180         }
1181         return selcount;
1182 }
1183
1184
1185
1186 /*
1187 VERT GROUP
1188  mode 1: same normal
1189  mode 2: same number of face users
1190  mode 3: same vertex groups
1191 */
1192 int vertgroup_select(short mode)
1193 {
1194         EditMesh *em = G.editMesh;
1195         EditVert *eve, *base_eve=NULL;
1196         
1197         unsigned int selcount=0; /* count how many new edges we select*/
1198         
1199         /*count how many visible selected edges there are,
1200         so we can return when there are none left */
1201         unsigned int deselcount=0;
1202         
1203         short ok=0;
1204         float thresh=G.scene->toolsettings->select_thresh;
1205         
1206         for(eve= em->verts.first; eve; eve= eve->next) {
1207                 if (!eve->h) {
1208                         if (eve->f & SELECT) {
1209                                 eve->f1=1;
1210                                 ok=1;
1211                         } else {
1212                                 eve->f1=0;
1213                                 deselcount++;
1214                         }
1215                         /* set all eve->tmp.l to 0 we use them later.*/
1216                         eve->tmp.l=0;
1217                 }
1218                 
1219         }
1220         
1221         if (!ok || !deselcount) /* no data selected OR no more data to select*/
1222                 return 0;
1223         
1224         
1225         if (mode==2) { /* store face users */
1226                 EditFace *efa;
1227                 
1228                 /* count how many faces each edge uses use tmp->l */
1229                 for(efa= em->faces.first; efa; efa= efa->next) {
1230                         efa->v1->tmp.l++;
1231                         efa->v2->tmp.l++;
1232                         efa->v3->tmp.l++;
1233                         if (efa->v4) efa->v4->tmp.l++;
1234                 }
1235         }
1236         
1237         
1238         for(base_eve= em->verts.first; base_eve; base_eve= base_eve->next) {
1239                 if (base_eve->f1) {
1240                                 
1241                         if (mode==1) { /* same normal */
1242                                 float angle;
1243                                 for(eve= em->verts.first; eve; eve= eve->next) {
1244                                         if (!(eve->f & SELECT) && !eve->h) {
1245                                                 angle= VecAngle2(base_eve->no, eve->no);
1246                                                 if (angle/180.0<=thresh) {
1247                                                         eve->f |= SELECT;
1248                                                         selcount++;
1249                                                         deselcount--;
1250                                                         if (!deselcount) /*have we selected all posible faces?, if so return*/
1251                                                                 return selcount;
1252                                                 }
1253                                         }
1254                                 }
1255                         } else if (mode==2) { /* face users */
1256                                 for(eve= em->verts.first; eve; eve= eve->next) {
1257                                         if (
1258                                                 !(eve->f & SELECT) &&
1259                                                 !eve->h &&
1260                                                 base_eve->tmp.l==eve->tmp.l
1261                                         ) {
1262                                                 eve->f |= SELECT;
1263                                                 selcount++;
1264                                                 deselcount--;
1265                                                 if (!deselcount) /*have we selected all posible faces?, if so return*/
1266                                                         return selcount;
1267                                         }
1268                                 }
1269                         } else if (mode==3) { /* vertex groups */
1270                                 MDeformVert *dvert, *base_dvert;
1271                                 short i, j; /* weight index */
1272
1273                                 base_dvert= CustomData_em_get(&em->vdata, base_eve->data,
1274                                         CD_MDEFORMVERT);
1275
1276                                 if (!base_dvert || base_dvert->totweight == 0)
1277                                         return selcount;
1278                                 
1279                                 for(eve= em->verts.first; eve; eve= eve->next) {
1280                                         dvert= CustomData_em_get(&em->vdata, eve->data,
1281                                                 CD_MDEFORMVERT);
1282
1283                                         if (dvert && !(eve->f & SELECT) && !eve->h && dvert->totweight) {
1284                                                 /* do the extra check for selection in the following if, so were not
1285                                                 checking verts that may be alredy selected */
1286                                                 for (i=0; base_dvert->totweight >i && !(eve->f & SELECT); i++) { 
1287                                                         for (j=0; dvert->totweight >j; j++) {
1288                                                                 if (base_dvert->dw[i].def_nr==dvert->dw[j].def_nr) {
1289                                                                         eve->f |= SELECT;
1290                                                                         selcount++;
1291                                                                         deselcount--;
1292                                                                         if (!deselcount) /*have we selected all posible faces?, if so return*/
1293                                                                                 return selcount;
1294                                                                         break;
1295                                                                 }
1296                                                         }
1297                                                 }
1298                                         }
1299                                 }
1300                         }
1301                 }
1302         } /* end basevert loop */
1303         return selcount;
1304 }
1305
1306 /* EditMode menu triggered from space.c by pressing Shift+G
1307 handles face/edge vert context and
1308 facegroup_select/edgegroup_select/vertgroup_select do all the work
1309 */
1310
1311 void select_mesh_group_menu()
1312 {
1313         short ret;
1314         int selcount, first_item=1, multi=0;
1315         char str[512] = "Select Similar "; /* total max length is 404 at the moment */
1316         
1317         if (!ELEM3(G.scene->selectmode, SCE_SELECT_VERTEX, SCE_SELECT_EDGE, SCE_SELECT_FACE)) {
1318                 multi=1;
1319         }
1320         
1321         if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1322                 if (multi) strcat(str, "%t|Vertices%x-1|");
1323                 else strcat(str, "Vertices %t|");
1324                 strcat(str, "    Normal %x1|    Face Users %x2|    Shared Vertex Groups%x3");
1325                 first_item=0;
1326         }
1327
1328         if(G.scene->selectmode & SCE_SELECT_EDGE) {
1329                 if (multi) {
1330                         if (first_item) strcat(str, "%t|Edges%x-1|");
1331                         else strcat(str, "|%l|Edges%x-1|");
1332                 } else strcat(str, "Edges %t|");
1333                 
1334                 strcat(str, "    Length %x10|    Direction %x20|    Face Users%x30|    Face Angle%x40|    Crease%x50|    Seam%x60|    Sharp%x70");
1335                 first_item=0;
1336         }
1337         
1338         if(G.scene->selectmode & SCE_SELECT_FACE) {
1339                 if (multi) {
1340                         strcat(str, "|%l|Faces%x-1|");
1341                 } else strcat(str, "Faces %t|");
1342                 strcat(str, "    Material %x100|    Image %x200|    Area %x300|    Perimeter %x400|    Normal %x500|    Co-Planar %x600");
1343         
1344         }
1345         
1346         ret= pupmenu(str);
1347         if (ret<1) return;
1348         
1349         if (ret<10) {
1350                 selcount= vertgroup_select(ret);
1351                 if (selcount) { /* update if data was selected */
1352                         EM_select_flush(); /* so that selected verts, go onto select faces */
1353                         G.totvertsel += selcount;
1354                         allqueue(REDRAWVIEW3D, 0);
1355                         if (EM_texFaceCheck())
1356                                 allqueue(REDRAWIMAGE, 0);
1357                         BIF_undo_push("Select Similar Vertices");
1358                 }
1359                 return;
1360         }
1361         
1362         if (ret<100) {
1363                 selcount= edgegroup_select(ret/10);
1364                 
1365                 if (selcount) { /* update if data was selected */
1366                         /*EM_select_flush();*/ /* dont use because it can end up selecting more edges and is not usefull*/
1367                         G.totedgesel+=selcount;
1368                         allqueue(REDRAWVIEW3D, 0);
1369                         if (EM_texFaceCheck())
1370                                 allqueue(REDRAWIMAGE, 0);
1371                         BIF_undo_push("Select Similar Edges");
1372                 }
1373                 return;
1374         }
1375         
1376         if (ret<1000) {
1377                 selcount= facegroup_select(ret/100);
1378                 if (selcount) { /* update if data was selected */
1379                         G.totfacesel+=selcount;
1380                         allqueue(REDRAWVIEW3D, 0);
1381                         if (EM_texFaceCheck())
1382                                 allqueue(REDRAWIMAGE, 0);
1383                         BIF_undo_push("Select Similar Faces");
1384                 }
1385                 return;
1386         }
1387 }
1388
1389 int mesh_layers_menu_charlen(CustomData *data, int type)
1390 {
1391         int i, len = 0;
1392         /* see if there is a duplicate */
1393         for(i=0; i<data->totlayer; i++) {
1394                 if((&data->layers[i])->type == type) {
1395                         /* we could count the chars here but we'll just assumeme each
1396                          * is 32 chars with some room for the menu text - 40 should be fine */
1397                         len+=40; 
1398                 }
1399         }
1400         return len;
1401 }
1402
1403 /* this function adds menu text into an existing string.
1404  * this string's size should be allocated with mesh_layers_menu_charlen */
1405 void mesh_layers_menu_concat(CustomData *data, int type, char *str) {
1406         int i, count = 0;
1407         char *str_pt = str;
1408         CustomDataLayer *layer;
1409         
1410         /* see if there is a duplicate */
1411         for(i=0; i<data->totlayer; i++) {
1412                 layer = &data->layers[i];
1413                 if(layer->type == type) {
1414                         str_pt += sprintf(str_pt, "%s%%x%d|", layer->name, count);
1415                         count++;
1416                 }
1417         }
1418 }
1419
1420 int mesh_layers_menu(CustomData *data, int type) {
1421         int ret;
1422         char *str_pt, *str;
1423         
1424         str_pt = str = MEM_mallocN(mesh_layers_menu_charlen(data, type) + 18, "layer menu");
1425         str[0] = '\0';
1426         
1427         str_pt += sprintf(str_pt, "Layers%%t|");
1428         
1429         mesh_layers_menu_concat(data, type, str_pt);
1430         
1431         ret = pupmenu(str);
1432         MEM_freeN(str);
1433         return ret;
1434 }
1435
1436 void EM_mesh_copy_edge(short type) 
1437 {
1438         EditMesh *em = G.editMesh;
1439         EditSelection *ese;
1440         short change=0;
1441         
1442         EditEdge *eed, *eed_act;
1443         float vec[3], vec_mid[3], eed_len, eed_len_act;
1444         
1445         if (!em) return;
1446         
1447         ese = em->selected.last;
1448         if (!ese) return;
1449         
1450         eed_act = (EditEdge*)ese->data;
1451         
1452         switch (type) {
1453         case 1: /* copy crease */
1454                 for(eed=em->edges.first; eed; eed=eed->next) {
1455                         if (eed->f & SELECT && eed != eed_act && eed->crease != eed_act->crease) {
1456                                 eed->crease = eed_act->crease;
1457                                 change = 1;
1458                         }
1459                 }
1460                 break;
1461         case 2: /* copy bevel weight */
1462                 for(eed=em->edges.first; eed; eed=eed->next) {
1463                         if (eed->f & SELECT && eed != eed_act && eed->bweight != eed_act->bweight) {
1464                                 eed->bweight = eed_act->bweight;
1465                                 change = 1;
1466                         }
1467                 }
1468                 break;
1469
1470         case 3: /* copy length */
1471                 eed_len_act = VecLenf(eed_act->v1->co, eed_act->v2->co);
1472                 for(eed=em->edges.first; eed; eed=eed->next) {
1473                         if (eed->f & SELECT && eed != eed_act) {
1474
1475                                 eed_len = VecLenf(eed->v1->co, eed->v2->co);
1476
1477                                 if (eed_len == eed_len_act) continue;
1478                                 /* if this edge is zero length we cont do anything with it*/
1479                                 if (eed_len == 0.0f) continue;
1480                                 if (eed_len_act == 0.0f) {
1481                                         VecAddf(vec_mid, eed->v1->co, eed->v2->co);
1482                                         VecMulf(vec_mid, 0.5);
1483                                         VECCOPY(eed->v1->co, vec_mid);
1484                                         VECCOPY(eed->v2->co, vec_mid);
1485                                 } else {
1486                                         /* copy the edge length */
1487                                         VecAddf(vec_mid, eed->v1->co, eed->v2->co);
1488                                         VecMulf(vec_mid, 0.5);
1489
1490                                         /* SCALE 1 */
1491                                         VecSubf(vec, eed->v1->co, vec_mid);
1492                                         VecMulf(vec, eed_len_act/eed_len);
1493                                         VecAddf(eed->v1->co, vec, vec_mid);
1494
1495                                         /* SCALE 2 */
1496                                         VecSubf(vec, eed->v2->co, vec_mid);
1497                                         VecMulf(vec, eed_len_act/eed_len);
1498                                         VecAddf(eed->v2->co, vec, vec_mid);
1499                                 }
1500                                 change = 1;
1501                         }
1502                 }
1503
1504                 if (change)
1505                         recalc_editnormals();
1506
1507                 break;
1508         }
1509         
1510         if (change) {
1511                 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
1512                 allqueue(REDRAWVIEW3D, 0);
1513                 allqueue(REDRAWBUTSEDIT, 0);
1514                 
1515                 BIF_undo_push("Copy Edge Attribute");
1516         }
1517 }
1518
1519 void EM_mesh_copy_face(short type)
1520 {
1521         EditMesh *em = G.editMesh;
1522         short change=0;
1523         
1524         EditFace *efa, *efa_act;
1525         MTFace *tf, *tf_act = NULL;
1526         MCol *mcol, *mcol_act = NULL;
1527         if (!em) return;
1528         efa_act = EM_get_actFace(0);
1529         
1530         if (!efa_act) return;
1531         
1532         tf_act =        CustomData_em_get(&em->fdata, efa_act->data, CD_MTFACE);
1533         mcol_act =      CustomData_em_get(&em->fdata, efa_act->data, CD_MCOL);
1534         
1535         switch (type) {
1536         case 1: /* copy material */
1537                 for(efa=em->faces.first; efa; efa=efa->next) {
1538                         if (efa->f & SELECT && efa->mat_nr != efa_act->mat_nr) {
1539                                 efa->mat_nr = efa_act->mat_nr;
1540                                 change = 1;
1541                         }
1542                 }
1543                 break;
1544         case 2: /* copy image */
1545                 if (!tf_act) {
1546                         error("mesh has no uv/image layers");
1547                         return;
1548                 }
1549                 for(efa=em->faces.first; efa; efa=efa->next) {
1550                         if (efa->f & SELECT && efa != efa_act) {
1551                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1552                                 if (tf_act->tpage) {
1553                                         tf->tpage = tf_act->tpage;
1554                                         tf->mode |= TF_TEX;
1555                                 } else {
1556                                         tf->tpage = NULL;
1557                                         tf->mode &= ~TF_TEX;
1558                                 }
1559                                 tf->tile= tf_act->tile;
1560                                 change = 1;
1561                         }
1562                 }
1563                 break;
1564
1565         case 3: /* copy UV's */
1566                 if (!tf_act) {
1567                         error("mesh has no uv/image layers");
1568                         return;
1569                 }
1570                 for(efa=em->faces.first; efa; efa=efa->next) {
1571                         if (efa->f & SELECT && efa != efa_act) {
1572                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1573                                 memcpy(tf->uv, tf_act->uv, sizeof(tf->uv));
1574                                 change = 1;
1575                         }
1576                 }
1577                 break;
1578         case 4: /* mode's */
1579                 if (!tf_act) {
1580                         error("mesh has no uv/image layers");
1581                         return;
1582                 }
1583                 for(efa=em->faces.first; efa; efa=efa->next) {
1584                         if (efa->f & SELECT && efa != efa_act) {
1585                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1586                                 tf->mode= tf_act->mode;
1587                                 change = 1;
1588                         }
1589                 }
1590                 break;
1591         case 5: /* copy transp's */
1592                 if (!tf_act) {
1593                         error("mesh has no uv/image layers");
1594                         return;
1595                 }
1596                 for(efa=em->faces.first; efa; efa=efa->next) {
1597                         if (efa->f & SELECT && efa != efa_act) {
1598                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1599                                 tf->transp= tf_act->transp;
1600                                 change = 1;
1601                         }
1602                 }
1603                 break;
1604
1605         case 6: /* copy vcols's */
1606                 if (!mcol_act) {
1607                         error("mesh has no color layers");
1608                         return;
1609                 } else {
1610                         /* guess the 4th color if needs be */
1611                         float val =- 1;
1612
1613                         if (!efa_act->v4) {
1614                                 /* guess the othe vale, we may need to use it
1615                                  * 
1616                                  * Modifying the 4th value of the mcol is ok here since its not seen
1617                                  * on a triangle
1618                                  * */
1619                                 val = ((float)(mcol_act->r +  (mcol_act+1)->r + (mcol_act+2)->r)) / 3; CLAMP(val, 0, 255);
1620                                 (mcol_act+3)->r = (char)val;
1621
1622                                 val = ((float)(mcol_act->g +  (mcol_act+1)->g + (mcol_act+2)->g)) / 3; CLAMP(val, 0, 255);
1623                                 (mcol_act+3)->g = (char)val;
1624
1625                                 val = ((float)(mcol_act->b +  (mcol_act+1)->b + (mcol_act+2)->b)) / 3; CLAMP(val, 0, 255);
1626                                 (mcol_act+3)->b = (char)val;
1627                         } 
1628
1629
1630                         for(efa=em->faces.first; efa; efa=efa->next) {
1631                                 if (efa->f & SELECT && efa != efa_act) {
1632                                         /* TODO - make copy from tri to quad guess the 4th vert */
1633                                         mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
1634                                         memcpy(mcol, mcol_act, sizeof(MCol)*4); 
1635                                         change = 1;
1636                                 }
1637                         }
1638                 }
1639                 break;
1640         }
1641         
1642         if (change) {
1643                 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
1644                 allqueue(REDRAWVIEW3D, 0);
1645                 allqueue(REDRAWBUTSEDIT, 0);
1646                 if (type==3) {
1647                         allqueue(REDRAWIMAGE, 0);                       
1648                 }
1649                 
1650                 BIF_undo_push("Copy Face Attribute");
1651         }
1652 }
1653
1654
1655 void EM_mesh_copy_face_layer(short type) 
1656 {
1657         EditMesh *em = G.editMesh;
1658         short change=0;
1659         
1660         EditFace *efa;
1661         MTFace *tf, *tf_from;
1662         MCol *mcol, *mcol_from;
1663         
1664         if (!em) return;
1665         
1666         switch(type) {
1667         case 7:
1668         case 8:
1669         case 9:
1670                 if (CustomData_number_of_layers(&em->fdata, CD_MTFACE)<2) {
1671                         error("mesh does not have multiple uv/image layers");
1672                         return;
1673                 } else {
1674                         int layer_orig_idx, layer_idx;
1675
1676                         layer_idx = mesh_layers_menu(&em->fdata, CD_MTFACE);
1677                         if (layer_idx<0) return;
1678
1679                         /* warning, have not updated mesh pointers however this is not needed since we swicth back */
1680                         layer_orig_idx = CustomData_get_active_layer(&em->fdata, CD_MTFACE);
1681                         if (layer_idx==layer_orig_idx)
1682                                 return;
1683
1684                         /* get the tfaces */
1685                         CustomData_set_layer_active(&em->fdata, CD_MTFACE, (int)layer_idx);
1686                         /* store the tfaces in our temp */
1687                         for(efa=em->faces.first; efa; efa=efa->next) {
1688                                 if (efa->f & SELECT) {
1689                                         efa->tmp.p = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1690                                 }       
1691                         }
1692                         CustomData_set_layer_active(&em->fdata, CD_MTFACE, layer_orig_idx);
1693                 }
1694                 break;
1695
1696         case 10: /* select vcol layers - make sure this stays in sync with above code */
1697                 if (CustomData_number_of_layers(&em->fdata, CD_MCOL)<2) {
1698                         error("mesh does not have multiple color layers");
1699                         return;
1700                 } else {
1701                         int layer_orig_idx, layer_idx;
1702
1703                         layer_idx = mesh_layers_menu(&em->fdata, CD_MCOL);
1704                         if (layer_idx<0) return;
1705
1706                         /* warning, have not updated mesh pointers however this is not needed since we swicth back */
1707                         layer_orig_idx = CustomData_get_active_layer(&em->fdata, CD_MCOL);
1708                         if (layer_idx==layer_orig_idx)
1709                                 return;
1710
1711                         /* get the tfaces */
1712                         CustomData_set_layer_active(&em->fdata, CD_MCOL, (int)layer_idx);
1713                         /* store the tfaces in our temp */
1714                         for(efa=em->faces.first; efa; efa=efa->next) {
1715                                 if (efa->f & SELECT) {
1716                                         efa->tmp.p = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
1717                                 }       
1718                         }
1719                         CustomData_set_layer_active(&em->fdata, CD_MCOL, layer_orig_idx);
1720
1721                 }
1722                 break;
1723         }
1724
1725         /* layer copy only - sanity checks done above */
1726         switch (type) {
1727         case 7: /* copy UV's only */
1728                 for(efa=em->faces.first; efa; efa=efa->next) {
1729                         if (efa->f & SELECT) {
1730                                 tf_from = (MTFace *)efa->tmp.p; /* not active but easier to use this way */
1731                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1732                                 memcpy(tf->uv, tf_from->uv, sizeof(tf->uv));
1733                                 change = 1;
1734                         }
1735                 }
1736                 break;
1737         case 8: /* copy image settings only */
1738                 for(efa=em->faces.first; efa; efa=efa->next) {
1739                         if (efa->f & SELECT) {
1740                                 tf_from = (MTFace *)efa->tmp.p; /* not active but easier to use this way */
1741                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1742                                 if (tf_from->tpage) {
1743                                         tf->tpage = tf_from->tpage;
1744                                         tf->mode |= TF_TEX;
1745                                 } else {
1746                                         tf->tpage = NULL;
1747                                         tf->mode &= ~TF_TEX;
1748                                 }
1749                                 tf->tile= tf_from->tile;
1750                                 change = 1;
1751                         }
1752                 }
1753                 break;
1754         case 9: /* copy all tface info */
1755                 for(efa=em->faces.first; efa; efa=efa->next) {
1756                         if (efa->f & SELECT) {
1757                                 tf_from = (MTFace *)efa->tmp.p; /* not active but easier to use this way */
1758                                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1759                                 memcpy(tf->uv, ((MTFace *)efa->tmp.p)->uv, sizeof(tf->uv));
1760                                 tf->tpage = tf_from->tpage;
1761                                 tf->mode = tf_from->mode;
1762                                 tf->transp = tf_from->transp;
1763                                 change = 1;
1764                         }
1765                 }
1766                 break;
1767         case 10:
1768                 for(efa=em->faces.first; efa; efa=efa->next) {
1769                         if (efa->f & SELECT) {
1770                                 mcol_from = (MCol *)efa->tmp.p; 
1771                                 mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
1772                                 memcpy(mcol, mcol_from, sizeof(MCol)*4);        
1773                                 change = 1;
1774                         }
1775                 }
1776                 break;
1777         }
1778
1779         if (change) {
1780                 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
1781                 allqueue(REDRAWVIEW3D, 0);
1782                 allqueue(REDRAWBUTSEDIT, 0);
1783                 
1784                 BIF_undo_push("Copy Face Layer");
1785         }
1786 }
1787
1788
1789 /* ctrl+c in mesh editmode */
1790 void mesh_copy_menu(void)
1791 {
1792         EditMesh *em = G.editMesh;
1793         EditSelection *ese;
1794         int ret;
1795         if (!em) return;
1796         
1797         ese = em->selected.last;
1798         
1799         /* Faces can have a NULL ese, so dont return on a NULL ese here */
1800         
1801         if(ese && ese->type == EDITVERT) {
1802                 /* EditVert *ev, *ev_act = (EditVert*)ese->data;
1803                 ret= pupmenu(""); */
1804         } else if(ese && ese->type == EDITEDGE) {
1805                 ret= pupmenu("Copy Active Edge to Selected%t|Crease%x1|Bevel Weight%x2|Length%x3");
1806                 if (ret<1) return;
1807                 
1808                 EM_mesh_copy_edge(ret);
1809                 
1810         } else if(ese==NULL || ese->type == EDITFACE) {
1811                 ret= pupmenu(
1812                         "Copy Face Selected%t|"
1813                         "Active Material%x1|Active Image%x2|Active UV Coords%x3|"
1814                         "Active Mode%x4|Active Transp%x5|Active Vertex Colors%x6|%l|"
1815
1816                         "TexFace UVs from layer%x7|"
1817                         "TexFace Images from layer%x8|"
1818                         "TexFace All from layer%x9|"
1819                         "Vertex Colors from layer%x10");
1820                 if (ret<1) return;
1821                 
1822                 if (ret<=6) {
1823                         EM_mesh_copy_face(ret);
1824                 } else {
1825                         EM_mesh_copy_face_layer(ret);
1826                 }
1827         }
1828 }
1829
1830
1831 /* ****************  LOOP SELECTS *************** */
1832
1833 /* selects quads in loop direction of indicated edge */
1834 /* only flush over edges with valence <= 2 */
1835 void faceloop_select(EditEdge *startedge, int select)
1836 {
1837         EditMesh *em = G.editMesh;
1838         EditEdge *eed;
1839         EditFace *efa;
1840         int looking= 1;
1841         
1842         /* in eed->f1 we put the valence (amount of faces in edge) */
1843         /* in eed->f2 we put tagged flag as correct loop */
1844         /* in efa->f1 we put tagged flag as correct to select */
1845
1846         for(eed= em->edges.first; eed; eed= eed->next) {
1847                 eed->f1= 0;
1848                 eed->f2= 0;
1849         }
1850         for(efa= em->faces.first; efa; efa= efa->next) {
1851                 efa->f1= 0;
1852                 if(efa->h==0) {
1853                         efa->e1->f1++;
1854                         efa->e2->f1++;
1855                         efa->e3->f1++;
1856                         if(efa->e4) efa->e4->f1++;
1857                 }
1858         }
1859         
1860         /* tag startedge OK*/
1861         startedge->f2= 1;
1862         
1863         while(looking) {
1864                 looking= 0;
1865                 
1866                 for(efa= em->faces.first; efa; efa= efa->next) {
1867                         if(efa->e4 && efa->f1==0) {     /* not done quad */
1868                                 if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { /* valence ok */
1869
1870                                         /* if edge tagged, select opposing edge and mark face ok */
1871                                         if(efa->e1->f2) {
1872                                                 efa->e3->f2= 1;
1873                                                 efa->f1= 1;
1874                                                 looking= 1;
1875                                         }
1876                                         else if(efa->e2->f2) {
1877                                                 efa->e4->f2= 1;
1878                                                 efa->f1= 1;
1879                                                 looking= 1;
1880                                         }
1881                                         if(efa->e3->f2) {
1882                                                 efa->e1->f2= 1;
1883                                                 efa->f1= 1;
1884                                                 looking= 1;
1885                                         }
1886                                         if(efa->e4->f2) {
1887                                                 efa->e2->f2= 1;
1888                                                 efa->f1= 1;
1889                                                 looking= 1;
1890                                         }
1891                                 }
1892                         }
1893                 }
1894         }
1895         
1896         /* (de)select the faces */
1897         if(select!=2) {
1898                 for(efa= em->faces.first; efa; efa= efa->next) {
1899                         if(efa->f1) EM_select_face(efa, select);
1900                 }
1901         }
1902 }
1903
1904
1905 /* helper for edgeloop_select, checks for eed->f2 tag in faces */
1906 static int edge_not_in_tagged_face(EditEdge *eed)
1907 {
1908         EditMesh *em = G.editMesh;
1909         EditFace *efa;
1910         
1911         for(efa= em->faces.first; efa; efa= efa->next) {
1912                 if(efa->h==0) {
1913                         if(efa->e1==eed || efa->e2==eed || efa->e3==eed || efa->e4==eed) {      /* edge is in face */
1914                                 if(efa->e1->f2 || efa->e2->f2 || efa->e3->f2 || (efa->e4 && efa->e4->f2)) {     /* face is tagged */
1915                                         return 0;
1916                                 }
1917                         }
1918                 }
1919         }
1920         return 1;
1921 }
1922
1923 /* selects or deselects edges that:
1924 - if edges has 2 faces:
1925         - has vertices with valence of 4
1926         - not shares face with previous edge
1927 - if edge has 1 face:
1928         - has vertices with valence 4
1929         - not shares face with previous edge
1930         - but also only 1 face
1931 - if edge no face:
1932         - has vertices with valence 2
1933 */
1934 static void edgeloop_select(EditEdge *starteed, int select)
1935 {
1936         EditMesh *em = G.editMesh;
1937         EditVert *eve;
1938         EditEdge *eed;
1939         EditFace *efa;
1940         int looking= 1;
1941         
1942         /* in f1 we put the valence (amount of edges in a vertex, or faces in edge) */
1943         /* in eed->f2 and efa->f1 we put tagged flag as correct loop */
1944         for(eve= em->verts.first; eve; eve= eve->next) {
1945                 eve->f1= 0;
1946                 eve->f2= 0;
1947         }
1948         for(eed= em->edges.first; eed; eed= eed->next) {
1949                 eed->f1= 0;
1950                 eed->f2= 0;
1951                 if((eed->h & 1)==0) {   /* fgon edges add to valence too */
1952                         eed->v1->f1++; eed->v2->f1++;
1953                 }
1954         }
1955         for(efa= em->faces.first; efa; efa= efa->next) {
1956                 efa->f1= 0;
1957                 if(efa->h==0) {
1958                         efa->e1->f1++;
1959                         efa->e2->f1++;
1960                         efa->e3->f1++;
1961                         if(efa->e4) efa->e4->f1++;
1962                 }
1963         }
1964         
1965         /* looped edges & vertices get tagged f2 */
1966         starteed->f2= 1;
1967         if(starteed->v1->f1<5) starteed->v1->f2= 1;
1968         if(starteed->v2->f1<5) starteed->v2->f2= 1;
1969         /* sorry, first edge isnt even ok */
1970         if(starteed->v1->f2==0 && starteed->v2->f2==0) looking= 0;
1971         
1972         while(looking) {
1973                 looking= 0;
1974                 
1975                 /* find correct valence edges which are not tagged yet, but connect to tagged one */
1976                 for(eed= em->edges.first; eed; eed= eed->next) {
1977                         if(eed->h==0 && eed->f2==0) { /* edge not hidden, not tagged */
1978                                 if( (eed->v1->f1<5 && eed->v1->f2) || (eed->v2->f1<5 && eed->v2->f2)) { /* valence of vertex OK, and is tagged */
1979                                         /* new edge is not allowed to be in face with tagged edge */
1980                                         if(edge_not_in_tagged_face(eed)) {
1981                                                 if(eed->f1==starteed->f1) {     /* same amount of faces */
1982                                                         looking= 1;
1983                                                         eed->f2= 1;
1984                                                         if(eed->v2->f1<5) eed->v2->f2= 1;
1985                                                         if(eed->v1->f1<5) eed->v1->f2= 1;
1986                                                 }
1987                                         }
1988                                 }
1989                         }
1990                 }
1991         }
1992         /* and we do the select */
1993         for(eed= em->edges.first; eed; eed= eed->next) {
1994                 if(eed->f2) EM_select_edge(eed, select);
1995         }
1996 }
1997
1998 /* 
1999    Almostly exactly the same code as faceloop select
2000 */
2001 static void edgering_select(EditEdge *startedge, int select){
2002         EditMesh *em = G.editMesh;
2003         EditEdge *eed;
2004         EditFace *efa;
2005         int looking= 1;
2006         
2007         /* in eed->f1 we put the valence (amount of faces in edge) */
2008         /* in eed->f2 we put tagged flag as correct loop */
2009         /* in efa->f1 we put tagged flag as correct to select */
2010
2011         for(eed= em->edges.first; eed; eed= eed->next) {
2012                 eed->f1= 0;
2013                 eed->f2= 0;
2014         }
2015         for(efa= em->faces.first; efa; efa= efa->next) {
2016                 efa->f1= 0;
2017                 if(efa->h==0) {
2018                         efa->e1->f1++;
2019                         efa->e2->f1++;
2020                         efa->e3->f1++;
2021                         if(efa->e4) efa->e4->f1++;
2022                 }
2023         }
2024         
2025         /* tag startedge OK */
2026         startedge->f2= 1;
2027         
2028         while(looking) {
2029                 looking= 0;
2030                 
2031                 for(efa= em->faces.first; efa; efa= efa->next) {
2032                         if(efa->e4 && efa->f1==0 && !efa->h) {  /* not done quad */
2033                                 if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { /* valence ok */
2034
2035                                         /* if edge tagged, select opposing edge and mark face ok */
2036                                         if(efa->e1->f2) {
2037                                                 efa->e3->f2= 1;
2038                                                 efa->f1= 1;
2039                                                 looking= 1;
2040                                         }
2041                                         else if(efa->e2->f2) {
2042                                                 efa->e4->f2= 1;
2043                                                 efa->f1= 1;
2044                                                 looking= 1;
2045                                         }
2046                                         if(efa->e3->f2) {
2047                                                 efa->e1->f2= 1;
2048                                                 efa->f1= 1;
2049                                                 looking= 1;
2050                                         }
2051                                         if(efa->e4->f2) {
2052                                                 efa->e2->f2= 1;
2053                                                 efa->f1= 1;
2054                                                 looking= 1;
2055                                         }
2056                                 }
2057                         }
2058                 }
2059         }
2060         
2061         /* (de)select the edges */
2062         for(eed= em->edges.first; eed; eed= eed->next) {
2063                 if(eed->f2) EM_select_edge(eed, select);
2064         }
2065 }
2066
2067 void loop_multiselect(int looptype)
2068 {
2069         EditEdge *eed;
2070         EditEdge **edarray;
2071         int edindex, edfirstcount;
2072         
2073         /*edarray = MEM_mallocN(sizeof(*edarray)*G.totedgesel,"edge array");*/
2074         edarray = MEM_mallocN(sizeof(EditEdge*)*G.totedgesel,"edge array");
2075         edindex = 0;
2076         edfirstcount = G.totedgesel;
2077         
2078         for(eed=G.editMesh->edges.first; eed; eed=eed->next){
2079                 if(eed->f&SELECT){
2080                         edarray[edindex] = eed;
2081                         edindex += 1;
2082                 }
2083         }
2084         
2085         if(looptype){
2086                 for(edindex = 0; edindex < edfirstcount; edindex +=1){
2087                         eed = edarray[edindex];
2088                         edgering_select(eed,SELECT);
2089                 }
2090                 countall();
2091                 EM_selectmode_flush();
2092                 BIF_undo_push("Edge Ring Multi-Select");
2093         }
2094         else{
2095                 for(edindex = 0; edindex < edfirstcount; edindex +=1){
2096                         eed = edarray[edindex];
2097                         edgeloop_select(eed,SELECT);
2098                 }
2099                 countall();
2100                 EM_selectmode_flush();
2101                 BIF_undo_push("Edge Loop Multi-Select");
2102         }
2103         MEM_freeN(edarray);
2104         allqueue(REDRAWVIEW3D,0);
2105         if (EM_texFaceCheck())
2106                 allqueue(REDRAWIMAGE, 0);
2107 }
2108                 
2109 /* ***************** MAIN MOUSE SELECTION ************** */
2110
2111 /* just to have the functions nice together */
2112
2113 static void mouse_mesh_loop(void)
2114 {
2115         EditEdge *eed;
2116         int select= 1;
2117         int dist= 50;
2118         
2119         eed= findnearestedge(&dist);
2120         if(eed) {
2121                 if (G.scene->toolsettings->edge_mode == EDGE_MODE_SELECT) {
2122                         if((G.qual & LR_SHIFTKEY)==0) EM_clear_flag_all(SELECT);
2123                 
2124                         if((eed->f & SELECT)==0) select=1;
2125                         else if(G.qual & LR_SHIFTKEY) select=0;
2126
2127                         if(G.scene->selectmode & SCE_SELECT_FACE) {
2128                                 faceloop_select(eed, select);
2129                         }
2130                         else if(G.scene->selectmode & SCE_SELECT_EDGE) {
2131                         if(G.qual == (LR_CTRLKEY | LR_ALTKEY) || G.qual == (LR_CTRLKEY | LR_ALTKEY |LR_SHIFTKEY))
2132                                         edgering_select(eed, select);
2133                         else if(G.qual & LR_ALTKEY)
2134                                         edgeloop_select(eed, select);
2135                         }
2136                     else if(G.scene->selectmode & SCE_SELECT_VERTEX) {
2137                         if(G.qual == (LR_CTRLKEY | LR_ALTKEY) || G.qual == (LR_CTRLKEY | LR_ALTKEY |LR_SHIFTKEY))
2138                                         edgering_select(eed, select);
2139                         else if(G.qual & LR_ALTKEY)
2140                                         edgeloop_select(eed, select);
2141                         }
2142
2143                         /* frontbuffer draw of last selected only */
2144                         unified_select_draw(NULL, eed, NULL);
2145                 
2146                         EM_selectmode_flush();
2147                         countall();
2148                         allqueue(REDRAWVIEW3D, 0);
2149                         if (EM_texFaceCheck())
2150                                 allqueue(REDRAWIMAGE, 0);
2151                 } else { /*(G.scene->toolsettings->edge_mode == EDGE_MODE_TAG_*)*/
2152                         int act = (edgetag_context_check(eed)==0);
2153                         int path = 0;
2154                         
2155                         if (G.qual == (LR_SHIFTKEY | LR_ALTKEY) && G.editMesh->selected.last) {
2156                                 EditSelection *ese = G.editMesh->selected.last;
2157         
2158                                 if(ese && ese->type == EDITEDGE) {
2159                                         EditEdge *eed_act;
2160                                         eed_act = (EditEdge*)ese->data;
2161                                         if (eed_act != eed) {
2162                                                 /* If shift is pressed we need to use the last active edge, (if it exists) */
2163                                                 if (edgetag_shortest_path(eed_act, eed)) {
2164                                                         EM_remove_selection(eed_act, EDITEDGE);
2165                                                         EM_select_edge(eed_act, 0);
2166                                                         path = 1;
2167                                                 }
2168                                         }
2169                                 }
2170                         }
2171                         if (path==0) {
2172                                 edgetag_context_set(eed, act); /* switch the edge option */
2173                         }
2174                         
2175                         if (act) {
2176                                 if ((eed->f & SELECT)==0) {
2177                                         EM_select_edge(eed, 1);
2178                                         EM_selectmode_flush();
2179                                         countall();
2180                                 }
2181                                 /* even if this is selected it may not be in the selection list */
2182                                 EM_store_selection(eed, EDITEDGE);
2183                         } else {
2184                                 if (eed->f & SELECT) {
2185                                         EM_select_edge(eed, 0);
2186                                         /* logic is differnt from above here since if this was selected we dont know if its in the selection list or not */
2187                                         EM_remove_selection(eed, EDITEDGE);
2188                                         
2189                                         EM_selectmode_flush();
2190                                         countall();
2191                                 }
2192                         }
2193                         
2194                         switch (G.scene->toolsettings->edge_mode) {
2195                         case EDGE_MODE_TAG_SEAM:
2196                                 G.f |= G_DRAWSEAMS;
2197                                 break;
2198                         case EDGE_MODE_TAG_SHARP:
2199                                 G.f |= G_DRAWSHARP;
2200                                 break;
2201                         case EDGE_MODE_TAG_CREASE:      
2202                                 G.f |= G_DRAWCREASES;
2203                                 break;
2204                         case EDGE_MODE_TAG_BEVEL:
2205                                 G.f |= G_DRAWBWEIGHTS;
2206                                 break;
2207                         }
2208                         
2209                         unified_select_draw(NULL, eed, NULL);
2210                         
2211                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2212                         allqueue(REDRAWVIEW3D, 0);
2213                 }
2214                                 
2215         }
2216 }
2217
2218
2219 /* here actual select happens */
2220 void mouse_mesh(void)
2221 {
2222         EditVert *eve;
2223         EditEdge *eed;
2224         EditFace *efa;
2225         
2226         if(G.qual & LR_ALTKEY) mouse_mesh_loop();
2227         else if(unified_findnearest(&eve, &eed, &efa)) {
2228                 
2229                 if((G.qual & LR_SHIFTKEY)==0) EM_clear_flag_all(SELECT);
2230                 
2231                 if(efa) {
2232                         /* set the last selected face */
2233                         EM_set_actFace(efa);
2234                         
2235                         if( (efa->f & SELECT)==0 ) {
2236                                 EM_store_selection(efa, EDITFACE);
2237                                 EM_select_face_fgon(efa, 1);
2238                         }
2239                         else if(G.qual & LR_SHIFTKEY) {
2240                                 EM_remove_selection(efa, EDITFACE);
2241                                 EM_select_face_fgon(efa, 0);
2242                         }
2243                 }
2244                 else if(eed) {
2245                         if((eed->f & SELECT)==0) {
2246                                 EM_store_selection(eed, EDITEDGE);
2247                                 EM_select_edge(eed, 1);
2248                         }
2249                         else if(G.qual & LR_SHIFTKEY) {
2250                                 EM_remove_selection(eed, EDITEDGE);
2251                                 EM_select_edge(eed, 0);
2252                         }
2253                 }
2254                 else if(eve) {
2255                         if((eve->f & SELECT)==0) {
2256                                 eve->f |= SELECT;
2257                                 EM_store_selection(eve, EDITVERT);
2258                         }
2259                         else if(G.qual & LR_SHIFTKEY){ 
2260                                 EM_remove_selection(eve, EDITVERT);
2261                                 eve->f &= ~SELECT;
2262                         }
2263                 }
2264                 
2265                 /* frontbuffer draw of last selected only */
2266                 unified_select_draw(eve, eed, efa);
2267         
2268                 EM_selectmode_flush();
2269                 countall();
2270                   
2271                 allqueue(REDRAWVIEW3D, 0);
2272                 if (EM_texFaceCheck()) {
2273                         allqueue(REDRAWIMAGE, 0);
2274                         allqueue(REDRAWBUTSEDIT, 0); /* for the texture face panel */
2275                 }
2276                 if (efa && efa->mat_nr != G.obedit->actcol-1) {
2277                         G.obedit->actcol= efa->mat_nr+1;
2278                         allqueue(REDRAWBUTSEDIT, 0);
2279                         allqueue(REDRAWBUTSSHADING, 0);
2280                         BIF_preview_changed(ID_MA);
2281                 }
2282         }
2283
2284         rightmouse_transform();
2285 }
2286
2287
2288 void selectconnected_mesh_all(void)
2289 {
2290         EditMesh *em = G.editMesh;
2291         EditVert *v1,*v2;
2292         EditEdge *eed;
2293         short done=1, toggle=0;
2294
2295         if(em->edges.first==0) return;
2296         
2297         while(done==1) {
2298                 done= 0;
2299                 
2300                 toggle++;
2301                 if(toggle & 1) eed= em->edges.first;
2302                 else eed= em->edges.last;
2303                 
2304                 while(eed) {
2305                         v1= eed->v1;
2306                         v2= eed->v2;
2307                         if(eed->h==0) {
2308                                 if(v1->f & SELECT) {
2309                                         if( (v2->f & SELECT)==0 ) {
2310                                                 v2->f |= SELECT;
2311                                                 done= 1;
2312                                         }
2313                                 }
2314                                 else if(v2->f & SELECT) {
2315                                         if( (v1->f & SELECT)==0 ) {
2316                                                 v1->f |= SELECT;
2317                                                 done= 1;
2318                                         }
2319                                 }
2320                         }
2321                         if(toggle & 1) eed= eed->next;
2322                         else eed= eed->prev;
2323                 }
2324         }
2325
2326         /* now use vertex select flag to select rest */
2327         EM_select_flush();
2328         
2329         countall();
2330
2331         allqueue(REDRAWVIEW3D, 0);
2332         if (EM_texFaceCheck())
2333                 allqueue(REDRAWIMAGE, 0);
2334         BIF_undo_push("Select Connected (All)");
2335 }
2336
2337 void selectconnected_mesh(void)
2338 {
2339         EditMesh *em = G.editMesh;
2340         EditVert *eve, *v1, *v2;
2341         EditEdge *eed;
2342         EditFace *efa;
2343         short done=1, sel, toggle=0;
2344
2345         if(em->edges.first==0) return;
2346         
2347         if( unified_findnearest(&eve, &eed, &efa)==0 ) {
2348                 /* error("Nothing indicated "); */ /* this is mostly annoying, eps with occluded geometry */
2349                 return;
2350         }
2351         
2352         sel= 1;
2353         if(G.qual & LR_SHIFTKEY) sel=0;
2354
2355         /* clear test flags */
2356         for(v1= em->verts.first; v1; v1= v1->next) v1->f1= 0;
2357         
2358         /* start vertex/face/edge */
2359         if(eve) eve->f1= 1;
2360         else if(eed) eed->v1->f1= eed->v2->f1= 1;
2361         else efa->v1->f1= efa->v2->f1= efa->v3->f1= 1;
2362         
2363         /* set flag f1 if affected */
2364         while(done==1) {
2365                 done= 0;
2366                 toggle++;
2367                 
2368                 if(toggle & 1) eed= em->edges.first;
2369                 else eed= em->edges.last;
2370                 
2371                 while(eed) {
2372                         v1= eed->v1;
2373                         v2= eed->v2;
2374                         
2375                         if(eed->h==0) {
2376                                 if(v1->f1 && v2->f1==0) {
2377                                         v2->f1= 1;
2378                                         done= 1;
2379                                 }
2380                                 else if(v1->f1==0 && v2->f1) {
2381                                         v1->f1= 1;
2382                                         done= 1;
2383                                 }
2384                         }
2385                         
2386                         if(toggle & 1) eed= eed->next;
2387                         else eed= eed->prev;
2388                 }
2389         }
2390         
2391         /* now use vertex f1 flag to select/deselect */
2392         for(eed= em->edges.first; eed; eed= eed->next) {
2393                 if(eed->v1->f1 && eed->v2->f1) 
2394                         EM_select_edge(eed, sel);
2395         }
2396         for(efa= em->faces.first; efa; efa= efa->next) {
2397                 if(efa->v1->f1 && efa->v2->f1 && efa->v3->f1 && (efa->v4==NULL || efa->v4->f1)) 
2398                         EM_select_face(efa, sel);
2399         }
2400         /* no flush needed, connected geometry is done */
2401         
2402         countall();
2403         
2404         allqueue(REDRAWVIEW3D, 0);
2405         if (EM_texFaceCheck())
2406                 allqueue(REDRAWIMAGE, 0);
2407         
2408         BIF_undo_push("Select Linked");
2409         
2410 }
2411
2412 /* for use with selectconnected_delimit_mesh only! */
2413 #define is_edge_delimit_ok(eed) ((eed->tmp.l == 1) && (eed->seam==0))
2414 #define is_face_tag(efa) is_edge_delimit_ok(efa->e1) || is_edge_delimit_ok(efa->e2) || is_edge_delimit_ok(efa->e3) || (efa->v4 && is_edge_delimit_ok(efa->e4))
2415
2416 #define face_tag(efa)\
2417         if(efa->v4)     efa->tmp.l=             efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= efa->e4->tmp.l= 1;\
2418         else            efa->tmp.l=             efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= 1;
2419
2420 /* all - 1) use all faces for extending the selection  2) only use the mouse face
2421  * sel - 1) select  0) deselect 
2422  * */
2423 static void selectconnected_delimit_mesh__internal(short all, short sel)
2424 {
2425         EditMesh *em = G.editMesh;
2426         EditFace *efa;
2427         short done=1, change=0;
2428         int dist = 75;
2429         EditEdge *eed;
2430         if(em->faces.first==0) return;
2431         
2432         /* flag all edges as off*/
2433         for(eed= em->edges.first; eed; eed= eed->next)
2434                 eed->tmp.l=0;
2435         
2436         if (all) {
2437                 for(efa= em->faces.first; efa; efa= efa->next) {
2438                         if (efa->f & SELECT) {
2439                                 face_tag(efa);
2440                         } else {
2441                                 efa->tmp.l = 0;
2442                         }
2443                 }
2444         } else {
2445                 EditFace *efa_mouse = findnearestface(&dist);
2446                 
2447                 if( !efa_mouse ) {
2448                         /* error("Nothing indicated "); */ /* this is mostly annoying, eps with occluded geometry */
2449                         return;
2450                 }
2451                 
2452                 for(efa= em->faces.first; efa; efa= efa->next) {
2453                         efa->tmp.l = 0;
2454                 }
2455                 efa_mouse->tmp.l = 1;
2456                 face_tag(efa_mouse);
2457         }
2458         
2459         while(done==1) {
2460                 done= 0;
2461                 /* simple algo - select all faces that have a selected edge
2462                  * this intern selects the edge, repeat until nothing is left to do */
2463                 for(efa= em->faces.first; efa; efa= efa->next) {
2464                         if ((efa->tmp.l == 0) && (!efa->h)) {
2465                                 if (is_face_tag(efa)) {
2466                                         face_tag(efa);
2467                                         done= 1;
2468                                 }
2469                         }
2470                 }
2471         }
2472         
2473         for(efa= em->faces.first; efa; efa= efa->next) {
2474                 if (efa->tmp.l) {
2475                         if (sel) {
2476                                 if (!(efa->f & SELECT)) {
2477                                         EM_select_face(efa, 1);
2478                                         change = 1;
2479                                 }
2480                         } else {
2481                                 if (efa->f & SELECT) {
2482                                         EM_select_face(efa, 0);
2483                                         change = 1;
2484                                 }
2485                         }
2486                 }
2487         }
2488         
2489         if (!change)
2490                 return;
2491         
2492         if (!sel) /* make sure de-selecting faces didnt de-select the verts/edges connected to selected faces, this is common with boundries */
2493                 for(efa= em->faces.first; efa; efa= efa->next)
2494                         if (efa->f & SELECT)
2495                                 EM_select_face(efa, 1);
2496         
2497         countall();
2498         
2499         allqueue(REDRAWVIEW3D, 0);
2500         if (EM_texFaceCheck())
2501                 allqueue(REDRAWIMAGE, 0);
2502         
2503         BIF_undo_push("Select Linked Delimeted");
2504         
2505 }
2506
2507 #undef is_edge_delimit_ok
2508 #undef is_face_tag
2509 #undef face_tag
2510
2511 void selectconnected_delimit_mesh(void)
2512 {
2513         selectconnected_delimit_mesh__internal(0, ((G.qual & LR_SHIFTKEY)==0));
2514 }
2515 void selectconnected_delimit_mesh_all(void)
2516 {
2517         selectconnected_delimit_mesh__internal(1, 1);
2518 }       
2519         
2520         
2521 /* swap is 0 or 1, if 1 it hides not selected */
2522 void hide_mesh(int swap)
2523 {
2524         EditMesh *em = G.editMesh;
2525         EditVert *eve;
2526         EditEdge *eed;
2527         EditFace *efa;
2528         int a;
2529         
2530         if(G.obedit==0) return;
2531
2532         /* hide happens on least dominant select mode, and flushes up, not down! (helps preventing errors in subsurf) */
2533         /*  - vertex hidden, always means edge is hidden too
2534                 - edge hidden, always means face is hidden too
2535                 - face hidden, only set face hide
2536                 - then only flush back down what's absolute hidden
2537         */
2538         if(G.scene->selectmode & SCE_SELECT_VERTEX) {
2539                 for(eve= em->verts.first; eve; eve= eve->next) {
2540                         if((eve->f & SELECT)!=swap) {
2541                                 eve->f &= ~SELECT;
2542                                 eve->h= 1;
2543                         }
2544                 }
2545         
2546                 for(eed= em->edges.first; eed; eed= eed->next) {
2547                         if(eed->v1->h || eed->v2->h) {
2548                                 eed->h |= 1;
2549                                 eed->f &= ~SELECT;
2550                         }
2551                 }
2552         
2553                 for(efa= em->faces.first; efa; efa= efa->next) {
2554                         if(efa->e1->h & 1 || efa->e2->h & 1 || efa->e3->h & 1 || (efa->e4 && efa->e4->h & 1)) {
2555                                 efa->h= 1;
2556                                 efa->f &= ~SELECT;
2557                         }
2558                 }
2559         }
2560         else if(G.scene->selectmode & SCE_SELECT_EDGE) {
2561
2562                 for(eed= em->edges.first; eed; eed= eed->next) {
2563                         if((eed->f & SELECT)!=swap) {
2564                                 eed->h |= 1;
2565                                 EM_select_edge(eed, 0);
2566                         }
2567                 }
2568
2569                 for(efa= em->faces.first; efa; efa= efa->next) {
2570                         if(efa->e1->h & 1 || efa->e2->h & 1 || efa->e3->h & 1 || (efa->e4 && efa->e4->h & 1)) {
2571                                 efa->h= 1;
2572                                 efa->f &= ~SELECT;
2573                         }
2574                 }
2575         }
2576         else {
2577
2578                 for(efa= em->faces.first; efa; efa= efa->next) {
2579                         if((efa->f & SELECT)!=swap) {
2580                                 efa->h= 1;
2581                                 EM_select_face(efa, 0);
2582                         }
2583                 }
2584         }
2585         
2586         /* flush down, only whats 100% hidden */
2587         for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2588         for(eed= em->edges.first; eed; eed= eed->next) eed->f1= 0;
2589         
2590         if(G.scene->selectmode & SCE_SELECT_FACE) {
2591                 for(efa= em->faces.first; efa; efa= efa->next) {
2592                         if(efa->h) a= 1; else a= 2;
2593                         efa->e1->f1 |= a;
2594                         efa->e2->f1 |= a;
2595                         efa->e3->f1 |= a;
2596                         if(efa->e4) efa->e4->f1 |= a;
2597                         /* When edges are not delt with in their own loop, we need to explicitly re-selct select edges that are joined to unselected faces */
2598                         if (swap && (G.scene->selectmode == SCE_SELECT_FACE) && (efa->f & SELECT)) {
2599                                 EM_select_face(efa, 1);
2600                         }
2601                 }
2602         }
2603         
2604         if(G.scene->selectmode >= SCE_SELECT_EDGE) {
2605                 for(eed= em->edges.first; eed; eed= eed->next) {
2606                         if(eed->f1==1) eed->h |= 1;
2607                         if(eed->h & 1) a= 1; else a= 2;
2608                         eed->v1->f1 |= a;
2609                         eed->v2->f1 |= a;
2610                 }
2611         }
2612
2613         if(G.scene->selectmode >= SCE_SELECT_VERTEX) {
2614                 for(eve= em->verts.first; eve; eve= eve->next) {
2615                         if(eve->f1==1) eve->h= 1;
2616                 }
2617         }
2618         
2619         G.totedgesel= G.totfacesel= G.totvertsel= 0;
2620         allqueue(REDRAWVIEW3D, 0);
2621         if(EM_texFaceCheck())
2622                 allqueue(REDRAWIMAGE, 0);
2623         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);     
2624         BIF_undo_push("Hide");
2625 }
2626
2627
2628 void reveal_mesh(void)
2629 {
2630         EditMesh *em = G.editMesh;
2631         EditVert *eve;
2632         EditEdge *eed;
2633         EditFace *efa;
2634         
2635         if(G.obedit==0) return;
2636
2637         for(eve= em->verts.first; eve; eve= eve->next) {
2638                 if(eve->h) {
2639                         eve->h= 0;
2640                         eve->f |= SELECT;
2641                 }
2642         }
2643         for(eed= em->edges.first; eed; eed= eed->next) {
2644                 if(eed->h & 1) {
2645                         eed->h &= ~1;
2646                         if(G.scene->selectmode & SCE_SELECT_VERTEX); 
2647                         else EM_select_edge(eed, 1);
2648                 }
2649         }
2650         for(efa= em->faces.first; efa; efa= efa->next) {
2651                 if(efa->h) {
2652                         efa->h= 0;
2653                         if(G.scene->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_VERTEX)); 
2654                         else EM_select_face(efa, 1);
2655                 }
2656         }
2657
2658         EM_fgon_flags();        /* redo flags and indices for fgons */
2659         EM_selectmode_flush();
2660         countall();
2661
2662         allqueue(REDRAWVIEW3D, 0);
2663         if (EM_texFaceCheck())
2664                 allqueue(REDRAWIMAGE, 0);
2665         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);     
2666         BIF_undo_push("Reveal");
2667 }
2668
2669 void hide_tface_uv(int swap)
2670 {
2671         EditMesh *em = G.editMesh;
2672         EditFace *efa;
2673         MTFace *tface;
2674         
2675         if( is_uv_tface_editing_allowed()==0 ) return;
2676
2677         /* call the mesh function if we are in mesh sync sel */
2678         if (G.sima->flag & SI_SYNC_UVSEL) {
2679                 hide_mesh(swap);
2680                 return;
2681         }
2682         
2683         if(swap) {
2684                 for (efa= em->faces.first; efa; efa= efa->next) {
2685                         if(efa->f & SELECT) {
2686                                 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2687                                 if (G.sima->flag & SI_SELACTFACE) {
2688                                         /* Pretend face mode */
2689                                         if ((   (efa->v4==NULL && 
2690                                                         (       tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) ==                     (TF_SEL1|TF_SEL2|TF_SEL3) )                      ||
2691                                                         (       tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) ==     (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)       ) == 0) {
2692                                                 
2693                                                 if (G.scene->selectmode == SCE_SELECT_FACE) {
2694                                                         efa->f &= ~SELECT;
2695                                                         /* must re-select after */
2696                                                         efa->e1->f &= ~SELECT;
2697                                                         efa->e2->f &= ~SELECT;
2698                                                         efa->e3->f &= ~SELECT;
2699                                                         if(efa->e4) efa->e4->f &= ~SELECT;
2700                                                 } else {
2701                                                         EM_select_face(efa, 0);
2702                                                 }
2703                                         }
2704                                         tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2705                                 } else if (G.scene->selectmode == SCE_SELECT_FACE) {
2706                                         if((tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3))==0) {
2707                                                 if(!efa->v4)
2708                                                         EM_select_face(efa, 0);
2709                                                 else if(!(tface->flag & TF_SEL4))
2710                                                         EM_select_face(efa, 0);
2711                                                 tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2712                                         }
2713                                 } else {
2714                                         /* EM_deselect_flush will deselect the face */
2715                                         if((tface->flag & TF_SEL1)==0)                          efa->v1->f &= ~SELECT;
2716                                         if((tface->flag & TF_SEL2)==0)                          efa->v2->f &= ~SELECT;
2717                                         if((tface->flag & TF_SEL3)==0)                          efa->v3->f &= ~SELECT;
2718                                         if((efa->v4) && (tface->flag & TF_SEL4)==0)     efa->v4->f &= ~SELECT;                  
2719                                         tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2720                                 }
2721                         }
2722                 }
2723         } else {
2724                 for (efa= em->faces.first; efa; efa= efa->next) {
2725                         if(efa->f & SELECT) {
2726                                 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2727                                 if (G.sima->flag & SI_SELACTFACE) {
2728                                         if (    (efa->v4==NULL && 
2729                                                         (       tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) ==                     (TF_SEL1|TF_SEL2|TF_SEL3) )                      ||
2730                                                         (       tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) ==     (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)       ) {
2731                                                 
2732                                                 if (G.scene->selectmode == SCE_SELECT_FACE) {
2733                                                         efa->f &= ~SELECT;
2734                                                         /* must re-select after */
2735                                                         efa->e1->f &= ~SELECT;
2736                                                         efa->e2->f &= ~SELECT;
2737                                                         efa->e3->f &= ~SELECT;
2738                                                         if(efa->e4) efa->e4->f &= ~SELECT;
2739                                                 } else {
2740                                                         EM_select_face(efa, 0);
2741                                                 }
2742                                         }
2743                                         tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2744                                 } else if (G.scene->selectmode == SCE_SELECT_FACE) {
2745                                         if(tface->flag & (TF_SEL1|TF_SEL2|TF_SEL3))
2746                                                 EM_select_face(efa, 0);
2747                                         else if(efa->v4 && tface->flag & TF_SEL4)
2748                                                 EM_select_face(efa, 0);
2749                                         tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2750                                 } else {
2751                                         /* EM_deselect_flush will deselect the face */
2752                                         if(tface->flag & TF_SEL1)                               efa->v1->f &= ~SELECT;
2753                                         if(tface->flag & TF_SEL2)                               efa->v2->f &= ~SELECT;
2754                                         if(tface->flag & TF_SEL3)                               efa->v3->f &= ~SELECT;
2755                                         if((efa->v4) && tface->flag & TF_SEL4)  efa->v4->f &= ~SELECT;
2756                                         tface->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
2757                                 }
2758                         }
2759                 }
2760         }
2761         
2762         
2763         /*deselects too many but ok for now*/
2764         if(G.scene->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_VERTEX)) {
2765                 EM_deselect_flush();
2766         }
2767         
2768         if (G.scene->selectmode==SCE_SELECT_FACE) {
2769                 /* de-selected all edges from faces that were de-selected.
2770                  * now make sure all faces that are selected also have selected edges */
2771                 for (efa= em->faces.first; efa; efa= efa->next) {
2772                         if (efa->f & SELECT) {
2773                                 EM_select_face(efa, 1);
2774                         }
2775                 }
2776         }
2777         
2778         EM_validate_selections();
2779         
2780         BIF_undo_push("Hide UV");
2781
2782         object_tface_flags_changed(OBACT, 0);
2783 }
2784
2785 void reveal_tface_uv(void)
2786 {
2787         EditMesh *em = G.editMesh;
2788         EditFace *efa;
2789         MTFace *tface;
2790
2791         if( is_uv_tface_editing_allowed()==0 ) return;
2792         
2793         /* call the mesh function if we are in mesh sync sel */
2794         if (G.sima->flag & SI_SYNC_UVSEL) {
2795                 reveal_mesh();
2796                 return;
2797         }
2798         
2799         if (G.sima->flag & SI_SELACTFACE) {
2800                 if (G.scene->selectmode == SCE_SELECT_FACE) {
2801                         for (efa= em->faces.first; efa; efa= efa->next) {
2802                                 if (!(efa->h) && !(efa->f & SELECT)) {
2803                                         tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2804                                         EM_select_face(efa, 1);
2805                                         tface->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4;
2806                                 }
2807                         }
2808                 } else {
2809                         /* enable adjacent faces to have disconnected UV selections if sticky is disabled */
2810                         if (G.sima->sticky == SI_STICKY_DISABLE) {
2811                                 for (efa= em->faces.first; efa; efa= efa->next) {
2812                                         if (!(efa->h) && !(efa->f & SELECT)) {
2813                                                 /* All verts must be unselected for the face to be selected in the UV view */
2814                                                 if ((efa->v1->f&SELECT)==0 && (efa->v2->f&SELECT)==0 && (efa->v3->f&SELECT)==0 && (efa->v4==0 || (efa->v4->f&SELECT)==0)) {
2815                                                         tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2816                                                         tface->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4;
2817                                                         /* Cant use EM_select_face here because it unselects the verts
2818                                                          * and we cant tell if the face was totally unselected or not */
2819                                                         /*EM_select_face(efa, 1);
2820                                                          * 
2821                                                          * See Loop with EM_select_face() below... */
2822                                                         efa->f |= SELECT;
2823                                                 }
2824                                         }
2825                                 }
2826                         } else {
2827                                 for (efa= em->faces.first; efa; efa= efa->next) {
2828                                         if (!(efa->h) && !(efa->f & SELECT)) {
2829                                                 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2830                                                 if ((efa->v1->f & SELECT)==0)                           {tface->flag |= TF_SEL1;}
2831                                                 if ((efa->v2->f & SELECT)==0)                           {tface->flag |= TF_SEL2;}
2832                                                 if ((efa->v3->f & SELECT)==0)                           {tface->flag |= TF_SEL3;}
2833                                                 if ((efa->v4 && (efa->v4->f & SELECT)==0))      {tface->flag |= TF_SEL4;}
2834                                                 efa->f |= SELECT;
2835                                         }
2836                                 }
2837                         }
2838                         
2839                         /* Select all edges and verts now */
2840                         for (efa= em->faces.first; efa; efa= efa->next) {
2841                                 /* we only selected the face flags, and didnt changes edges or verts, fix this now */
2842                                 if (!(efa->h) && (efa->f & SELECT)) {
2843                                         EM_select_face(efa, 1);
2844                                 }
2845                         }
2846                         EM_select_flush();
2847                 }
2848         } else if (G.scene->selectmode == SCE_SELECT_FACE) {
2849                 for (efa= em->faces.first; efa; efa= efa->next) {
2850                         if (!(efa->h) && !(efa->f & SELECT)) {
2851                                 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2852                                 efa->f |= SELECT;
2853                                 tface->flag |= TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4;
2854                         }
2855                 }
2856                 
2857                 /* Select all edges and verts now */
2858                 for (efa= em->faces.first; efa; efa= efa->next) {
2859                         /* we only selected the face flags, and didnt changes edges or verts, fix this now */
2860                         if (!(efa->h) && (efa->f & SELECT)) {
2861                                 EM_select_face(efa, 1);
2862                         }
2863                 }
2864                 
2865         } else {
2866                 for (efa= em->faces.first; efa; efa= efa->next) {
2867                         if (!(efa->h) && !(efa->f & SELECT)) {
2868                                 tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2869                                 if ((efa->v1->f & SELECT)==0)                           {tface->flag |= TF_SEL1;}
2870                                 if ((efa->v2->f & SELECT)==0)                           {tface->flag |= TF_SEL2;}
2871                                 if ((efa->v3->f & SELECT)==0)                           {tface->flag |= TF_SEL3;}
2872                                 if ((efa->v4 && (efa->v4->f & SELECT)==0))      {tface->flag |= TF_SEL4;}
2873                                 efa->f |= SELECT;
2874                         }
2875                 }
2876                 
2877                 /* Select all edges and verts now */
2878                 for (efa= em->faces.first; efa; efa= efa->next) {
2879                         /* we only selected the face flags, and didnt changes edges or verts, fix this now */
2880                         if (!(efa->h) && (efa->f & SELECT)) {
2881                                 EM_select_face(efa, 1);
2882                         }
2883                 }
2884         }
2885         
2886         BIF_undo_push("Reveal UV");
2887         
2888         object_tface_flags_changed(OBACT, 0);
2889 }
2890
2891 void select_faces_by_numverts(int numverts)
2892 {
2893         EditMesh *em = G.editMesh;
2894         EditFace *efa;
2895
2896         /* Selects trias/qiads or isolated verts, and edges that do not have 2 neighboring
2897          * faces
2898          */
2899
2900         /* for loose vertices/edges, we first select all, loop below will deselect */
2901         if(numverts==5)
2902                 EM_set_flag_all(SELECT);
2903         else if(G.scene->selectmode!=SCE_SELECT_FACE) {
2904                 error("Only works in face selection mode");
2905                 return;
2906         }
2907         
2908         for(efa= em->faces.first; efa; efa= efa->next) {
2909                 if (efa->e4) {
2910                         EM_select_face(efa, (numverts==4) );
2911                 }
2912                 else {
2913                         EM_select_face(efa, (numverts==3) );
2914                 }
2915         }
2916
2917         countall();
2918         addqueue(curarea->win,  REDRAW, 0);
2919         if (EM_texFaceCheck())
2920                 allqueue(REDRAWIMAGE, 0);
2921         
2922         if (numverts==3)
2923                 BIF_undo_push("Select Triangles");
2924         else if (numverts==4)
2925                 BIF_undo_push("Select Quads");
2926         else
2927                 BIF_undo_push("Select non-Triangles/Quads");
2928 }
2929
2930 void select_sharp_edges(void)
2931 {
2932         /* Find edges that have exactly two neighboring faces,
2933          * check the angle between those faces, and if angle is
2934          * small enough, select the edge
2935          */
2936         EditMesh *em = G.editMesh;
2937         EditEdge *eed;
2938         EditFace *efa;
2939         EditFace **efa1;
2940         EditFace **efa2;
2941         intptr_t edgecount = 0, i;
2942         static short sharpness = 135;
2943         float fsharpness;
2944
2945         if(G.scene->selectmode==SCE_SELECT_FACE) {
2946                 error("Doesn't work in face selection mode");
2947                 return;
2948         }
2949
2950         if(button(&sharpness,0, 180,"Max Angle:")==0) return;
2951         /* if faces are at angle 'sharpness', then the face normals
2952          * are at angle 180.0 - 'sharpness' (convert to radians too)
2953          */
2954         fsharpness = ((180.0 - sharpness) * M_PI) / 180.0;
2955
2956         i=0;