==Mesh modeling==
[blender.git] / source / blender / src / editmesh_lib.c
1 /**
2  * $Id: 
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2004 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 /*
34
35 editmesh_lib: generic (no UI, no menus) operations/evaluators for editmesh data
36
37 */
38
39 #include <stdlib.h>
40 #include <string.h>
41 #include <math.h>
42
43 #ifdef HAVE_CONFIG_H
44 #include <config.h>
45 #endif
46
47 #include "MEM_guardedalloc.h"
48
49
50 #include "DNA_mesh_types.h"
51 #include "DNA_meshdata_types.h"
52 #include "DNA_modifier_types.h"
53 #include "DNA_object_types.h"
54 #include "DNA_scene_types.h"
55
56 #include "BLI_blenlib.h"
57 #include "BLI_arithb.h"
58 #include "BLI_editVert.h"
59
60 #include "BKE_global.h"
61 #include "BKE_mesh.h"
62 #include "BKE_utildefines.h"
63
64 #include "BIF_editmesh.h"
65
66 #include "BSE_edit.h"
67
68 #include "editmesh.h"
69
70 /* ********* Selection ************ */
71 static int EM_check_selection(void *data)
72 {
73         EditSelection *ese;
74         
75         for(ese = G.editMesh->selected.first; ese; ese = ese->next){
76                 if(ese->data == data) return 1;
77                 }
78         
79         return 0;
80 }
81
82 void EM_remove_selection(void *data, int type)
83 {
84         EditSelection *ese;
85         for(ese=G.editMesh->selected.first; ese; ese = ese->next){
86                 if(ese->data == data){
87                         BLI_freelinkN(&(G.editMesh->selected),ese);
88                         break;
89                 }
90         }
91 }
92
93 void EM_store_selection(void *data, int type)
94 {
95         EditSelection *ese;
96         if(!EM_check_selection(data)){
97                 ese = (EditSelection*) MEM_callocN( sizeof(EditSelection), "Edit Selection");
98                 ese->type = type;
99                 ese->data = data;
100                 BLI_addtail(&(G.editMesh->selected),ese);
101         }
102 }
103
104 static void EM_strip_selections(void)
105 {
106         EditSelection *ese, *nextese;
107         if(!(G.scene->selectmode & SCE_SELECT_VERTEX)){
108                 ese = G.editMesh->selected.first;
109                 while(ese){
110                         nextese = ese->next; 
111                         if(ese->type == EDITVERT) BLI_freelinkN(&(G.editMesh->selected),ese);
112                         ese = nextese;
113                 }
114         }
115         if(!(G.scene->selectmode & SCE_SELECT_EDGE)){
116                 ese=G.editMesh->selected.first;
117                 while(ese){
118                         nextese = ese->next;
119                         if(ese->type == EDITEDGE) BLI_freelinkN(&(G.editMesh->selected), ese);
120                         ese = nextese;
121                 }
122         }
123         if(!(G.scene->selectmode & SCE_SELECT_FACE)){
124                 ese=G.editMesh->selected.first;
125                 while(ese){
126                         nextese = ese->next;
127                         if(ese->type == EDITFACE) BLI_freelinkN(&(G.editMesh->selected), ese);
128                         ese = nextese;
129                 }
130         }
131 }
132
133 /* generic way to get data from an EditSelection type 
134 These functions were written to be used by the Modifier widget when in Rotate about active mode,
135 but can be used anywhere.
136 EM_editselection_center
137 EM_editselection_normal
138 EM_editselection_plane
139 */
140 void EM_editselection_center(float *center, EditSelection *ese)
141 {
142         if (ese->type==EDITVERT) {
143                 EditVert *eve= ese->data;
144                 VecCopyf(center, eve->co);
145         } else if (ese->type==EDITEDGE) {
146                 EditEdge *eed= ese->data;
147                 VecAddf(center, eed->v1->co, eed->v2->co);
148                 VecMulf(center, 0.5);
149         } else if (ese->type==EDITFACE) {
150                 EditFace *efa= ese->data;
151                 VecCopyf(center, efa->cent);
152         }
153 }
154
155 void EM_editselection_normal(float *normal, EditSelection *ese)
156 {
157         if (ese->type==EDITVERT) {
158                 EditVert *eve= ese->data;
159                 VecCopyf(normal, eve->no);
160         } else if (ese->type==EDITEDGE) {
161                 EditEdge *eed= ese->data;
162                 float plane[3]; /* need a plane to correct the normal */
163                 float vec[3]; /* temp vec storage */
164                 
165                 VecAddf(normal, eed->v1->no, eed->v2->no);
166                 VecSubf(plane, eed->v2->co, eed->v1->co);
167                 
168                 /* the 2 vertex normals will be close but not at rightangles to the edge
169                 for rotate about edge we want them to be at right angles, so we need to
170                 do some extra colculation to correct the vert normals,
171                 we need the plane for this */
172                 Crossf(vec, normal, plane);
173                 Crossf(normal, plane, vec); 
174                 Normalise(normal);
175                 
176         } else if (ese->type==EDITFACE) {
177                 EditFace *efa= ese->data;
178                 VecCopyf(normal, efa->n);
179         }
180 }
181
182 /* Calculate a plane that is rightangles to the edge/vert/faces normal
183 also make the plane run allong an axis that is related to the geometry,
184 because this is used for the manipulators Y axis.*/
185 void EM_editselection_plane(float *plane, EditSelection *ese)
186 {
187         if (ese->type==EDITVERT) {
188                 EditVert *eve= ese->data;
189                 float vec[3]={0,0,0};
190                 
191                 if (ese->prev) { /*use previously selected data to make a usefull vertex plane */
192                         EM_editselection_center(vec, ese->prev);
193                         VecSubf(plane, eve->co, vec);
194                 } else {
195                         /* make a fake  plane thats at rightangles to the normal
196                         we cant make a crossvec from a vec thats the same as the vec
197                         unlikely but possible, so make sure if the normal is (0,0,1)
198                         that vec isnt the same or in the same direction even.*/
199                         if (eve->no[0]<0.5)                     vec[0]=1;
200                         else if (eve->no[1]<0.5)        vec[1]=1;
201                         else                                            vec[2]=1;
202                         Crossf(plane, eve->no, vec);
203                 }
204         } else if (ese->type==EDITEDGE) {
205                 EditEdge *eed= ese->data;
206
207                 /*the plane is simple, it runs allong the edge
208                 however selecting different edges can swap the direction of the y axis.
209                 this makes it less likely for the y axis of the manipulator
210                 (running along the edge).. to flip less often.
211                 at least its more pradictable */
212                 if (eed->v2->co[1] > eed->v1->co[1]) /*check which to do first */
213                         VecSubf(plane, eed->v2->co, eed->v1->co);
214                 else
215                         VecSubf(plane, eed->v1->co, eed->v2->co);
216                 
217         } else if (ese->type==EDITFACE) {
218                 EditFace *efa= ese->data;
219                 float vec[3];
220                 if (efa->v4) { /*if its a quad- set the plane along the 2 longest edges.*/
221                         float vecA[3], vecB[3];
222                         VecSubf(vecA, efa->v4->co, efa->v3->co);
223                         VecSubf(vecB, efa->v1->co, efa->v2->co);
224                         VecAddf(plane, vecA, vecB);
225                         
226                         VecSubf(vecA, efa->v1->co, efa->v4->co);
227                         VecSubf(vecB, efa->v2->co, efa->v3->co);
228                         VecAddf(vec, vecA, vecB);                                               
229                         /*use the biggest edge length*/
230                         if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
231                                 VecCopyf(plane, vec);
232                 } else {
233                         /*start with v1-2 */
234                         VecSubf(plane, efa->v1->co, efa->v2->co);
235                         
236                         /*test the edge between v2-3, use if longer */
237                         VecSubf(vec, efa->v2->co, efa->v3->co);
238                         if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
239                                 VecCopyf(plane, vec);
240                         
241                         /*test the edge between v1-3, use if longer */
242                         VecSubf(vec, efa->v3->co, efa->v1->co);
243                         if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
244                                 VecCopyf(plane, vec);
245                 }
246         }
247         Normalise(plane);
248 }
249
250
251
252 void EM_select_face(EditFace *efa, int sel)
253 {
254         if(sel) {
255                 efa->f |= SELECT;
256                 efa->e1->f |= SELECT;
257                 efa->e2->f |= SELECT;
258                 efa->e3->f |= SELECT;
259                 if(efa->e4) efa->e4->f |= SELECT;
260                 efa->v1->f |= SELECT;
261                 efa->v2->f |= SELECT;
262                 efa->v3->f |= SELECT;
263                 if(efa->v4) efa->v4->f |= SELECT;
264         }
265         else {
266                 efa->f &= ~SELECT;
267                 efa->e1->f &= ~SELECT;
268                 efa->e2->f &= ~SELECT;
269                 efa->e3->f &= ~SELECT;
270                 if(efa->e4) efa->e4->f &= ~SELECT;
271                 efa->v1->f &= ~SELECT;
272                 efa->v2->f &= ~SELECT;
273                 efa->v3->f &= ~SELECT;
274                 if(efa->v4) efa->v4->f &= ~SELECT;
275         }
276 }
277
278 void EM_select_edge(EditEdge *eed, int sel)
279 {
280         if(sel) {
281                 eed->f |= SELECT;
282                 eed->v1->f |= SELECT;
283                 eed->v2->f |= SELECT;
284         }
285         else {
286                 eed->f &= ~SELECT;
287                 eed->v1->f &= ~SELECT;
288                 eed->v2->f &= ~SELECT;
289         }
290 }
291
292 void EM_select_face_fgon(EditFace *efa, int val)
293 {
294         EditMesh *em = G.editMesh;
295         short index=0;
296         
297         if(efa->fgonf==0) EM_select_face(efa, val);
298         else {
299                 if(efa->e1->fgoni) index= efa->e1->fgoni;
300                 if(efa->e2->fgoni) index= efa->e2->fgoni;
301                 if(efa->e3->fgoni) index= efa->e3->fgoni;
302                 if(efa->v4 && efa->e4->fgoni) index= efa->e4->fgoni;
303                 
304                 if(index==0) printf("wrong fgon select\n");
305                 
306                 // select all ngon faces with index
307                 for(efa= em->faces.first; efa; efa= efa->next) {
308                         if(efa->fgonf) {
309                                 if(efa->e1->fgoni==index || efa->e2->fgoni==index || 
310                                    efa->e3->fgoni==index || (efa->e4 && efa->e4->fgoni==index) ) {
311                                         EM_select_face(efa, val);
312                                 }
313                         }
314                 }
315         }
316 }
317
318
319 /* only vertices */
320 int faceselectedOR(EditFace *efa, int flag)
321 {
322         if ((efa->v1->f | efa->v2->f | efa->v3->f | (efa->v4?efa->v4->f:0))&flag) {
323                 return 1;
324         } else {
325                 return 0;
326         }
327 }
328
329 // replace with (efa->f & SELECT)
330 int faceselectedAND(EditFace *efa, int flag)
331 {
332         if ((efa->v1->f & efa->v2->f & efa->v3->f & (efa->v4?efa->v4->f:flag))&flag) {
333                 return 1;
334         } else {
335                 return 0;
336         }
337 }
338
339 int EM_nfaces_selected(void)
340 {
341         EditMesh *em = G.editMesh;
342         EditFace *efa;
343         int count= 0;
344
345         for (efa= em->faces.first; efa; efa= efa->next)
346                 if (efa->f & SELECT)
347                         count++;
348
349         return count;
350 }
351
352 #if 0
353 static int EM_nedges(void)
354 {
355         EditMesh *em = G.editMesh;
356         EditEdge *eed;
357         int count= 0;
358
359         for (eed= em->edges.first; eed; eed= eed->next) count++;
360         return count;
361 }
362 #endif
363
364 int EM_nvertices_selected(void)
365 {
366         EditMesh *em = G.editMesh;
367         EditVert *eve;
368         int count= 0;
369
370         for (eve= em->verts.first; eve; eve= eve->next)
371                 if (eve->f & SELECT)
372                         count++;
373
374         return count;
375 }
376
377 void EM_clear_flag_all(int flag)
378 {
379         EditMesh *em = G.editMesh;
380         EditVert *eve;
381         EditEdge *eed;
382         EditFace *efa;
383         
384         for (eve= em->verts.first; eve; eve= eve->next) eve->f &= ~flag;
385         for (eed= em->edges.first; eed; eed= eed->next) eed->f &= ~flag;
386         for (efa= em->faces.first; efa; efa= efa->next) efa->f &= ~flag;
387         
388         if(flag & SELECT) BLI_freelistN(&(G.editMesh->selected));
389 }
390
391 void EM_set_flag_all(int flag)
392 {
393         EditMesh *em = G.editMesh;
394         EditVert *eve;
395         EditEdge *eed;
396         EditFace *efa;
397         
398         for (eve= em->verts.first; eve; eve= eve->next) if(eve->h==0) eve->f |= flag;
399         for (eed= em->edges.first; eed; eed= eed->next) if(eed->h==0) eed->f |= flag;
400         for (efa= em->faces.first; efa; efa= efa->next) if(efa->h==0) efa->f |= flag;
401         
402 }
403
404 /* flush for changes in vertices only */
405 void EM_deselect_flush(void)
406 {
407         EditMesh *em = G.editMesh;
408         EditEdge *eed;
409         EditFace *efa;
410         
411         for(eed= em->edges.first; eed; eed= eed->next) {
412                 if(eed->v1->f & eed->v2->f & SELECT);
413                 else eed->f &= ~SELECT;
414         }
415         for(efa= em->faces.first; efa; efa= efa->next) {
416                 if(efa->v4) {
417                         if(efa->v1->f & efa->v2->f & efa->v3->f & efa->v4->f & SELECT );
418                         else efa->f &= ~SELECT;
419                 }
420                 else {
421                         if(efa->v1->f & efa->v2->f & efa->v3->f & SELECT );
422                         else efa->f &= ~SELECT;
423                 }
424         }
425 }
426
427
428 /* flush selection to edges & faces */
429
430 /*  this only based on coherent selected vertices, for example when adding new
431     objects. call clear_flag_all() before you select vertices to be sure it ends OK!
432         
433 */
434
435 void EM_select_flush(void)
436 {
437         EditMesh *em = G.editMesh;
438         EditEdge *eed;
439         EditFace *efa;
440         
441         for(eed= em->edges.first; eed; eed= eed->next) {
442                 if(eed->v1->f & eed->v2->f & SELECT) eed->f |= SELECT;
443         }
444         for(efa= em->faces.first; efa; efa= efa->next) {
445                 if(efa->v4) {
446                         if(efa->v1->f & efa->v2->f & efa->v3->f & efa->v4->f & SELECT ) efa->f |= SELECT;
447                 }
448                 else {
449                         if(efa->v1->f & efa->v2->f & efa->v3->f & SELECT ) efa->f |= SELECT;
450                 }
451         }
452 }
453
454 /* when vertices or edges can be selected, also make fgon consistant */
455 static void check_fgons_selection()
456 {
457         EditMesh *em = G.editMesh;
458         EditFace *efa, *efan;
459         EditEdge *eed;
460         ListBase *lbar;
461         int sel, desel, index, totfgon= 0;
462         
463         /* count amount of fgons */
464         for(eed= em->edges.first; eed; eed= eed->next) 
465                 if(eed->fgoni>totfgon) totfgon= eed->fgoni;
466         
467         if(totfgon==0) return;
468         
469         lbar= MEM_callocN((totfgon+1)*sizeof(ListBase), "listbase array");
470         
471         /* put all fgons in lbar */
472         for(efa= em->faces.first; efa; efa= efan) {
473                 efan= efa->next;
474                 index= efa->e1->fgoni;
475                 if(index==0) index= efa->e2->fgoni;
476                 if(index==0) index= efa->e3->fgoni;
477                 if(index==0 && efa->e4) index= efa->e4->fgoni;
478                 if(index) {
479                         BLI_remlink(&em->faces, efa);
480                         BLI_addtail(&lbar[index], efa);
481                 }
482         }
483         
484         /* now check the fgons */
485         for(index=1; index<=totfgon; index++) {
486                 /* we count on vertices/faces/edges being set OK, so we only have to set ngon itself */
487                 sel= desel= 0;
488                 for(efa= lbar[index].first; efa; efa= efa->next) {
489                         if(efa->e1->fgoni==0) {
490                                 if(efa->e1->f & SELECT) sel++;
491                                 else desel++;
492                         }
493                         if(efa->e2->fgoni==0) {
494                                 if(efa->e2->f & SELECT) sel++;
495                                 else desel++;
496                         }
497                         if(efa->e3->fgoni==0) {
498                                 if(efa->e3->f & SELECT) sel++;
499                                 else desel++;
500                         }
501                         if(efa->e4 && efa->e4->fgoni==0) {
502                                 if(efa->e4->f & SELECT) sel++;
503                                 else desel++;
504                         }
505                         
506                         if(sel && desel) break;
507                 }
508
509                 if(sel && desel) sel= 0;
510                 else if(sel) sel= 1;
511                 else sel= 0;
512                 
513                 /* select/deselect and put back */
514                 for(efa= lbar[index].first; efa; efa= efa->next) {
515                         if(sel) efa->f |= SELECT;
516                         else efa->f &= ~SELECT;
517                 }
518                 addlisttolist(&em->faces, &lbar[index]);
519         }
520         
521         MEM_freeN(lbar);
522 }
523
524
525 /* flush to edges & faces */
526
527 /* based on select mode it selects edges/faces 
528    assumed is that verts/edges/faces were properly selected themselves
529    with the calls above
530 */
531
532 void EM_selectmode_flush(void)
533 {
534         EditMesh *em = G.editMesh;
535         EditEdge *eed;
536         EditFace *efa;
537         
538         // flush to edges & faces
539         if(G.scene->selectmode & SCE_SELECT_VERTEX) {
540                 for(eed= em->edges.first; eed; eed= eed->next) {
541                         if(eed->v1->f & eed->v2->f & SELECT) eed->f |= SELECT;
542                         else eed->f &= ~SELECT;
543                 }
544                 for(efa= em->faces.first; efa; efa= efa->next) {
545                         if(efa->v4) {
546                                 if(efa->v1->f & efa->v2->f & efa->v3->f & efa->v4->f & SELECT) efa->f |= SELECT;
547                                 else efa->f &= ~SELECT;
548                         }
549                         else {
550                                 if(efa->v1->f & efa->v2->f & efa->v3->f & SELECT) efa->f |= SELECT;
551                                 else efa->f &= ~SELECT;
552                         }
553                 }
554         }
555         // flush to faces
556         else if(G.scene->selectmode & SCE_SELECT_EDGE) {
557                 for(efa= em->faces.first; efa; efa= efa->next) {
558                         if(efa->e4) {
559                                 if(efa->e1->f & efa->e2->f & efa->e3->f & efa->e4->f & SELECT) efa->f |= SELECT;
560                                 else efa->f &= ~SELECT;
561                         }
562                         else {
563                                 if(efa->e1->f & efa->e2->f & efa->e3->f & SELECT) efa->f |= SELECT;
564                                 else efa->f &= ~SELECT;
565                         }
566                 }
567         }       
568         // make sure selected faces have selected edges too, for extrude (hack?)
569         else if(G.scene->selectmode & SCE_SELECT_FACE) {
570                 for(efa= em->faces.first; efa; efa= efa->next) {
571                         if(efa->f & SELECT) EM_select_face(efa, 1);
572                 }
573         }
574         check_fgons_selection();
575
576 }
577
578 void EM_convertsel(short oldmode, short selectmode)
579 {
580         EditMesh *em = G.editMesh;
581         EditVert *eve;
582         EditEdge *eed;
583         EditFace *efa;
584         /*clear flags*/
585         for(eve= em->verts.first; eve; eve= eve->next) eve->f1 = 0;
586         for(eed= em->edges.first; eed; eed= eed->next) eed->f1 = 0;
587         for(efa= em->faces.first; efa; efa= efa->next) efa->f1 = 0;
588         
589         /*have to find out what the selectionmode was previously*/
590         if(oldmode == SCE_SELECT_VERTEX) {
591                 if(selectmode == SCE_SELECT_EDGE){
592                         /*select all edges associated with every selected vertex*/
593                         for(eed= em->edges.first; eed; eed= eed->next){
594                                 if(eed->v1->f&SELECT) eed->f1 = 1;
595                                 else if(eed->v2->f&SELECT) eed->f1 = 1;
596                         }
597                         
598                         for(eed= em->edges.first; eed; eed= eed->next){
599                                 if(eed->f1 == 1) EM_select_edge(eed,1); 
600                         }
601                 }               
602                 else if(selectmode == SCE_SELECT_FACE){
603                         /*select all faces associated with every selected vertex*/
604                         for(efa= em->faces.first; efa; efa= efa->next){
605                                 if(efa->v1->f&SELECT) efa->f1 = 1;
606                                 else if(efa->v2->f&SELECT) efa->f1 = 1;
607                                 else if(efa->v3->f&SELECT) efa->f1 = 1;
608                                 else{ 
609                                         if(efa->v4){
610                                                 if(efa->v4->f&SELECT) efa->f1 =1;
611                                         }
612                                 }
613                         }
614                         for(efa= em->faces.first; efa; efa= efa->next){
615                                 if(efa->f1 == 1) EM_select_face(efa,1);
616                         }
617                 }
618         }
619         
620         if(oldmode == SCE_SELECT_EDGE){
621                 if(selectmode == SCE_SELECT_FACE){
622                         for(efa= em->faces.first; efa; efa= efa->next){
623                                 if(efa->e1->f&SELECT) efa->f1 = 1;
624                                 else if(efa->e2->f&SELECT) efa->f1 = 1;
625                                 else if(efa->e3->f&SELECT) efa->f1 = 1;
626                                 else if(efa->e4){
627                                         if(efa->e4->f&SELECT) efa->f1 = 1;
628                                 }
629                         }
630                         for(efa= em->faces.first; efa; efa= efa->next){
631                                 if(efa->f1 == 1) EM_select_face(efa,1);
632                         }
633                 }
634         }
635         
636         check_fgons_selection();
637 }
638
639 /* when switching select mode, makes sure selection is consistant for editing */
640 /* also for paranoia checks to make sure edge or face mode works */
641 void EM_selectmode_set(void)
642 {
643         EditMesh *em = G.editMesh;
644         EditVert *eve;
645         EditEdge *eed;
646         EditFace *efa;
647         
648         EM_strip_selections(); /*strip EditSelections from em->selected that are not relevant to new mode*/
649         if(G.scene->selectmode & SCE_SELECT_VERTEX) {
650                 /* vertices -> edges -> faces */
651                 for (eed= em->edges.first; eed; eed= eed->next) eed->f &= ~SELECT;
652                 for (efa= em->faces.first; efa; efa= efa->next) efa->f &= ~SELECT;
653                 
654                 EM_select_flush();
655         }
656         else if(G.scene->selectmode & SCE_SELECT_EDGE) {
657                 /* deselect vertices, and select again based on edge select */
658                 for(eve= em->verts.first; eve; eve= eve->next) eve->f &= ~SELECT;
659                 for(eed= em->edges.first; eed; eed= eed->next) 
660                         if(eed->f & SELECT) EM_select_edge(eed, 1);
661                 /* selects faces based on edge status */
662                 EM_selectmode_flush();
663         }
664         else if(G.scene->selectmode & SCE_SELECT_FACE) {
665                 /* deselect eges, and select again based on face select */
666                 for(eed= em->edges.first; eed; eed= eed->next) EM_select_edge(eed, 0);
667                 
668                 for(efa= em->faces.first; efa; efa= efa->next) 
669                         if(efa->f & SELECT) EM_select_face(efa, 1);
670         }
671 }
672
673 /* paranoia check, actually only for entering editmode. rule:
674 - vertex hidden, always means edge is hidden too
675 - edge hidden, always means face is hidden too
676 - face hidden, dont change anything
677 */
678 void EM_hide_reset(void)
679 {
680         EditMesh *em = G.editMesh;
681         EditEdge *eed;
682         EditFace *efa;
683         
684         for(eed= em->edges.first; eed; eed= eed->next) 
685                 if(eed->v1->h || eed->v2->h) eed->h |= 1;
686                 
687         for(efa= em->faces.first; efa; efa= efa->next) 
688                 if((efa->e1->h & 1) || (efa->e2->h & 1) || (efa->e3->h & 1) || (efa->e4 && (efa->e4->h & 1)))
689                         efa->h= 1;
690                 
691 }
692
693
694 /* ********  EXTRUDE ********* */
695
696 static void add_normal_aligned(float *nor, float *add)
697 {
698         if( INPR(nor, add) < 0.0 ) 
699                 VecSubf(nor, nor, add);
700         else
701                 VecAddf(nor, nor, add);
702 }
703
704 static void set_edge_directions_f2(int val)
705 {
706         EditMesh *em= G.editMesh;
707         EditFace *efa;
708         int do_all= 1;
709         
710         /* edge directions are used for extrude, to detect direction of edges that make new faces */
711         /* we have set 'f2' flags in edges that need to get a direction set (e.g. get new face) */
712         /* the val argument differs... so we need it as arg */
713         
714         for(efa= em->faces.first; efa; efa= efa->next) {
715                 if(efa->f & SELECT) {
716                         do_all= 0;
717                         if(efa->e1->f2<val) {
718                                 if(efa->e1->v1 == efa->v1) efa->e1->dir= 0;
719                                 else efa->e1->dir= 1;
720                         }
721                         if(efa->e2->f2<val) {
722                                 if(efa->e2->v1 == efa->v2) efa->e2->dir= 0;
723                                 else efa->e2->dir= 1;
724                         }
725                         if(efa->e3->f2<val) {
726                                 if(efa->e3->v1 == efa->v3) efa->e3->dir= 0;
727                                 else efa->e3->dir= 1;
728                         }
729                         if(efa->e4 && efa->e4->f2<val) {
730                                 if(efa->e4->v1 == efa->v4) efa->e4->dir= 0;
731                                 else efa->e4->dir= 1;
732                         }
733                 }
734         }       
735         /* ok, no faces done... then we at least set it for exterior edges */
736         if(do_all) {
737                 for(efa= em->faces.first; efa; efa= efa->next) {
738                         if(efa->e1->v1 == efa->v1) efa->e1->dir= 0;
739                         else efa->e1->dir= 1;
740                         if(efa->e2->v1 == efa->v2) efa->e2->dir= 0;
741                         else efa->e2->dir= 1;
742                         if(efa->e3->v1 == efa->v3) efa->e3->dir= 0;
743                         else efa->e3->dir= 1;
744                         if(efa->e4) {
745                                 if(efa->e4->v1 == efa->v4) efa->e4->dir= 0;
746                                 else efa->e4->dir= 1;
747                         }
748                 }       
749         }
750 }
751
752 /* individual face extrude */
753 /* will use vertex normals for extrusion directions, so *nor is unaffected */
754 short extrudeflag_face_indiv(short flag, float *nor)
755 {
756         EditMesh *em = G.editMesh;
757         EditVert *eve, *v1, *v2, *v3, *v4;
758         EditEdge *eed;
759         EditFace *efa, *nextfa;
760         
761         if(G.obedit==0 || get_mesh(G.obedit)==0) return 0;
762         
763         /* selected edges with 1 or more selected face become faces */
764         /* selected faces each makes new faces */
765         /* always remove old faces, keeps volumes manifold */
766         /* select the new extrusion, deselect old */
767         
768         /* step 1; init, count faces in edges */
769         recalc_editnormals();
770         
771         for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;      // new select flag
772
773         for(eed= em->edges.first; eed; eed= eed->next) {
774                 eed->f2= 0; // amount of unselected faces
775         }
776         for(efa= em->faces.first; efa; efa= efa->next) {
777                 if(efa->f & SELECT);
778                 else {
779                         efa->e1->f2++;
780                         efa->e2->f2++;
781                         efa->e3->f2++;
782                         if(efa->e4) efa->e4->f2++;
783                 }
784         }
785
786         /* step 2: make new faces from faces */
787         for(efa= em->faces.last; efa; efa= efa->prev) {
788                 if(efa->f & SELECT) {
789                         v1= addvertlist(efa->v1->co);
790                         v2= addvertlist(efa->v2->co);
791                         v3= addvertlist(efa->v3->co);
792                         v1->f1= v2->f1= v3->f1= 1;
793                         VECCOPY(v1->no, efa->n);
794                         VECCOPY(v2->no, efa->n);
795                         VECCOPY(v3->no, efa->n);
796                         if(efa->v4) {
797                                 v4= addvertlist(efa->v4->co); 
798                                 v4->f1= 1;
799                                 VECCOPY(v4->no, efa->n);
800                         }
801                         else v4= NULL;
802                         
803                         /* side faces, clockwise */
804                         addfacelist(efa->v2, v2, v1, efa->v1, efa, NULL);
805                         addfacelist(efa->v3, v3, v2, efa->v2, efa, NULL);
806                         if(efa->v4) {
807                                 addfacelist(efa->v4, v4, v3, efa->v3, efa, NULL);
808                                 addfacelist(efa->v1, v1, v4, efa->v4, efa, NULL);
809                         }
810                         else {
811                                 addfacelist(efa->v1, v1, v3, efa->v3, efa, NULL);
812                         }
813                         /* top face */
814                         addfacelist(v1, v2, v3, v4, efa, NULL);
815                 }
816         }
817         
818         /* step 3: remove old faces */
819         efa= em->faces.first;
820         while(efa) {
821                 nextfa= efa->next;
822                 if(efa->f & SELECT) {
823                         BLI_remlink(&em->faces, efa);
824                         free_editface(efa);
825                 }
826                 efa= nextfa;
827         }
828
829         /* step 4: redo selection */
830         EM_clear_flag_all(SELECT);
831         
832         for(eve= em->verts.first; eve; eve= eve->next) {
833                 if(eve->f1)  eve->f |= SELECT;
834         }
835         
836         EM_select_flush();
837         
838         return 'n';
839 }
840
841
842 /* extrudes individual edges */
843 /* nor is filled with constraint vector */
844 short extrudeflag_edges_indiv(short flag, float *nor) 
845 {
846         EditMesh *em = G.editMesh;
847         EditVert *eve;
848         EditEdge *eed;
849         EditFace *efa;
850         
851         for(eve= em->verts.first; eve; eve= eve->next) eve->tmp.v = NULL;
852         for(eed= em->edges.first; eed; eed= eed->next) {
853                 eed->tmp.f = NULL;
854                 eed->f2= ((eed->f & flag)!=0);
855         }
856         
857         set_edge_directions_f2(2);
858
859         /* sample for next loop */
860         for(efa= em->faces.first; efa; efa= efa->next) {
861                 efa->e1->tmp.f = efa;
862                 efa->e2->tmp.f = efa;
863                 efa->e3->tmp.f = efa;
864                 if(efa->e4) efa->e4->tmp.f = efa;
865         }
866         /* make the faces */
867         for(eed= em->edges.first; eed; eed= eed->next) {
868                 if(eed->f & flag) {
869                         if(eed->v1->tmp.v == NULL) 
870                                 eed->v1->tmp.v = addvertlist(eed->v1->co);
871                         if(eed->v2->tmp.v == NULL) 
872                                 eed->v2->tmp.v = addvertlist(eed->v2->co);
873                         
874                         if(eed->dir==1) 
875                                 addfacelist(eed->v1, eed->v2, 
876                                                         eed->v2->tmp.v, eed->v1->tmp.v, 
877                                                         eed->tmp.f, NULL);
878                         else 
879                                 addfacelist(eed->v2, eed->v1, 
880                                                         eed->v1->tmp.v, eed->v2->tmp.v, 
881                                                         eed->tmp.f, NULL);
882
883                         /* for transform */
884                         if(eed->tmp.f) {
885                                 efa = eed->tmp.f;
886                                 if (efa->f & SELECT) add_normal_aligned(nor, efa->n);
887                         }
888                 }
889         }
890         Normalise(nor);
891         
892         /* set correct selection */
893         EM_clear_flag_all(SELECT);
894         for(eve= em->verts.last; eve; eve= eve->prev) {
895                 if(eve->tmp.v) {
896                         eve->tmp.v->f |= flag;
897                 }
898         }
899
900         for(eed= em->edges.first; eed; eed= eed->next) {
901                 if(eed->v1->f & eed->v2->f & flag) eed->f |= flag;
902         }
903         
904         if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // g is grab
905         return 'n';  // n is for normal constraint
906 }
907
908 /* extrudes individual vertices */
909 short extrudeflag_verts_indiv(short flag, float *nor) 
910 {
911         EditMesh *em = G.editMesh;
912         EditVert *eve;
913         
914         /* make the edges */
915         for(eve= em->verts.first; eve; eve= eve->next) {
916                 if(eve->f & flag) {
917                         eve->tmp.v = addvertlist(eve->co);
918                         addedgelist(eve, eve->tmp.v, NULL);
919                 }
920                 else eve->tmp.v = NULL;
921         }
922         
923         /* set correct selection */
924         EM_clear_flag_all(SELECT);
925
926         for(eve= em->verts.last; eve; eve= eve->prev) 
927                 if (eve->tmp.v) 
928                         eve->tmp.v->f |= flag;
929
930         return 'g';     // g is grab
931 }
932
933
934 /* this is actually a recode of extrudeflag(), using proper edge/face select */
935 /* hurms, doesnt use 'flag' yet, but its not called by primitive making stuff anyway */
936 static short extrudeflag_edge(short flag, float *nor)
937 {
938         /* all select edges/faces: extrude */
939         /* old select is cleared, in new ones it is set */
940         EditMesh *em = G.editMesh;
941         EditVert *eve, *nextve;
942         EditEdge *eed, *nexted;
943         EditFace *efa, *nextfa;
944         short del_old= 0;
945         ModifierData *md= G.obedit->modifiers.first;
946         
947         if(G.obedit==0 || get_mesh(G.obedit)==0) return 0;
948         
949         /* selected edges with 0 or 1 selected face become faces */
950         /* selected faces generate new faces */
951
952         /* if *one* selected face has edge with unselected face; remove old selected faces */
953         
954         /* if selected edge is not used anymore; remove */
955         /* if selected vertex is not used anymore: remove */
956         
957         /* select the new extrusion, deselect old */
958         
959         
960         /* step 1; init, count faces in edges */
961         recalc_editnormals();
962         
963         for(eve= em->verts.first; eve; eve= eve->next) {
964                 eve->tmp.v = NULL;
965                 eve->f1= 0;
966         }
967
968         for(eed= em->edges.first; eed; eed= eed->next) {
969                 eed->f1= 0; // amount of unselected faces
970                 eed->f2= 0; // amount of selected faces
971                 if(eed->f & SELECT) {
972                         eed->v1->f1= 1; // we call this 'selected vertex' now
973                         eed->v2->f1= 1;
974                 }
975                 eed->tmp.f = NULL;              // here we tuck face pointer, as sample
976         }
977         for(efa= em->faces.first; efa; efa= efa->next) {
978                 if(efa->f & SELECT) {
979                         efa->e1->f2++;
980                         efa->e2->f2++;
981                         efa->e3->f2++;
982                         if(efa->e4) efa->e4->f2++;
983                         
984                         // sample for next loop
985                         efa->e1->tmp.f = efa;
986                         efa->e2->tmp.f = efa;
987                         efa->e3->tmp.f = efa;
988                         if(efa->e4) efa->e4->tmp.f = efa;
989                 }
990                 else {
991                         efa->e1->f1++;
992                         efa->e2->f1++;
993                         efa->e3->f1++;
994                         if(efa->e4) efa->e4->f1++;
995                 }
996         }
997         
998         /* If a mirror modifier with clipping is on, we need to adjust some 
999          * of the cases above to handle edges on the line of symmetry.
1000          */
1001         for (; md; md=md->next) {
1002                 if (md->type==eModifierType_Mirror) {
1003                         MirrorModifierData *mmd = (MirrorModifierData*) md;     
1004                 
1005                         if(mmd->flag & MOD_MIR_CLIPPING) {
1006                                 for (eed= em->edges.first; eed; eed= eed->next) {
1007                                         if(eed->f2 == 1) {
1008
1009                                                 switch(mmd->axis){
1010                                                         case 0:
1011                                                                 if ( (fabs(eed->v1->co[0]) < mmd->tolerance) &&
1012                                                                          (fabs(eed->v2->co[0]) < mmd->tolerance) )
1013                                                                         ++eed->f2;
1014                                                                 break;
1015                                                         case 1:
1016                                                                 if ( (fabs(eed->v1->co[1]) < mmd->tolerance) &&
1017                                                                          (fabs(eed->v2->co[1]) < mmd->tolerance) )
1018                                                                         ++eed->f2;
1019                                                                 break;
1020                                                         case 2:
1021                                                                 if ( (fabs(eed->v1->co[2]) < mmd->tolerance) &&
1022                                                                          (fabs(eed->v2->co[2]) < mmd->tolerance) )
1023                                                                         ++eed->f2;
1024                                                                 break;
1025                                                 }
1026                                         }
1027                                 }
1028                         }
1029                 }
1030         }
1031
1032         set_edge_directions_f2(2);
1033         
1034         /* step 1.5: if *one* selected face has edge with unselected face; remove old selected faces */
1035         for(efa= em->faces.last; efa; efa= efa->prev) {
1036                 if(efa->f & SELECT) {
1037                         if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1 || (efa->e4 && efa->e4->f1)) {
1038                                 del_old= 1;
1039                                 break;
1040                         }
1041                 }
1042         }
1043                                 
1044         /* step 2: make new faces from edges */
1045         for(eed= em->edges.last; eed; eed= eed->prev) {
1046                 if(eed->f & SELECT) {
1047                         if(eed->f2<2) {
1048                                 if(eed->v1->tmp.v == NULL)
1049                                         eed->v1->tmp.v = addvertlist(eed->v1->co);
1050                                 if(eed->v2->tmp.v == NULL)
1051                                         eed->v2->tmp.v = addvertlist(eed->v2->co);
1052                                 
1053                                 /* if del_old, the preferred normal direction is exact 
1054                                  * opposite as for keep old faces
1055                                  */
1056                                 if(eed->dir!=del_old) 
1057                                         addfacelist(eed->v1, eed->v2, 
1058                                                                 eed->v2->tmp.v, eed->v1->tmp.v, 
1059                                                                 eed->tmp.f, NULL);
1060                                 else 
1061                                         addfacelist(eed->v2, eed->v1, 
1062                                                                 eed->v1->tmp.v, eed->v2->tmp.v,
1063                                                                 eed->tmp.f, NULL);
1064                         }
1065                 }
1066         }
1067         
1068         /* step 3: make new faces from faces */
1069         for(efa= em->faces.last; efa; efa= efa->prev) {
1070                 if(efa->f & SELECT) {
1071                         if (efa->v1->tmp.v == NULL) 
1072                                 efa->v1->tmp.v = addvertlist(efa->v1->co);
1073                         if (efa->v2->tmp.v ==NULL)
1074                                 efa->v2->tmp.v = addvertlist(efa->v2->co);
1075                         if (efa->v3->tmp.v ==NULL) 
1076                                 efa->v3->tmp.v = addvertlist(efa->v3->co);
1077                         if (efa->v4 && (efa->v4->tmp.v == NULL)) 
1078                                 efa->v4->tmp.v = addvertlist(efa->v4->co);
1079                         
1080                         if(del_old==0) {        // keep old faces means flipping normal
1081                                 if(efa->v4)
1082                                         addfacelist(efa->v4->tmp.v, efa->v3->tmp.v, 
1083                                                                 efa->v2->tmp.v, efa->v1->tmp.v, efa, efa);
1084                                 else
1085                                         addfacelist(efa->v3->tmp.v, efa->v2->tmp.v, 
1086                                                                 efa->v1->tmp.v, NULL, efa, efa);
1087                         }
1088                         else {
1089                                 if(efa->v4)
1090                                         addfacelist(efa->v1->tmp.v, efa->v2->tmp.v, 
1091                                                                 efa->v3->tmp.v, efa->v4->tmp.v, efa, efa);
1092                                 else
1093                                         addfacelist(efa->v1->tmp.v, efa->v2->tmp.v, 
1094                                                                 efa->v3->tmp.v, NULL, efa, efa);
1095                         }
1096         
1097                         /* for transform */
1098                         add_normal_aligned(nor, efa->n);
1099                 }
1100         }
1101         
1102         if(del_old) {
1103                 /* step 4: remove old faces, if del_old */
1104                 efa= em->faces.first;
1105                 while(efa) {
1106                         nextfa= efa->next;
1107                         if(efa->f & SELECT) {
1108                                 BLI_remlink(&em->faces, efa);
1109                                 free_editface(efa);
1110                         }
1111                         efa= nextfa;
1112                 }
1113         
1114                 /* step 5: remove selected unused edges */
1115                 /* start tagging again */
1116                 for(eed= em->edges.first; eed; eed= eed->next) eed->f1=0;
1117                 for(efa= em->faces.first; efa; efa= efa->next) {
1118                         efa->e1->f1= 1;
1119                         efa->e2->f1= 1;
1120                         efa->e3->f1= 1;
1121                         if(efa->e4) efa->e4->f1= 1;
1122                 }
1123                 /* remove */
1124                 eed= em->edges.first; 
1125                 while(eed) {
1126                         nexted= eed->next;
1127                         if(eed->f & SELECT) {
1128                                 if(eed->f1==0) {
1129                                         remedge(eed);
1130                                         free_editedge(eed);
1131                                 }
1132                         }
1133                         eed= nexted;
1134                 }
1135         
1136                 /* step 6: remove selected unused vertices */
1137                 for(eed= em->edges.first; eed; eed= eed->next) 
1138                         eed->v1->f1= eed->v2->f1= 0;
1139                 
1140                 eve= em->verts.first;
1141                 while(eve) {
1142                         nextve= eve->next;
1143                         if(eve->f1) {
1144                                 // hack... but we need it for step 7, redoing selection
1145                                 if(eve->tmp.v) eve->tmp.v->tmp.v= eve->tmp.v;
1146                                 
1147                                 BLI_remlink(&em->verts, eve);
1148                                 free_editvert(eve);
1149                         }
1150                         eve= nextve;
1151                 }
1152         }
1153         
1154         Normalise(nor); // translation normal grab
1155         
1156         /* step 7: redo selection */
1157         EM_clear_flag_all(SELECT);
1158
1159         for(eve= em->verts.first; eve; eve= eve->next) {
1160                 if(eve->tmp.v) {
1161                         eve->tmp.v->f |= SELECT;
1162                 }
1163         }
1164
1165         EM_select_flush();
1166
1167         if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // grab
1168         return 'n'; // normal constraint 
1169 }
1170
1171 short extrudeflag_vert(short flag, float *nor)
1172 {
1173         /* all verts/edges/faces with (f & 'flag'): extrude */
1174         /* from old verts, 'flag' is cleared, in new ones it is set */
1175         EditMesh *em = G.editMesh;
1176         EditVert *eve, *v1, *v2, *v3, *v4, *nextve;
1177         EditEdge *eed, *e1, *e2, *e3, *e4, *nexted;
1178         EditFace *efa, *efa2, *nextvl;
1179         short sel=0, del_old= 0, is_face_sel=0;
1180         ModifierData *md= G.obedit->modifiers.first;
1181
1182         if(G.obedit==0 || get_mesh(G.obedit)==0) return 0;
1183
1184         /* clear vert flag f1, we use this to detect a loose selected vertice */
1185         eve= em->verts.first;
1186         while(eve) {
1187                 if(eve->f & flag) eve->f1= 1;
1188                 else eve->f1= 0;
1189                 eve= eve->next;
1190         }
1191         /* clear edges counter flag, if selected we set it at 1 */
1192         eed= em->edges.first;
1193         while(eed) {
1194                 if( (eed->v1->f & flag) && (eed->v2->f & flag) ) {
1195                         eed->f2= 1;
1196                         eed->v1->f1= 0;
1197                         eed->v2->f1= 0;
1198                 }
1199                 else eed->f2= 0;
1200                 
1201                 eed->f1= 1;             /* this indicates it is an 'old' edge (in this routine we make new ones) */
1202                 eed->tmp.f = NULL;      /* used as sample */
1203                 
1204                 eed= eed->next;
1205         }
1206
1207         /* we set a flag in all selected faces, and increase the associated edge counters */
1208
1209         efa= em->faces.first;
1210         while(efa) {
1211                 efa->f1= 0;
1212
1213                 if(faceselectedAND(efa, flag)) {
1214                         e1= efa->e1;
1215                         e2= efa->e2;
1216                         e3= efa->e3;
1217                         e4= efa->e4;
1218
1219                         if(e1->f2 < 3) e1->f2++;
1220                         if(e2->f2 < 3) e2->f2++;
1221                         if(e3->f2 < 3) e3->f2++;
1222                         if(e4 && e4->f2 < 3) e4->f2++;
1223                         
1224                         efa->f1= 1;
1225                         is_face_sel= 1; // for del_old
1226                 }
1227                 else if(faceselectedOR(efa, flag)) {
1228                         e1= efa->e1;
1229                         e2= efa->e2;
1230                         e3= efa->e3;
1231                         e4= efa->e4;
1232                         
1233                         if( (e1->v1->f & flag) && (e1->v2->f & flag) ) e1->f1= 2;
1234                         if( (e2->v1->f & flag) && (e2->v2->f & flag) ) e2->f1= 2;
1235                         if( (e3->v1->f & flag) && (e3->v2->f & flag) ) e3->f1= 2;
1236                         if( e4 && (e4->v1->f & flag) && (e4->v2->f & flag) ) e4->f1= 2;
1237                 }
1238                 
1239                 // sample for next loop
1240                 efa->e1->tmp.f = efa;
1241                 efa->e2->tmp.f = efa;
1242                 efa->e3->tmp.f = efa;
1243                 if(efa->e4) efa->e4->tmp.f = efa;
1244
1245                 efa= efa->next;
1246         }
1247
1248         set_edge_directions_f2(3);
1249
1250         /* the current state now is:
1251                 eve->f1==1: loose selected vertex 
1252
1253                 eed->f2==0 : edge is not selected, no extrude
1254                 eed->f2==1 : edge selected, is not part of a face, extrude
1255                 eed->f2==2 : edge selected, is part of 1 face, extrude
1256                 eed->f2==3 : edge selected, is part of more faces, no extrude
1257                 
1258                 eed->f1==0: new edge
1259                 eed->f1==1: edge selected, is part of selected face, when eed->f==3: remove
1260                 eed->f1==2: edge selected, part of a partially selected face
1261                                         
1262                 efa->f1==1 : duplicate this face
1263         */
1264
1265         /* If a mirror modifier with clipping is on, we need to adjust some 
1266          * of the cases above to handle edges on the line of symmetry.
1267          */
1268         for (; md; md=md->next) {
1269                 if (md->type==eModifierType_Mirror) {
1270                         MirrorModifierData *mmd = (MirrorModifierData*) md;     
1271                 
1272                         if(mmd->flag & MOD_MIR_CLIPPING) {
1273                                 for (eed= em->edges.first; eed; eed= eed->next) {
1274                                         if(eed->f2 == 2) {
1275
1276                                                 switch(mmd->axis){
1277                                                         case 0:
1278                                                                 if ( (fabs(eed->v1->co[0]) < mmd->tolerance) &&
1279                                                                          (fabs(eed->v2->co[0]) < mmd->tolerance) )
1280                                                                         ++eed->f2;
1281                                                                 break;
1282                                                         case 1:
1283                                                                 if ( (fabs(eed->v1->co[1]) < mmd->tolerance) &&
1284                                                                          (fabs(eed->v2->co[1]) < mmd->tolerance) )
1285                                                                         ++eed->f2;
1286                                                                 break;
1287                                                         case 2:
1288                                                                 if ( (fabs(eed->v1->co[2]) < mmd->tolerance) &&
1289                                                                          (fabs(eed->v2->co[2]) < mmd->tolerance) )
1290                                                                         ++eed->f2;
1291                                                                 break;
1292                                                 }
1293                                         }
1294                                 }
1295                         }
1296                 }
1297         }
1298
1299         /* copy all selected vertices, */
1300         /* write pointer to new vert in old struct at eve->tmp.v */
1301         eve= em->verts.last;
1302         while(eve) {
1303                 eve->f &= ~128;  /* clear, for later test for loose verts */
1304                 if(eve->f & flag) {
1305                         sel= 1;
1306                         v1= addvertlist(0);
1307                         
1308                         VECCOPY(v1->co, eve->co);
1309                         v1->f= eve->f;
1310                         eve->f-= flag;
1311                         eve->tmp.v = v1;
1312                 }
1313                 else eve->tmp.v = 0;
1314                 eve= eve->prev;
1315         }
1316
1317         if(sel==0) return 0;
1318
1319         /* all edges with eed->f2==1 or eed->f2==2 become faces */
1320         
1321         /* if del_old==1 then extrude is in partial geometry, to keep it manifold.
1322                                          verts with f1==0 and (eve->f & 128)==0) are removed
1323                          edges with eed->f2>2 are removed
1324                                          faces with efa->f1 are removed
1325            if del_old==0 the extrude creates a volume.
1326         */
1327         
1328          /* find if we delete old faces */
1329         if(is_face_sel) {
1330                 for(eed= em->edges.first; eed; eed= eed->next) {
1331                         if( (eed->f2==1 || eed->f2==2) ) {
1332                                 if(eed->f1==2) {
1333                                         del_old= 1;
1334                                         break;
1335                                 }
1336                         }
1337                 }
1338         }
1339         
1340         eed= em->edges.last;
1341         while(eed) {
1342                 nexted= eed->prev;
1343                 if( eed->f2<3) {
1344                         eed->v1->f |= 128;  /* = no loose vert! */
1345                         eed->v2->f |= 128;
1346                 }
1347                 if( (eed->f2==1 || eed->f2==2) ) {
1348         
1349                         /* if del_old, the preferred normal direction is exact opposite as for keep old faces */
1350                         if(eed->dir != del_old) 
1351                                 efa2 = addfacelist(eed->v1, eed->v2, 
1352                                                                   eed->v2->tmp.v, eed->v1->tmp.v, 
1353                                                                   NULL, NULL);
1354                         else 
1355                                 efa2 = addfacelist(eed->v2, eed->v1, 
1356                                                                    eed->v1->tmp.v, eed->v2->tmp.v, 
1357                                                                    NULL, NULL);
1358                         
1359                         if(eed->tmp.f) {
1360                                 efa = eed->tmp.f;
1361                                 efa2->mat_nr= efa->mat_nr;
1362                                 efa2->tf= efa->tf;
1363                                 efa2->flag= efa->flag;
1364                         }
1365                         
1366                         /* Needs smarter adaption of existing creases.
1367                          * If addedgelist is used, make sure seams are set to 0 on these
1368                          * new edges, since we do not want to add any seams on extrusion.
1369                          */
1370                         efa2->e1->crease= eed->crease;
1371                         efa2->e2->crease= eed->crease;
1372                         efa2->e3->crease= eed->crease;
1373                         if(efa2->e4) efa2->e4->crease= eed->crease;
1374                 }
1375
1376                 eed= nexted;
1377         }
1378         if(del_old) {
1379                 eed= em->edges.first;
1380                 while(eed) {
1381                         nexted= eed->next;
1382                         if(eed->f2==3 && eed->f1==1) {
1383                                 remedge(eed);
1384                                 free_editedge(eed);
1385                         }
1386                         eed= nexted;
1387                 }
1388         }
1389         /* duplicate faces, if necessary remove old ones  */
1390         efa= em->faces.first;
1391         while(efa) {
1392                 nextvl= efa->next;
1393                 if(efa->f1 & 1) {
1394                 
1395                         v1 = efa->v1->tmp.v;
1396                         v2 = efa->v2->tmp.v;
1397                         v3 = efa->v3->tmp.v;
1398                         if(efa->v4) 
1399                                 v4 = efa->v4->tmp.v; 
1400                         else
1401                                 v4= 0;
1402
1403                         /* hmm .. not sure about edges here */
1404                         if(del_old==0)  // if we keep old, we flip normal
1405                                 efa2= addfacelist(v3, v2, v1, v4, efa, efa); 
1406                         else
1407                                 efa2= addfacelist(v1, v2, v3, v4, efa, efa);
1408                         
1409                         /* for transform */
1410                         add_normal_aligned(nor, efa->n);
1411
1412                         if(del_old) {
1413                                 BLI_remlink(&em->faces, efa);
1414                                 free_editface(efa);
1415                         }
1416                 }
1417                 efa= nextvl;
1418         }
1419         
1420         Normalise(nor); // for grab
1421         
1422         /* for all vertices with eve->tmp.v!=0 
1423                 if eve->f1==1: make edge
1424                 if flag!=128 : if del_old==1: remove
1425         */
1426         eve= em->verts.last;
1427         while(eve) {
1428                 nextve= eve->prev;
1429                 if(eve->tmp.v) {
1430                         if(eve->f1==1) addedgelist(eve, eve->tmp.v, NULL);
1431                         else if( (eve->f & 128)==0) {
1432                                 if(del_old) {
1433                                         BLI_remlink(&em->verts,eve);
1434                                         free_editvert(eve);
1435                                         eve= NULL;
1436                                 }
1437                         }
1438                 }
1439                 if(eve) {
1440                         eve->f &= ~128;
1441                 }
1442                 eve= nextve;
1443         }
1444         // since its vertex select mode now, it also deselects higher order
1445         EM_selectmode_flush();
1446
1447         if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // g is grab, for correct undo print
1448         return 'n';
1449 }
1450
1451 /* generic extrude */
1452 short extrudeflag(short flag, float *nor)
1453 {
1454         if(G.scene->selectmode & SCE_SELECT_VERTEX)
1455                 return extrudeflag_vert(flag, nor);
1456         else 
1457                 return extrudeflag_edge(flag, nor);
1458                 
1459 }
1460
1461 void rotateflag(short flag, float *cent, float rotmat[][3])
1462 {
1463         /* all verts with (flag & 'flag') rotate */
1464         EditMesh *em = G.editMesh;
1465         EditVert *eve;
1466
1467         eve= em->verts.first;
1468         while(eve) {
1469                 if(eve->f & flag) {
1470                         eve->co[0]-=cent[0];
1471                         eve->co[1]-=cent[1];
1472                         eve->co[2]-=cent[2];
1473                         Mat3MulVecfl(rotmat,eve->co);
1474                         eve->co[0]+=cent[0];
1475                         eve->co[1]+=cent[1];
1476                         eve->co[2]+=cent[2];
1477                 }
1478                 eve= eve->next;
1479         }
1480 }
1481
1482 void translateflag(short flag, float *vec)
1483 {
1484         /* all verts with (flag & 'flag') translate */
1485         EditMesh *em = G.editMesh;
1486         EditVert *eve;
1487
1488         eve= em->verts.first;
1489         while(eve) {
1490                 if(eve->f & flag) {
1491                         eve->co[0]+=vec[0];
1492                         eve->co[1]+=vec[1];
1493                         eve->co[2]+=vec[2];
1494                 }
1495                 eve= eve->next;
1496         }
1497 }
1498
1499 /* helper call for below */
1500 static EditVert *adduplicate_vertex(EditVert *eve, int flag)
1501 {
1502         EditVert *v1= addvertlist(eve->co);
1503         
1504         v1->f= eve->f;
1505         eve->f-= flag;
1506         eve->f|= 128;
1507         
1508         eve->tmp.v = v1;
1509         
1510         /* FIXME: Copy deformation weight ? */
1511         v1->totweight = eve->totweight;
1512         if (eve->totweight){
1513                 v1->dw = MEM_mallocN (eve->totweight * sizeof(MDeformWeight), "deformWeight");
1514                 memcpy (v1->dw, eve->dw, eve->totweight * sizeof(MDeformWeight));
1515         }
1516         else
1517                 v1->dw=NULL;
1518         
1519         return v1;
1520 }
1521
1522 /* old selection has flag 128 set, and flag 'flag' cleared
1523 new selection has flag 'flag' set */
1524 void adduplicateflag(int flag)
1525 {
1526         EditMesh *em = G.editMesh;
1527         EditVert *eve, *v1, *v2, *v3, *v4;
1528         EditEdge *eed, *newed;
1529         EditFace *efa, *newfa;
1530
1531         EM_clear_flag_all(128);
1532         EM_selectmode_set();    // paranoia check, selection now is consistant
1533
1534         /* vertices first */
1535         for(eve= em->verts.last; eve; eve= eve->prev) {
1536
1537                 if(eve->f & flag)
1538                         adduplicate_vertex(eve, flag);
1539                 else 
1540                         eve->tmp.v = NULL;
1541         }
1542         
1543         /* copy edges, note that vertex selection can be independent of edge */
1544         for(eed= em->edges.last; eed; eed= eed->prev) {
1545                 if( eed->f & flag ) {
1546                         v1 = eed->v1->tmp.v;
1547                         if(v1==NULL) v1= adduplicate_vertex(eed->v1, flag);
1548                         v2 = eed->v2->tmp.v;
1549                         if(v2==NULL) v2= adduplicate_vertex(eed->v2, flag);
1550                         
1551                         newed= addedgelist(v1, v2, eed);
1552                         
1553                         newed->f= eed->f;
1554                         eed->f -= flag;
1555                         eed->f |= 128;
1556                 }
1557         }
1558
1559         /* then duplicate faces, again create new vertices if needed */
1560         for(efa= em->faces.last; efa; efa= efa->prev) {
1561                 if(efa->f & flag) {
1562                         v1 = efa->v1->tmp.v;
1563                         if(v1==NULL) v1= adduplicate_vertex(efa->v1, flag);
1564                         v2 = efa->v2->tmp.v;
1565                         if(v2==NULL) v2= adduplicate_vertex(efa->v2, flag);
1566                         v3 = efa->v3->tmp.v;
1567                         if(v3==NULL) v3= adduplicate_vertex(efa->v3, flag);
1568                         if(efa->v4) {
1569                                 v4 = efa->v4->tmp.v; 
1570                                 if(v4==NULL) v4= adduplicate_vertex(efa->v4, flag);
1571                         }
1572                         else v4= NULL;
1573                         
1574                         newfa= addfacelist(v1, v2, v3, v4, efa, efa); 
1575                         
1576                         newfa->f= efa->f;
1577                         efa->f -= flag;
1578                         efa->f |= 128;
1579                 }
1580         }
1581         
1582         EM_fgon_flags();        // redo flags and indices for fgons
1583 }
1584
1585 void delfaceflag(int flag)
1586 {
1587         EditMesh *em = G.editMesh;
1588         /* delete all faces with 'flag', including loose edges and loose vertices */
1589         /* this is maybe a bit weird, but this function is used for 'split' and 'separate' */
1590         /* in remaining vertices/edges 'flag' is cleared */
1591         EditVert *eve,*nextve;
1592         EditEdge *eed, *nexted;
1593         EditFace *efa,*nextvl;
1594
1595         /* to detect loose edges, we put f2 flag on 1 */
1596         for(eed= em->edges.first; eed; eed= eed->next) {
1597                 if(eed->f & flag) eed->f2= 1;
1598                 else eed->f2= 0;
1599         }
1600         
1601         /* delete faces */
1602         efa= em->faces.first;
1603         while(efa) {
1604                 nextvl= efa->next;
1605                 if(efa->f & flag) {
1606                         
1607                         efa->e1->f2= 1;
1608                         efa->e2->f2= 1;
1609                         efa->e3->f2= 1;
1610                         if(efa->e4) {
1611                                 efa->e4->f2= 1;
1612                         }
1613                                                                 
1614                         BLI_remlink(&em->faces, efa);
1615                         free_editface(efa);
1616                 }
1617                 efa= nextvl;
1618         }
1619         
1620         /* all remaining faces: make sure we keep the edges */
1621         for(efa= em->faces.first; efa; efa= efa->next) {
1622                 efa->e1->f2= 0;
1623                 efa->e2->f2= 0;
1624                 efa->e3->f2= 0;
1625                 if(efa->e4) {
1626                         efa->e4->f2= 0;
1627                 }
1628         }
1629         
1630         /* remove tagged edges, and clear remaining ones */
1631         eed= em->edges.first;
1632         while(eed) {
1633                 nexted= eed->next;
1634                 
1635                 if(eed->f2==1) {
1636                         remedge(eed);
1637                         free_editedge(eed);
1638                 }
1639                 else {
1640                         eed->f &= ~flag;
1641                         eed->v1->f &= ~flag;
1642                         eed->v2->f &= ~flag;
1643                 }
1644                 eed= nexted;
1645         }
1646         
1647         /* vertices with 'flag' now are the loose ones, and will be removed */
1648         eve= em->verts.first;
1649         while(eve) {
1650                 nextve= eve->next;
1651                 if(eve->f & flag) {
1652                         BLI_remlink(&em->verts, eve);
1653                         free_editvert(eve);
1654                 }
1655                 eve= nextve;
1656         }
1657
1658 }
1659
1660 /* ********************* */
1661 #if 0
1662 static int check_vnormal_flip(float *n, float *vnorm) 
1663 {
1664         float inp;
1665
1666         inp= n[0]*vnorm[0]+n[1]*vnorm[1]+n[2]*vnorm[2];
1667
1668         /* angles 90 degrees: dont flip */
1669         if(inp> -0.000001) return 0;
1670
1671         return 1;
1672 }
1673 #endif
1674
1675 void flipface(EditFace *efa)
1676 {
1677         if(efa->v4) {
1678                 SWAP(EditVert *, efa->v2, efa->v4);
1679                 SWAP(EditEdge *, efa->e1, efa->e4);
1680                 SWAP(EditEdge *, efa->e2, efa->e3);
1681                 SWAP(unsigned int, efa->tf.col[1], efa->tf.col[3]);
1682                 SWAP(float, efa->tf.uv[1][0], efa->tf.uv[3][0]);
1683                 SWAP(float, efa->tf.uv[1][1], efa->tf.uv[3][1]);
1684         }
1685         else {
1686                 SWAP(EditVert *, efa->v2, efa->v3);
1687                 SWAP(EditEdge *, efa->e1, efa->e3);
1688                 SWAP(unsigned int, efa->tf.col[1], efa->tf.col[2]);
1689                 efa->e2->dir= 1-efa->e2->dir;
1690                 SWAP(float, efa->tf.uv[1][0], efa->tf.uv[2][0]);
1691                 SWAP(float, efa->tf.uv[1][1], efa->tf.uv[2][1]);
1692         }
1693         if(efa->v4) CalcNormFloat4(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co, efa->n);
1694         else CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, efa->n);
1695 }
1696
1697
1698 void flip_editnormals(void)
1699 {
1700         EditMesh *em = G.editMesh;
1701         EditFace *efa;
1702         
1703         efa= em->faces.first;
1704         while(efa) {
1705                 if( efa->f & SELECT ){
1706                         flipface(efa);
1707                 }
1708                 efa= efa->next;
1709         }
1710 }
1711
1712 /* does face centers too */
1713 void recalc_editnormals(void)
1714 {
1715         EditMesh *em = G.editMesh;
1716         EditFace *efa;
1717         EditVert *eve;
1718
1719         for(eve= em->verts.first; eve; eve=eve->next) {
1720                 eve->no[0] = eve->no[1] = eve->no[2] = 0.0;
1721         }
1722
1723         for(efa= em->faces.first; efa; efa=efa->next) {
1724                 if(efa->v4) {
1725                         CalcNormFloat4(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co, efa->n);
1726                         CalcCent4f(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
1727                         VecAddf(efa->v4->no, efa->v4->no, efa->n);
1728                 }
1729                 else {
1730                         CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, efa->n);
1731                         CalcCent3f(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co);
1732                 }
1733                 VecAddf(efa->v1->no, efa->v1->no, efa->n);
1734                 VecAddf(efa->v2->no, efa->v2->no, efa->n);
1735                 VecAddf(efa->v3->no, efa->v3->no, efa->n);
1736         }
1737
1738         /* following Mesh convention; we use vertex coordinate itself for normal in this case */
1739         for(eve= em->verts.first; eve; eve=eve->next) {
1740                 if (Normalise(eve->no)==0.0) {
1741                         VECCOPY(eve->no, eve->co);
1742                         Normalise(eve->no);
1743                 }
1744         }
1745 }
1746
1747 int compareface(EditFace *vl1, EditFace *vl2)
1748 {
1749         EditVert *v1, *v2, *v3, *v4;
1750         
1751         if(vl1->v4 && vl2->v4) {
1752                 v1= vl2->v1;
1753                 v2= vl2->v2;
1754                 v3= vl2->v3;
1755                 v4= vl2->v4;
1756                 
1757                 if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1 || vl1->v4==v1) {
1758                         if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2 || vl1->v4==v2) {
1759                                 if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3 || vl1->v4==v3) {
1760                                         if(vl1->v1==v4 || vl1->v2==v4 || vl1->v3==v4 || vl1->v4==v4) {
1761                                                 return 1;
1762                                         }
1763                                 }
1764                         }
1765                 }
1766         }
1767         else if(vl1->v4==0 && vl2->v4==0) {
1768                 v1= vl2->v1;
1769                 v2= vl2->v2;
1770                 v3= vl2->v3;
1771                 
1772                 if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1) {
1773                         if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2) {
1774                                 if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3) {
1775                                         return 1;
1776                                 }
1777                         }
1778                 }
1779         }
1780         
1781         return 0;
1782 }
1783
1784 /* checks for existance, not tria overlapping inside quad */
1785 EditFace *exist_face(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4)
1786 {
1787         EditMesh *em = G.editMesh;
1788         EditFace *efa, efatest;
1789         
1790         efatest.v1= v1;
1791         efatest.v2= v2;
1792         efatest.v3= v3;
1793         efatest.v4= v4;
1794         
1795         efa= em->faces.first;
1796         while(efa) {
1797                 if(compareface(&efatest, efa)) return efa;
1798                 efa= efa->next;
1799         }
1800         return NULL;
1801 }
1802
1803 /* evaluate if entire quad is a proper convex quad */
1804 int convex(float *v1, float *v2, float *v3, float *v4)
1805 {
1806         float nor[3], nor1[3], nor2[3], vec[4][2];
1807         
1808         /* define projection, do both trias apart, quad is undefined! */
1809         CalcNormFloat(v1, v2, v3, nor1);
1810         CalcNormFloat(v1, v3, v4, nor2);
1811         nor[0]= ABS(nor1[0]) + ABS(nor2[0]);
1812         nor[1]= ABS(nor1[1]) + ABS(nor2[1]);
1813         nor[2]= ABS(nor1[2]) + ABS(nor2[2]);
1814
1815         if(nor[2] >= nor[0] && nor[2] >= nor[1]) {
1816                 vec[0][0]= v1[0]; vec[0][1]= v1[1];
1817                 vec[1][0]= v2[0]; vec[1][1]= v2[1];
1818                 vec[2][0]= v3[0]; vec[2][1]= v3[1];
1819                 vec[3][0]= v4[0]; vec[3][1]= v4[1];
1820         }
1821         else if(nor[1] >= nor[0] && nor[1]>= nor[2]) {
1822                 vec[0][0]= v1[0]; vec[0][1]= v1[2];
1823                 vec[1][0]= v2[0]; vec[1][1]= v2[2];
1824                 vec[2][0]= v3[0]; vec[2][1]= v3[2];
1825                 vec[3][0]= v4[0]; vec[3][1]= v4[2];
1826         }
1827         else {
1828                 vec[0][0]= v1[1]; vec[0][1]= v1[2];
1829                 vec[1][0]= v2[1]; vec[1][1]= v2[2];
1830                 vec[2][0]= v3[1]; vec[2][1]= v3[2];
1831                 vec[3][0]= v4[1]; vec[3][1]= v4[2];
1832         }
1833         
1834         /* linetests, the 2 diagonals have to instersect to be convex */
1835         if( IsectLL2Df(vec[0], vec[2], vec[1], vec[3]) > 0 ) return 1;
1836         return 0;
1837 }
1838
1839
1840 /* ********************* Fake Polgon support (FGon) ***************** */
1841
1842
1843 /* results in:
1844    - faces having ->fgonf flag set (also for draw)
1845    - edges having ->fgoni index set (for select)
1846 */
1847
1848 float EM_face_area(EditFace *efa)
1849 {
1850         if(efa->v4) return AreaQ3Dfl(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
1851         else return AreaT3Dfl(efa->v1->co, efa->v2->co, efa->v3->co);
1852 }
1853
1854 float EM_face_perimeter(EditFace *efa)
1855 {       
1856         if(efa->v4) return
1857                 VecLenf(efa->v1->co, efa->v2->co)+
1858                 VecLenf(efa->v2->co, efa->v3->co)+
1859                 VecLenf(efa->v3->co, efa->v4->co)+
1860                 VecLenf(efa->v4->co, efa->v1->co);
1861         
1862         else return
1863                 VecLenf(efa->v1->co, efa->v2->co)+
1864                 VecLenf(efa->v2->co, efa->v3->co)+
1865                 VecLenf(efa->v3->co, efa->v1->co);
1866 }
1867
1868 void EM_fgon_flags(void)
1869 {
1870         EditMesh *em = G.editMesh;
1871         EditFace *efa, *efan, *efamax;
1872         EditEdge *eed;
1873         ListBase listb={NULL, NULL};
1874         float size, maxsize;
1875         short done, curindex= 1;
1876         
1877         // for each face with fgon edge AND not fgon flag set
1878         for(eed= em->edges.first; eed; eed= eed->next) eed->fgoni= 0;  // index
1879         for(efa= em->faces.first; efa; efa= efa->next) efa->fgonf= 0;  // flag
1880         
1881         // for speed & simplicity, put fgon face candidates in new listbase
1882         efa= em->faces.first;
1883         while(efa) {
1884                 efan= efa->next;
1885                 if( (efa->e1->h & EM_FGON) || (efa->e2->h & EM_FGON) || 
1886                         (efa->e3->h & EM_FGON) || (efa->e4 && (efa->e4->h & EM_FGON)) ) {
1887                         BLI_remlink(&em->faces, efa);
1888                         BLI_addtail(&listb, efa);
1889                 }
1890                 efa= efan;
1891         }
1892         
1893         // find an undone face with fgon edge
1894         for(efa= listb.first; efa; efa= efa->next) {
1895                 if(efa->fgonf==0) {
1896                         
1897                         // init this face
1898                         efa->fgonf= EM_FGON;
1899                         if(efa->e1->h & EM_FGON) efa->e1->fgoni= curindex;
1900                         if(efa->e2->h & EM_FGON) efa->e2->fgoni= curindex;
1901                         if(efa->e3->h & EM_FGON) efa->e3->fgoni= curindex;
1902                         if(efa->e4 && (efa->e4->h & EM_FGON)) efa->e4->fgoni= curindex;
1903                         
1904                         // we search for largest face, to give facedot drawing rights
1905                         maxsize= EM_face_area(efa);
1906                         efamax= efa;
1907                         
1908                         // now flush curendex over edges and set faceflags
1909                         done= 1;
1910                         while(done==1) {
1911                                 done= 0;
1912                                 
1913                                 for(efan= listb.first; efan; efan= efan->next) {
1914                                         if(efan->fgonf==0) {
1915                                                 // if one if its edges has index set, do other too
1916                                                 if( (efan->e1->fgoni==curindex) || (efan->e2->fgoni==curindex) ||
1917                                                         (efan->e3->fgoni==curindex) || (efan->e4 && (efan->e4->fgoni==curindex)) ) {
1918                                                         
1919                                                         efan->fgonf= EM_FGON;
1920                                                         if(efan->e1->h & EM_FGON) efan->e1->fgoni= curindex;
1921                                                         if(efan->e2->h & EM_FGON) efan->e2->fgoni= curindex;
1922                                                         if(efan->e3->h & EM_FGON) efan->e3->fgoni= curindex;
1923                                                         if(efan->e4 && (efan->e4->h & EM_FGON)) efan->e4->fgoni= curindex;
1924                                                         
1925                                                         size= EM_face_area(efan);
1926                                                         if(size>maxsize) {
1927                                                                 efamax= efan;
1928                                                                 maxsize= size;
1929                                                         }
1930                                                         done= 1;
1931                                                 }
1932                                         }
1933                                 }
1934                         }
1935                         
1936                         efamax->fgonf |= EM_FGON_DRAW;
1937                         curindex++;
1938
1939                 }
1940         }
1941
1942         // put fgon face candidates back in listbase
1943         efa= listb.first;
1944         while(efa) {
1945                 efan= efa->next;
1946                 BLI_remlink(&listb, efa);
1947                 BLI_addtail(&em->faces, efa);
1948                 efa= efan;
1949         }
1950         
1951         // remove fgon flags when edge not in fgon (anymore)
1952         for(eed= em->edges.first; eed; eed= eed->next) {
1953                 if(eed->fgoni==0) eed->h &= ~EM_FGON;
1954         }
1955         
1956 }