Well here it is. Subdivision/Loop Tools Recode Commit #1
authorJohnny Matthews <johnny.matthews@gmail.com>
Wed, 13 Jul 2005 15:20:40 +0000 (15:20 +0000)
committerJohnny Matthews <johnny.matthews@gmail.com>
Wed, 13 Jul 2005 15:20:40 +0000 (15:20 +0000)
Ton has been pushing me to get this in and finish it up with help, so here is a run down of the commit

Revised Features
Subdivide now is Edge based, allows for multicut
Loopcut was recoded, now has multi option
Knife tool now has multi option

New Features
Edgeslide
Edgering select

Removed Features
Alt-B Edgeloop selection (use alt-RMB in edgemode)
Shift-R Faceloop selection (use alt-RMB in facemode)
Old Subdivide (Except for smooth which is left in until new one works)

Todo
Subdivide Smooth Math is broken - could use some help here (look for alter_co in editmesh_tools.c)
Tweak mouse control of Edgeslide is hackish ATM
Add Non-proportional movement  to edgeslide
Add smooth option to new loopcut

I probably left something out.

See here for more info
http://wiki.blender.org/bin/view.pl/Blenderdev/EdgeSubdivision

12 files changed:
source/blender/blenlib/BLI_linklist.h
source/blender/blenlib/intern/BLI_linklist.c
source/blender/include/BIF_editmesh.h
source/blender/src/buttons_editing.c
source/blender/src/editmesh_add.c
source/blender/src/editmesh_loop.c
source/blender/src/editmesh_mods.c
source/blender/src/editmesh_tools.c
source/blender/src/editobject.c
source/blender/src/header_view3d.c
source/blender/src/space.c
source/blender/src/toolbox.c

index d0e6effae3d310df30e3790c964310d161ce6406..2e75420a1ffa5fd80e7c53557280dedc204a6634 100644 (file)
@@ -52,6 +52,7 @@ int           BLI_linklist_length             (struct LinkNode *list);
 void   BLI_linklist_reverse    (struct LinkNode **listp);
 
 void   BLI_linklist_prepend            (struct LinkNode **listp, void *ptr);
+void   BLI_linklist_append             (struct LinkNode **listp, void *ptr);
 void   BLI_linklist_prepend_arena      (struct LinkNode **listp, void *ptr, struct MemArena *ma);
 
 void   BLI_linklist_free               (struct LinkNode *list, LinkNodeFreeFP freefunc);
index ad945b53d11dd747bfc9f11ecf396f36a10ce61a..253d127db388625619041eed4ee5c0702af2e761 100644 (file)
@@ -76,6 +76,23 @@ void BLI_linklist_prepend(LinkNode **listp, void *ptr) {
        *listp= nlink;
 }
 
+void BLI_linklist_append(LinkNode **listp, void *ptr) {
+       LinkNode *nlink= MEM_mallocN(sizeof(*nlink), "nlink");
+       LinkNode *node = *listp;
+       
+       nlink->link = ptr;
+       nlink->next = NULL;
+       
+       if(node == NULL){
+        *listp = nlink;
+    } else {
+        while(node->next != NULL){
+            node = node->next;   
+        }
+        node->next = nlink;
+    }
+}
+
 void BLI_linklist_prepend_arena(LinkNode **listp, void *ptr, MemArena *ma) {
        LinkNode *nlink= BLI_memarena_alloc(ma, sizeof(*nlink));
        nlink->link= ptr;
index 0f794e89ed6768a093ec0e58bc1e5a7c029fe0f1..c1dd2c43afa23241fd79a3ce87a4993647420b69 100644 (file)
@@ -101,6 +101,7 @@ extern void EM_free_backbuf_border(void);
 
 extern void EM_selectmode_menu(void);
 
+
 extern void vertexnoise(void);
 extern void vertexsmooth(void);
 extern void righthandfaces(int select);
@@ -135,20 +136,22 @@ extern void editmesh_deselect_by_material(int index);
 extern void Edge_Menu(void);
 extern void editmesh_mark_seam(int clear);
 
+
 /* ******************* editmesh_loop.c */
 
 #define KNIFE_PROMPT 0
 #define KNIFE_EXACT 1
 #define KNIFE_MIDPOINT 2
+#define KNIFE_MULTICUT 3
 
+extern void CutEdgeloop(int numcuts);
 extern void KnifeSubdivide(char mode);
 extern void LoopMenu(void);
 
 #define LOOP_SELECT    1
 #define LOOP_CUT       2
 
-extern void loopoperations(char mode);
-extern void vertex_loop_select(void); 
+extern short sharesFace(struct EditEdge* e1, struct EditEdge* e2);
 
 /* ******************* editmesh_tools.c */
 extern void convert_to_triface(int all);
@@ -156,6 +159,7 @@ extern int removedoublesflag(short flag, float limit);
 extern void xsortvert_flag(int flag);
 extern void hashvert_flag(int flag);
 extern void subdivideflag(int flag, float rad, int beauty);
+extern void esubdivideflag(int flag, float rad, int beauty, int numcuts, int selecttype);
 extern void extrude_mesh(void);
 extern void split_mesh(void);
 extern void extrude_repeat_mesh(int steps, float offs);
@@ -168,6 +172,7 @@ extern void edge_flip(void);
 extern void fill_mesh(void);
 extern void bevel_menu();
 void edge_rotate_selected(int dir);
+void EdgeSlide(short immediate, float imperc);
  
 #endif
 
index e07b0d2118b3c4b6ebea1c7723702cf13437035b..8a8423fe4bc785ad83599c704a9103c402e1f340 100644 (file)
@@ -2048,7 +2048,7 @@ void do_meshbuts(unsigned short event)
                break;
        case B_SUBDIV:
                waitcursor(1);
-               subdivideflag(1, 0.0, editbutflag & B_BEAUTY);
+               esubdivideflag(1, 0.0, editbutflag & B_BEAUTY,1,0);
                countall();
                waitcursor(0);
                allqueue(REDRAWVIEW3D, 0);
@@ -2059,7 +2059,7 @@ void do_meshbuts(unsigned short event)
                if(button(&randfac, 1, 100, "Rand fac:")==0) return;
                waitcursor(1);
                fac= -( (float)randfac )/100;
-               subdivideflag(1, fac, editbutflag & B_BEAUTY);
+               esubdivideflag(1, fac, editbutflag & B_BEAUTY,1,0);
                countall();
                waitcursor(0);
                allqueue(REDRAWVIEW3D, 0);
index f8518fc4a903700cd85d0cb5fff5d4861960701d..25249f890aa9e68f8e33f38303c5a9b2f2dc84e8 100644 (file)
@@ -776,7 +776,8 @@ void add_primitiveMesh(int type)
        }
        else if(type==12) {     /* Icosphere */
                EditVert *eva[12];
-
+        EditEdge *eed;
+        
                /* clear all flags */
                eve= em->verts.first;
                while(eve) {
@@ -792,14 +793,18 @@ void add_primitiveMesh(int type)
                        eva[a]->f= 1+2;
                }
                for(a=0;a<20;a++) {
-                       v1= eva[ icoface[a][0] ];
+                   EditFace *evtemp;
+            v1= eva[ icoface[a][0] ];
                        v2= eva[ icoface[a][1] ];
                        v3= eva[ icoface[a][2] ];
-                       addfacelist(v1, v2, v3, 0, NULL, NULL);
+                       evtemp = addfacelist(v1, v2, v3, 0, NULL, NULL);
+                       evtemp->e1->f = 1+2;
+                       evtemp->e2->f = 1+2;
+                       evtemp->e3->f = 1+2;
                }
 
                dia*=200;
-               for(a=1; a<subdiv; a++) subdivideflag(2, dia, 0);
+               for(a=1; a<subdiv; a++) esubdivideflag(2, dia, 0,1,0);
                /* and now do imat */
                eve= em->verts.first;
                while(eve) {
@@ -809,6 +814,15 @@ void add_primitiveMesh(int type)
                        }
                        eve= eve->next;
                }
+               
+               // Clear the flag 2 from the edges
+               for(eed=em->edges.first;eed;eed=eed->next){
+            if(eed->f & 2){
+                   eed->f &= !2;
+            }   
+        }
+               
+               
        } else if (type==13) {  /* Monkey */
                extern int monkeyo, monkeynv, monkeynf;
                extern signed char monkeyf[][4];
index afc63ee50f7ba966d9064342a74c0c060ff6d54c..ca1985ba5af2cefa12272699bef286f4830b857b 100644 (file)
@@ -90,67 +90,123 @@ editmesh_loop: tools with own drawing subloops, select, knife, subdiv
 #include "winlay.h"
 
 
-/* *************** LOOP SELECT ************* */
-
-static short edgeFaces(EditEdge *e){
+/* New LoopCut */
+static void edgering_sel(EditEdge *startedge, int select, int previewlines){
        EditMesh *em = G.editMesh;
-       EditFace *search=NULL;
-       short count = 0;
-       
-       search = em->faces.first;
-       while(search){
-               if((search->e1 == e || search->e2 == e) || (search->e3 == e || search->e4 == e)) 
-                       count++;
-       search = search->next;
+       EditEdge *eed;
+       EditFace *efa;
+       int looking= 1,i;
+       float co[2][3];
+       EditVert *v[2][2];
+       /* in eed->f1 we put the valence (amount of faces in edge) */
+       /* in eed->f2 we put tagged flag as correct loop */
+       /* in efa->f1 we put tagged flag as correct to select */
+
+       for(eed= em->edges.first; eed; eed= eed->next) {
+               eed->f1= 0;
+               eed->f2= 0;
        }
-       return count;   
-}
-
-/* this utility function checks to see if 2 edit edges share a face,
-       returns 1 if they do
-       returns 0 if they do not, or if the function is passed the same edge 2 times
-*/
-static short sharesFace(EditEdge* e1, EditEdge* e2)
-{
-       EditMesh *em = G.editMesh;
-       EditFace *search=NULL;
-       search = em->faces.first;
-       if (e1 == e2){
-               return 0 ;
+       for(efa= em->faces.first; efa; efa= efa->next) {
+               efa->f1= 0;
+               if(efa->h==0) {
+                       efa->e1->f1++;
+                       efa->e2->f1++;
+                       efa->e3->f1++;
+                       if(efa->e4) efa->e4->f1++;
+               }
        }
-       while(search){
-               if(
-                       ((search->e1 == e1 || search->e2 == e1) || (search->e3 == e1 || search->e4 == e1)) &&
-                       ((search->e1 == e2 || search->e2 == e2) || (search->e3 == e2 || search->e4 == e2))
-                       ) {
-                       return 1;
+       
+       // tag startedge OK
+       startedge->f2= 1;
+       
+       while(looking) {
+               looking= 0;
+               
+               for(efa= em->faces.first; efa; efa= efa->next) {
+                       if(efa->e4 && efa->f1==0) {     // not done quad
+                               if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { // valence ok
+
+                                       // if edge tagged, select opposing edge and mark face ok
+                                       if(efa->e1->f2) {
+                                               efa->e3->f2= 1;
+                                               efa->f1= 1;
+                                               looking= 1;
+                                       }
+                                       else if(efa->e2->f2) {
+                                               efa->e4->f2= 1;
+                                               efa->f1= 1;
+                                               looking= 1;
+                                       }
+                                       if(efa->e3->f2) {
+                                               efa->e1->f2= 1;
+                                               efa->f1= 1;
+                                               looking= 1;
+                                       }
+                                       if(efa->e4->f2) {
+                                               efa->e2->f2= 1;
+                                               efa->f1= 1;
+                                               looking= 1;
+                                       }
+                               }
+                       }
                }
-               search = search->next;
        }
-       return 0;
+       
+    if(previewlines > 0 && select == 0){
+               persp(PERSP_VIEW);
+                       glPushMatrix();
+                       mymultmatrix(G.obedit->obmat);
+                       //glColor3ub(0, 255, 255);
+                       //glBegin(GL_LINES);                    
+                       //glVertex3f(nearest->v1->co[0],nearest->v1->co[1],nearest->v1->co[2]);
+                       //glVertex3f(nearest->v2->co[0],nearest->v2->co[1],nearest->v2->co[2]);
+                       //glEnd();
+                       for(efa= em->faces.first; efa; efa= efa->next) {
+                if(efa->v4 == NULL) {  continue; }
+                if(efa->e1->f2 == 1){
+                    v[0][0] = efa->v1;
+                    v[0][1] = efa->v2;
+                    v[1][0] = efa->v4;
+                    v[1][1] = efa->v3;
+                } else if(efa->e2->f2 == 1){
+                    v[0][0] = efa->v2;
+                    v[0][1] = efa->v3;
+                    v[1][0] = efa->v1;
+                    v[1][1] = efa->v4;                    
+                } else { continue; }
+                                      
+                       for(i=1;i<=previewlines;i++){
+                    co[0][0] = (v[0][1]->co[0] - v[0][0]->co[0])*(i/((float)previewlines+1))+v[0][0]->co[0];
+                    co[0][1] = (v[0][1]->co[1] - v[0][0]->co[1])*(i/((float)previewlines+1))+v[0][0]->co[1];
+                    co[0][2] = (v[0][1]->co[2] - v[0][0]->co[2])*(i/((float)previewlines+1))+v[0][0]->co[2];
+
+                    co[1][0] = (v[1][1]->co[0] - v[1][0]->co[0])*(i/((float)previewlines+1))+v[1][0]->co[0];
+                    co[1][1] = (v[1][1]->co[1] - v[1][0]->co[1])*(i/((float)previewlines+1))+v[1][0]->co[1];
+                    co[1][2] = (v[1][1]->co[2] - v[1][0]->co[2])*(i/((float)previewlines+1))+v[1][0]->co[2];                    
+                    glColor3ub(255, 0, 255);
+                               glBegin(GL_LINES);      
+                               glVertex3f(co[0][0],co[0][1],co[0][2]);
+                               glVertex3f(co[1][0],co[1][1],co[1][2]);
+                               glEnd();
+                }
+            }
+                       glPopMatrix();   
+    } else {   
+       
+          /* (de)select the edges */
+          for(eed= em->edges.first; eed; eed= eed->next) {
+               if(eed->f2) EM_select_edge(eed, select);
+          }
+    }
 }
-/* This function selects a vertex loop based on a each succesive edge having a valance of 4
-   and not sharing a face with the previous edge */
-
-/* It uses ->f flags still, which isn't causing bugs now, but better be put in ->f1 (ton) */
-
-void vertex_loop_select() 
-{
-       EditMesh *em = G.editMesh;
-       EditVert *v1=NULL,*v2=NULL;
-       EditEdge *search=NULL,*startEdge=NULL,*valSearch = NULL,*nearest = NULL,*compEdge;
-       EditEdge *EdgeVal[5] = {NULL,NULL,NULL,NULL,NULL};
-       short numEdges=0,curEdge = 0,looking = 1,edgeValCount = 0,i=0,looped = 0,choosing = 1,event,noloop=0,cancel=0, val;
-       short protect = 0, dist= 50;
+void CutEdgeloop(int numcuts){
+    EditMesh *em = G.editMesh;
        short mvalo[2] = {0,0}, mval[2];
-
-       SetBlenderCursor(BC_VLOOPCURSOR);
-       for(search=em->edges.first;search;search=search->next)
-               numEdges++;
-
-       /* start with v1 and go in one direction. */
-       while(choosing){
-               getmouseco_areawin(mval);
+       EditEdge* nearest,*eed;
+       short event,val,choosing=1,cancel=0,dist,cuthalf = 0;
+    
+    while(choosing){
+        getmouseco_areawin(mval);
                if (mval[0] != mvalo[0] || mval[1] != mvalo[1]) {
 
                        mvalo[0] = mval[0];
@@ -158,139 +214,12 @@ void vertex_loop_select()
 
                        dist= 50;
                        nearest = findnearestedge(&dist);       // returns actual distance in dist
-                       
-                       scrarea_do_windraw(curarea);    // after findnearestedge, backbuf!
-
-                       if (nearest && edgeFaces(nearest)==2) {
-                               for(search = em->edges.first;search;search=search->next)
-                                       search->f &= ~32;
-                                       
-                               compEdge = startEdge = nearest;
-                               nearest->f |= 32;
-                               curEdge = 0;
-                               v1 = startEdge->v1;
-                               v2 = startEdge->v2;
-                               looking = 1;
-                               while(looking){
-                                       if(protect++ > numEdges) break;
-                                       if(edgeFaces(compEdge) != 2) break;
-                                       /*Find Edges that have v1*/
-                                       edgeValCount = -1;
-                                       EdgeVal[0] = EdgeVal[1] = EdgeVal[2] = NULL;
-                                       
-                                       for(valSearch = em->edges.first;valSearch;valSearch = valSearch->next){
-                                               if(valSearch->v1 == v1 || valSearch->v2 == v1){
-                                                       if(valSearch != compEdge){
-                                                               if((valSearch->v1->h == 0) && (valSearch->v2->h == 0)){
-                                                                       if(edgeFaces(valSearch) == 2){
-                                                                               edgeValCount++;                                                 
-                                                                               EdgeVal[edgeValCount] = valSearch;
-                                                                       }
-                                                               }
-                                                       }
-                                               }
-                                               if(edgeValCount == 3)break;
-                                       }
-                                       /* Check that there was a valance of 4*/
-                                       if(edgeValCount != 2){
-                                               noloop = 1;
-                                               looking = 0;
-                                               break;
-                                       }
-                                       else{
-                                       /* There were 3 edges, so find the one that does not share the previous edge */
-                                               for(i=0;i<3;i++){
-                                                       if(sharesFace(compEdge,EdgeVal[i]) == 0){
-                                                               /* We went all the way around the loop */
-                                                               if(EdgeVal[i] == nearest){
-                                                                       looking = 0;
-                                                                       looped = 1;
-                                                                       break;
-                                                               }
-                                                               else{
-                                                                       /* we are still in the loop, so add the next edge*/
-                                                                       curEdge++;
-                                                                       EdgeVal[i]->f |= 32;
-                                                                       compEdge = EdgeVal[i];
-                                                                       if(compEdge->v1 == v1)
-                                                                               v1 = compEdge->v2;
-                                                                       else
-                                                                               v1 = compEdge->v1;
-                                                               }
-                                                       }
-                                               }
-                                       }
-                               }       
-                               compEdge = nearest;
-                               looking = 1;
-                               protect = 0;
-                               while(looking/* && !looped*/){
-                                       if(protect++ > numEdges) break;
-                                       if(edgeFaces(compEdge) != 2) break;
-                                       /*Find Edges that have v1*/
-                                       edgeValCount = -1;
-                                       EdgeVal[0] = EdgeVal[1] = EdgeVal[2] = NULL;
-                                       
-                                       for(valSearch = em->edges.first;valSearch;valSearch = valSearch->next){
-                                               if(valSearch->v1 == v2 || valSearch->v2 == v2){
-                                                       if(valSearch != compEdge){
-                                                               if((valSearch->v1->h == 0) && (valSearch->v2->h == 0)){
-                                                                       if(edgeFaces(valSearch) == 2){
-                                                                               edgeValCount++;                                                 
-                                                                               EdgeVal[edgeValCount] = valSearch;
-                                                                       }
-                                                               }
-                                                       }
-                                               }
-                                               if(edgeValCount == 3)break;
-                                       }
-                                       /* Check that there was a valance of 4*/
-                                       if(edgeValCount != 2){
-                                               noloop = 1;
-                                               looking = 0;
-                                               break;
-                                       }
-                                       else{
-                                       /* There were 3 edges, so find the one that does not share the previous edge */
-                                               for(i=0;i<3;i++){
-                                                       if(sharesFace(compEdge,EdgeVal[i]) == 0){
-                                                               /* We went all the way around the loop */
-                                                               if(EdgeVal[i] == nearest){
-                                                                       looking = 0;
-                                                                       looped = 1;
-                                                                       break;
-                                                               }
-                                                               else{
-                                                                       /* we are still in the loop, so add the next edge*/
-                                                                       curEdge++;
-                                                                       EdgeVal[i]->f |= 32;
-                                                                       compEdge = EdgeVal[i];
-                                                                       if(compEdge->v1 == v2)
-                                                                               v2 = compEdge->v2;
-                                                                       else
-                                                                               v2 = compEdge->v1;
-                                                               }
-                                                       }
-                                               }
-                                       }
-                               }
-                               /* set up for opengl drawing in the 3d window */
-                               persp(PERSP_VIEW);
-                               glPushMatrix();
-                               mymultmatrix(G.obedit->obmat);
-                               glColor3ub(0, 255, 255);
-                               for(search = em->edges.first;search;search= search->next){
-                                       if(search->f & 32){
-                                               glBegin(GL_LINES);                      
-                                               glVertex3f(search->v1->co[0],search->v1->co[1],search->v1->co[2]);
-                                               glVertex3f(search->v2->co[0],search->v2->co[1],search->v2->co[2]);
-                                               glEnd();
-                                       }
-                               }               
-
-                               glPopMatrix();
-                       }
+                       scrarea_do_windraw(curarea);    // after findnearestedge, backbuf!        
 
+            /* Need to figure preview */
+            if(nearest){
+                   edgering_sel(nearest, 0, numcuts);
+             }   
                        screen_swapbuffers();
 
                /* backbuffer refresh for non-apples (no aux) */
@@ -300,14 +229,16 @@ void vertex_loop_select()
                        }
 #endif
                }
-               else PIL_sleep_ms(10);  // idle
-               
+               else PIL_sleep_ms(10);  // idle         
                while(qtest()) 
                {
                        val=0;
                        event= extern_qread(&val);
                        if(val && ((event==LEFTMOUSE || event==RETKEY) || event == MIDDLEMOUSE))
                        {
+                if(event == MIDDLEMOUSE){
+                    cuthalf = 1;   
+                }
                                if (nearest==NULL)
                                        cancel = 1;
                                choosing=0;
@@ -319,65 +250,90 @@ void vertex_loop_select()
                                cancel = 1;
                                break;
                        }
-                       if(val && (event==BKEY && G.qual==LR_ALTKEY ))
-                       {                       
-                               
-                               SetBlenderCursor(SYSCURSOR);
-                               loopoperations(LOOP_SELECT);
-                               return;
-                       }
-               }
-       }
-       if(!cancel){
-               /* If this is a unmodified select, clear the selection */
-               
-               /* XXX note that !1 is 0, so it not only clears bit 1 (ton) */
-               if(!(G.qual & LR_SHIFTKEY) && !(G.qual & LR_ALTKEY)){
-                       for(search = em->edges.first;search;search= search->next){
-                               search->v1->f &= !1;
-                               search->v2->f &= !1;
-                       }
-                       EM_clear_flag_all(SELECT);      /* XXX probably that's sufficient */
-               }
-               /* Alt was not pressed, so add to the selection */
-               if(!(G.qual & LR_ALTKEY)){
-                       for(search = em->edges.first;search;search= search->next){
-                               if(search->f & 32){
-                                       search->v1->f |= 1;
-                                       search->v2->f |= 1;
-                               }
-                               search->f &= ~32;
+                       if(val && (event==PADPLUSKEY || event==WHEELUPMOUSE))
+                       {
+                               numcuts++;
+                               mvalo[0] = 0;mvalo[1] = 0;
+                               break;
                        }
-                       /* XXX this will correctly flush */
-               }
-               /* alt was pressed, so subtract from the selection */
-               else
-               {
-                       /* XXX this doesnt flush correct in face select mode */
-                       for(search = em->edges.first;search;search= search->next){
-                               if(search->f & 32){
-                                       search->v1->f &= !1;
-                                       search->v2->f &= !1;
-                                       EM_select_edge(search, 0);      // the call to deselect edge
-                               }
-                               search->f &= ~32;
+                       if(val && (event==PADMINUS || event==WHEELDOWNMOUSE))
+                       {
+                if(numcuts > 1){
+                               numcuts--;
+                               mvalo[0] = 0;mvalo[1] = 0;
+                               break;
+                } 
                        }
-               }
-               
-               EM_select_flush(); // flushes vertex -> edge -> face selection
-               
-               countall();
-               
-               BIF_undo_push("Select Vertex Loop");
-       }
-
-       addqueue(curarea->win, REDRAW, 1); 
-       SetBlenderCursor(SYSCURSOR);
-       return;
+               }       
+    }
+    if(cancel){
+        return;   
+    }
+    /* clean selection */
+    for(eed=em->edges.first; eed; eed = eed->next){
+        EM_select_edge(eed,0);   
+    }
+    /* select edge ring */
+       edgering_sel(nearest, 1, 0);
+       
+       /* now cut the loops */
+       esubdivideflag(SELECT,0,0,numcuts,1);
+       
+    force_draw(0);
+    makeDispList(G.obedit);
+    scrarea_queue_winredraw(curarea);
+       
+       /* if this was a single cut, enter edgeslide mode */
+       if(numcuts == 1){
+        if(cuthalf)
+            EdgeSlide(1,0.0);
+        else
+            EdgeSlide(0,0.0);       
+    }
+       
+    return;
 }
 
-/* *********** END LOOP SELECT ********** */
 
+/* *************** LOOP SELECT ************* */
+
+static short edgeFaces(EditEdge *e){
+       EditMesh *em = G.editMesh;
+       EditFace *search=NULL;
+       short count = 0;
+       
+       search = em->faces.first;
+       while(search){
+               if((search->e1 == e || search->e2 == e) || (search->e3 == e || search->e4 == e)) 
+                       count++;
+       search = search->next;
+       }
+       return count;   
+}
+
+/* this utility function checks to see if 2 edit edges share a face,
+       returns 1 if they do
+       returns 0 if they do not, or if the function is passed the same edge 2 times
+*/
+short sharesFace(EditEdge* e1, EditEdge* e2)
+{
+       EditMesh *em = G.editMesh;
+       EditFace *search=NULL;
+       search = em->faces.first;
+       if (e1 == e2){
+               return 0 ;
+       }
+       while(search){
+               if(
+                       ((search->e1 == e1 || search->e2 == e1) || (search->e3 == e1 || search->e4 == e1)) &&
+                       ((search->e1 == e2 || search->e2 == e2) || (search->e3 == e2 || search->e4 == e2))
+                       ) {
+                       return 1;
+               }
+               search = search->next;
+       }
+       return 0;
+}
 
 
 /*   ***************** TRAIL ************************
@@ -549,6 +505,7 @@ void KnifeSubdivide(char mode)
        CutCurve *curve;                
        EditEdge *eed; 
        Window *win;    
+       short numcuts=1;
        
        if (G.obedit==0) return;
 
@@ -558,11 +515,15 @@ void KnifeSubdivide(char mode)
        }
 
        if (mode==KNIFE_PROMPT) {
-               short val= pupmenu("Cut Type %t|Exact Line%x1|Midpoints%x2");
+               short val= pupmenu("Cut Type %t|Exact Line%x1|Midpoints%x2|Multicut%x3");
                if(val<1) return;
-               mode= val;      // warning, mode is char, pupmenu returns -1 with ESC
+               mode = val;     // warning, mode is char, pupmenu returns -1 with ESC
        }
 
+    if(mode == KNIFE_MULTICUT) {
+       if(button(&numcuts, 2, 128, "Number of Cuts:")==0) return;
+    }
+
        calc_meshverts_ext();  /*Update screen coords for current window */
        
        /* Set a knife cursor here */
@@ -591,9 +552,10 @@ void KnifeSubdivide(char mode)
                        eed= eed->next;
                }
                
-               if (mode==1) subdivideflag(1, 0, B_KNIFE|B_PERCENTSUBD);
-               else if (mode==2) subdivideflag(1, 0, B_KNIFE);
-               
+               if      (mode==KNIFE_EXACT)    esubdivideflag(1, 0, B_KNIFE|B_PERCENTSUBD,1,0);
+               else if (mode==KNIFE_MIDPOINT) esubdivideflag(1, 0, B_KNIFE,1,0);
+               else if (mode==KNIFE_MULTICUT) esubdivideflag(1, 0, B_KNIFE,numcuts,0);
+                       
                eed=em->edges.first;
                while(eed){
                        eed->f2=0;
@@ -718,1103 +680,26 @@ short seg_intersect(EditEdge *e, CutCurve *c, int len){
        return(isect);
 } 
 
-/* ******************** LOOP ******************************************* */
-
-/* XXX: this loop function is totally out of control!
-   can be half the code, and using structured functions (ton) */
-   
-/* 
-functionality: various loop functions
-parameters: mode tells the function what it should do with the loop:
-               LOOP_SELECT = select
-               LOOP_CUT = cut in half
-*/     
-
-void loopoperations(char mode)
-{
-       EditMesh *em = G.editMesh;
-       EditVert* look = NULL;
-       EditEdge *start, *eed, *opposite,*currente, *oldstart;
-       EditEdge **tagged = NULL,**taggedsrch = NULL,*close;
-       EditFace *efa,**percentfacesloop = NULL, *currentvl,  *formervl;        
-       short lastface=0, foundedge=0, c=0, tri=0, side=1, totface=0, searching=1, event=0, noface=1;
-       short skip,nextpos,percentfaces, dist=50;
-
-       int i=0,ect=0,j=0,k=0,cut,smooth,timesthrough=0,inset = 0;
-
-       float percentcut, outcut;
-
-       char mesg[100];
-
-       if ((G.obedit==0) || (em->faces.first==0)) return;
-       
-       SetBlenderCursor(BC_VLOOPCURSOR);
-       
-       /* Clear flags */
-       for(eed=em->edges.first; eed; eed=eed->next) eed->f2= 0;
-       for(efa= em->faces.first; efa; efa=efa->next) efa->f1= 0;
-       
-       start=NULL;
-       oldstart=NULL;
-
-       while(searching){
-               
-               /* reset variables */
-               start=eed=opposite=currente=0;
-               efa=currentvl=formervl=0;
-               side=noface=1;
-               lastface=foundedge=c=tri=totface=0;             
-                               
-               //start=findnearestvisibleedge();
-               dist= 50;
-               start= findnearestedge(&dist);
-               
-               /* used flags in the code:
-                  vertex->f & 2: in findnearestvisibleedge
-                  edge->f2 : subdiv codes
-                  efa->f1 : subdiv codes
-               */
-               
-               /* If the edge doesn't belong to a face, it's not a valid starting edge */
-               /* and only accept starting edge if it is part of at least one visible face */
-               if(start){
-                       start->f2 |= 16;
-                       efa=em->faces.first;
-                       while(efa){
-                               /* since this edge is on the face, check if the face is hidden */
-                               if( efa->h==0  ){
-                                       if(efa->e1->f2 & 16){
-                                               noface=0;
-                                               efa->e1->f2 &= ~16;
-                                       }
-                                       else if(efa->e2->f2 & 16){                                      
-                                               noface=0;
-                                               efa->e2->f2 &= ~16;
-                                       }
-                                       else if(efa->e3->f2 & 16){                                      
-                                               noface=0;
-                                               efa->e3->f2 &= ~16;
-                                       }
-                                       else if(efa->e4 && (efa->e4->f2 & 16)){                                 
-                                               noface=0;
-                                               efa->e4->f2 &= ~16;
-                                       }
-                               }
-                               efa=efa->next;
-                       }                       
-               }
-                               
-               /* Did we find anything that is selectable? */
-               if(start && !noface && (oldstart==NULL || start!=oldstart)){
-                                       
-                       /* If we stay in the neighbourhood of this edge, we don't have to recalculate the loop everytime*/
-                       oldstart=start; 
-                       
-                       /* Clear flags */
-                       for(eed=em->edges.first; eed; eed=eed->next){                   
-                               eed->f2 &= ~(2|4|8|32|64);
-                               eed->v1->f &= ~(2|8|16); // xxxx
-                               eed->v2->f &= ~(2|8|16);                                
-                       }
-                       
-                       for(efa= em->faces.first; efa; efa=efa->next){                  
-                               efa->f1 &= ~(4|8);
-                               totface++;                              
-                       }
-                                       
-                       /* Tag the starting edge */
-                       start->f2 |= (2|4|8|64);                                
-                       start->v1->f |= 2;  /* xxxx */
-                       start->v2->f |= 2;              
-                       
-                       currente=start;                                         
-                       
-                       /*-----Limit the Search----- */
-                       while(!lastface && c<totface+1){
-                               
-                               /*----------Get Loop------------------------*/
-                               tri=foundedge=lastface=0;                                                                                                       
-                               efa= em->faces.first;           
-                               while(efa && !foundedge && !tri){
-                                                                       
-                                       if(!(efa->v4)){ /* Exception for triangular faces */
-                                               
-                                               if((efa->e1->f2 | efa->e2->f2 | efa->e3->f2) & 2){
-                                                       if(!(efa->f1 & 4)){                                                             
-                                                               tri=1;
-                                                               currentvl=efa;
-                                                               if(side==1) efa->f1 |= 4;
-                                                       }
-                                               }                                               
-                                       }
-                                       else{
-                                               
-                                               if((efa->e1->f2 | efa->e2->f2 | efa->e3->f2 | efa->e4->f2) & 2){
-                                                       
-                                                       if(c==0){       /* just pick a face, doesn't matter wich side of the edge we go to */
-                                                               if(!(efa->f1 & 4)){
-                                                                       
-                                                                       if(!(efa->e1->v1->f & 2) && !(efa->e1->v2->f & 2)){ // xxxxx
-                                                                               if(efa->e1->h==0){
-                                                                                       opposite=efa->e1;                                                                                                               
-                                                                                       foundedge=1;
-                                                                               }
-                                                                       }
-                                                                       else if(!(efa->e2->v1->f & 2) && !(efa->e2->v2->f & 2)){ // xxxx
-                                                                               if(efa->e2->h==0){
-                                                                                       opposite=efa->e2;
-                                                                                       foundedge=1;
-                                                                               }
-                                                                       }
-                                                                       else if(!(efa->e3->v1->f & 2) && !(efa->e3->v2->f & 2)){
-                                                                               if(efa->e3->h==0){
-                                                                                       opposite=efa->e3;
-                                                                                       foundedge=1;
-                                                                               }
-                                                                       }
-                                                                       else if(!(efa->e4->v1->f & 2) && !(efa->e4->v2->f & 2)){
-                                                                               if(efa->e4->h==0){
-                                                                                       opposite=efa->e4;
-                                                                                       foundedge=1;
-                                                                               }
-                                                                       }
-                                                                       
-                                                                       if(foundedge){
-                                                                               currentvl=efa;
-                                                                               formervl=efa;
-                                                                       
-                                                                               /* mark this side of the edge so we know in which direction we went */
-                                                                               if(side==1) efa->f1 |= 4;
-                                                                       }
-                                                               }
-                                                       }
-                                                       else {  
-                                                               if(efa!=formervl){      /* prevent going backwards in the loop */
-                                                               
-                                                                       if(!(efa->e1->v1->f & 2) && !(efa->e1->v2->f & 2)){
-                                                                               if(efa->e1->h==0){
-                                                                                       opposite=efa->e1;                                                                                                               
-                                                                                       foundedge=1;
-                                                                               }
-                                                                       }
-                                                                       else if(!(efa->e2->v1->f & 2) && !(efa->e2->v2->f & 2)){
-                                                                               if(efa->e2->h==0){
-                                                                                       opposite=efa->e2;
-                                                                                       foundedge=1;
-                                                                               }
-                                                                       }
-                                                                       else if(!(efa->e3->v1->f & 2) && !(efa->e3->v2->f & 2)){
-                                                                               if(efa->e3->h==0){
-                                                                                       opposite=efa->e3;
-                                                                                       foundedge=1;
-                                                                               }
-                                                                       }
-                                                                       else if(!(efa->e4->v1->f & 2) && !(efa->e4->v2->f & 2)){
-                                                                               if(efa->e4->h==0){
-                                                                                       opposite=efa->e4;
-                                                                                       foundedge=1;
-                                                                               }
-                                                                       }
-                                                                       
-                                                                       currentvl=efa;
-                                                               }
-                                                       }
-                                               }
-                                       }
-                               efa=efa->next;
-                               }
-                               /*----------END Get Loop------------------------*/
-                               
-                       
-                               /*----------Decisions-----------------------------*/
-                               if(foundedge){
-                                       /* mark the edge and face as done */                                    
-                                       currente->f2 |= 8;
-                                       currentvl->f1 |= 8;
-
-                                       if(opposite->f2 & 4) lastface=1;        /* found the starting edge! close loop */                                                               
-                                       else{
-                                               /* un-set the testflags */
-                                               currente->f2 &= ~2;
-                                               currente->v1->f &= ~2; // xxxx
-                                               currente->v2->f &= ~2;                                                  
-                                               
-                                               /* set the opposite edge to be the current edge */                              
-                                               currente=opposite;                                                      
-                                               
-                                               /* set the current face to be the FORMER face (to prevent going backwards in the loop) */
-                                               formervl=currentvl;
-                                               
-                                               /* set the testflags */
-                                               currente->f2 |= 2;
-                                               currente->v1->f |= 2; // xxxx
-                                               currente->v2->f |= 2;                   
-                                       }
-                                       c++;
-                               }
-                               else{   
-                                       /* un-set the testflags */
-                                       currente->f2 &= ~2;
-                                       currente->v1->f &= ~2; // xxxx
-                                       currente->v2->f &= ~2;
-                                       
-                                       /* mark the edge and face as done */
-                                       currente->f2 |= 8;
-                                       currentvl->f1 |= 8;
-                                       
-                                       
-                                                                                               
-                                       /* is the the first time we've ran out of possible faces?
-                                       *  try to start from the beginning but in the opposite direction go as far as possible
-                                       */                              
-                                       if(side==1){                                            
-                                               if(tri)tri=0;
-                                               currente=start;
-                                               currente->f2 |= 2;
-                                               currente->v1->f |= 2; // xxxx
-                                               currente->v2->f |= 2;                                   
-                                               side++;
-                                               c=0;
-                                       }
-                                       else lastface=1;
-                               }                               
-                               /*----------END Decisions-----------------------------*/
-                               
-                       }
-                       /*-----END Limit the Search----- */
-                       
-                       
-                       /*------------- Preview lines--------------- */
-                       
-                       /* uses callback mechanism to draw it all in current area */
-                       scrarea_do_windraw(curarea);                    
-                       
-                       /* set window matrix to perspective, default an area returns with buttons transform */
-                       persp(PERSP_VIEW);
-                       /* make a copy, for safety */
-                       glPushMatrix();
-                       /* multiply with the object transformation */
-                       mymultmatrix(G.obedit->obmat);
-                       
-                       glColor3ub(255, 255, 0);
-                       
-                       if(mode==LOOP_SELECT){
-                               efa= em->faces.first;
-                               while(efa){
-                                       if(efa->f1 & 8){
-                                               
-                                               if(!(efa->e1->f2 & 8)){
-                                                       glBegin(GL_LINES);                                                      
-                                                       glVertex3fv(efa->e1->v1->co);
-                                                       glVertex3fv(efa->e1->v2->co);
-                                                       glEnd();        
-                                               }
-                                               
-                                               if(!(efa->e2->f2 & 8)){
-                                                       glBegin(GL_LINES);                                                      
-                                                       glVertex3fv(efa->e2->v1->co);
-                                                       glVertex3fv(efa->e2->v2->co);
-                                                       glEnd();        
-                                               }
-                                               
-                                               if(!(efa->e3->f2 & 8)){
-                                                       glBegin(GL_LINES);                                                      
-                                                       glVertex3fv(efa->e3->v1->co);
-                                                       glVertex3fv(efa->e3->v2->co);
-                                                       glEnd();        
-                                               }
-                                               
-                                               if(efa->e4){
-                                                       if(!(efa->e4->f2 & 8)){
-                                                               glBegin(GL_LINES);                                                      
-                                                               glVertex3fv(efa->e4->v1->co);
-                                                               glVertex3fv(efa->e4->v2->co);
-                                                               glEnd();        
-                                                       }
-                                               }
-                                       }
-                                       efa=efa->next;
-                               }
-                       }
-                               
-                       if(mode==LOOP_CUT){
-                               efa= em->faces.first;
-                               while(efa){
-                                       if(efa->f1 & 8){
-                                               float cen[2][3];
-                                               int a=0;                                                
-                                               
-                                               efa->v1->f &= ~8; // xxx
-                                               efa->v2->f &= ~8;
-                                               efa->v3->f &= ~8;
-                                               if(efa->v4)efa->v4->f &= ~8;
-                                       
-                                               if(efa->e1->f2 & 8){
-                                                       cen[a][0]= (efa->e1->v1->co[0] + efa->e1->v2->co[0])/2.0;
-                                                       cen[a][1]= (efa->e1->v1->co[1] + efa->e1->v2->co[1])/2.0;
-                                                       cen[a][2]= (efa->e1->v1->co[2] + efa->e1->v2->co[2])/2.0;
-                                                       
-                                                       efa->e1->v1->f |= 8; // xxx
-                                                       efa->e1->v2->f |= 8;
-                                                       
-                                                       a++;
-                                               }
-                                               if((efa->e2->f2 & 8) && a!=2){
-                                                       cen[a][0]= (efa->e2->v1->co[0] + efa->e2->v2->co[0])/2.0;
-                                                       cen[a][1]= (efa->e2->v1->co[1] + efa->e2->v2->co[1])/2.0;
-                                                       cen[a][2]= (efa->e2->v1->co[2] + efa->e2->v2->co[2])/2.0;
-                                                       
-                                                       efa->e2->v1->f |= 8; // xxx
-                                                       efa->e2->v2->f |= 8;
-                                                       
-                                                       a++;
-                                               }
-                                               if((efa->e3->f2 & 8) && a!=2){
-                                                       cen[a][0]= (efa->e3->v1->co[0] + efa->e3->v2->co[0])/2.0;
-                                                       cen[a][1]= (efa->e3->v1->co[1] + efa->e3->v2->co[1])/2.0;
-                                                       cen[a][2]= (efa->e3->v1->co[2] + efa->e3->v2->co[2])/2.0;
-                                                       
-                                                       efa->e3->v1->f |= 8; // xxx
-                                                       efa->e3->v2->f |= 8;
-                                                       
-                                                       a++;
-                                               }
-                                               
-                                               if(efa->e4){
-                                                       if((efa->e4->f2 & 8) && a!=2){
-                                                               cen[a][0]= (efa->e4->v1->co[0] + efa->e4->v2->co[0])/2.0;
-                                                               cen[a][1]= (efa->e4->v1->co[1] + efa->e4->v2->co[1])/2.0;
-                                                               cen[a][2]= (efa->e4->v1->co[2] + efa->e4->v2->co[2])/2.0;
-                                                               
-                                                               efa->e4->v1->f |= 8; // xxx
-                                                               efa->e4->v2->f |= 8;
-                                                       
-                                                               a++;
-                                                       }
-                                               }
-                                               else{   /* if it's a triangular face, set the remaining vertex as the cutcurve coordinate */                                                                                                            
-                                                               if(!(efa->v1->f & 8) && efa->v1->h==0){ // xxx
-                                                                       cen[a][0]= efa->v1->co[0];
-                                                                       cen[a][1]= efa->v1->co[1];
-                                                                       cen[a][2]= efa->v1->co[2];
-                                                                       a++;                                                            
-                                                               }
-                                                               else if(!(efa->v2->f & 8) && efa->v2->h==0){
-                                                                       cen[a][0]= efa->v2->co[0];
-                                                                       cen[a][1]= efa->v2->co[1];
-                                                                       cen[a][2]= efa->v2->co[2];      
-                                                                       a++;
-                                                               }
-                                                               else if(!(efa->v3->f & 8) && efa->v3->h==0){
-                                                                       cen[a][0]= efa->v3->co[0];
-                                                                       cen[a][1]= efa->v3->co[1];
-                                                                       cen[a][2]= efa->v3->co[2];
-                                                                       a++;                                                                    
-                                                               }                                                       
-                                               }
-                                               
-                                               if(a==2){
-                                                       glBegin(GL_LINES);
-                                                       
-                                                       glVertex3fv(cen[0]);
-                                                       glVertex3fv(cen[1]);    
-                                                                                               
-                                                       glEnd();
-                                               }                                               
-                                       }
-                                       efa=efa->next;
-                               }
-                               
-                               eed=em->edges.first; 
-                               while(eed){
-                                       if(eed->f2 & 64){
-                                               glBegin(GL_LINES);
-                                               glColor3ub(200, 255, 200);
-                                               glVertex3fv(eed->v1->co);
-                                               glVertex3fv(eed->v2->co);
-                                               glEnd();
-                                               eed=0;
-                                       }else{
-                                               eed = eed->next;
-                                       }
-                               }               
-                       }
-                       
-                       /* restore matrix transform */
-                       glPopMatrix();
-                       
-                       headerprint("LMB to confirm, RMB to cancel");
-                       
-                       /* this also verifies other area/windows for clean swap */
-                       screen_swapbuffers();
-                       
-                       /* backbuffer refresh for non-apples (no aux) */
-#ifndef __APPLE__
-                       if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) {
-                               backdrawview3d(0);
-                       }
-#endif
-       
-                       /*--------- END Preview Lines------------*/
-                               
-               }/*if(start!=NULL){ */
-               else PIL_sleep_ms(10);  // idle
-               
-               while(qtest()) {
-                       unsigned short val=0;                   
-                       event= extern_qread(&val);      /* extern_qread stores important events for the mainloop to handle */
-
-                       /* val==0 on key-release event */
-                       if(val && (event==ESCKEY || event==RIGHTMOUSE || event==LEFTMOUSE || event==RETKEY || event == MIDDLEMOUSE)){
-                               searching=0;
-                       }
-               }       
-               
-       }/*while(event!=ESCKEY && event!=RIGHTMOUSE && event!=LEFTMOUSE && event!=RETKEY){*/
-       
-       /*----------Select Loop------------*/
-       if(mode==LOOP_SELECT && start!=NULL && ((event==LEFTMOUSE || event==RETKEY) || event == MIDDLEMOUSE || event == BKEY)){
-                               
-               /* If this is a unmodified select, clear the selection */
-               if(!(G.qual & LR_SHIFTKEY) && !(G.qual & LR_ALTKEY)){
-                       for(efa= em->faces.first;efa;efa=efa->next){
-                               EM_select_face(efa, 0); // and this is correct deselect face            
-                       }
-               }
-               /* Alt was not pressed, so add to the selection */
-               if(!(G.qual & LR_ALTKEY)){
-                       for(efa= em->faces.first;efa;efa=efa->next){
-                               if(efa->f1 & 8){
-                                       EM_select_face(efa, 1); // and this is correct select face
-                               }
-                       }
-               }
-               /* alt was pressed, so subtract from the selection */
-               else
-               {
-                       for(efa= em->faces.first;efa;efa=efa->next){
-                               if(efa->f1 & 8){
-                                       EM_select_face(efa, 0); // this is correct deselect face
-                               }
-                       }
-               }
-       
-       }
-       /*----------END Select Loop------------*/
-       
-       /*----------Cut Loop---------------*/                   
-       if(mode==LOOP_CUT && start!=NULL && (event==LEFTMOUSE || event==RETKEY)){
-               
-               /* count the number of edges in the loop */             
-               for(eed=em->edges.first; eed; eed = eed->next){
-                       if(eed->f2 & 8)
-                               ect++;
-               }               
-               
-               tagged = MEM_mallocN(ect*sizeof(EditEdge*), "tagged");
-               taggedsrch = MEM_mallocN(ect*sizeof(EditEdge*), "taggedsrch");
-               for(i=0;i<ect;i++)
-               {
-                       tagged[i] = NULL;
-                       taggedsrch[i] = NULL;
-               }
-               ect = 0;
-               for(eed=em->edges.first; eed; eed = eed->next){
-                       if(eed->f2 & 8)
-                       {
-                               if(eed->h==0){
-                                       eed->v1->f |= SELECT;
-                                       eed->v2->f |= SELECT;
-                                       eed->f |= SELECT;
-                                       tagged[ect] = eed;
-                                       eed->f2 &= ~(32);
-                                       ect++;
-                               }
-                       }                       
-               }
-               taggedsrch[0] = tagged[0];
-
-               while(timesthrough < 2)
-               {
-                       i=0;
-                       while(i < ect){/*Look at the members of the search array to line up cuts*/
-                               if(taggedsrch[i]==NULL)break;
-                               for(j=0;j<ect;j++){                      /*Look through the list of tagged verts for connected edges*/
-                                       int addededge = 0;
-                                       if(taggedsrch[i]->f2 & 32)        /*If this edgee is marked as flipped, use vert 2*/
-                                               look = taggedsrch[i]->v2;
-                                       else                                                     /*else use vert 1*/
-                                               look = taggedsrch[i]->v1;
-
-                                       if(taggedsrch[i] == tagged[j])
-                                               continue;  /*If we are looking at the same edge, skip it*/
-       
-                                       skip = 0;
-                                       for(k=0;k<ect;k++)      {
-                                               if(taggedsrch[k] == NULL)       /*go to empty part of search list without finding*/
-                                                       break;                                                  
-                                               if(tagged[j] == taggedsrch[k]){         /*We found a match already in the list*/
-                                                       skip = 1;
-                                                       break;
-                                               }
-                                       }
-                                       if(skip)
-                                               continue;
-                                       nextpos = 0;
-                                       if(findedgelist(look,tagged[j]->v2)){
-                                               while(nextpos < ect){ /*Find the first open spot in the search array*/
-                                                       if(taggedsrch[nextpos] == NULL){
-                                                               taggedsrch[nextpos] = tagged[j]; /*put tagged[j] in it*/
-                                                               taggedsrch[nextpos]->f2 |= 32;
-                                                               addededge = 1;
-                                                               break;
-                                                       }
-                                                       else
-                                                               nextpos++;
-                                               }
-                                       } /* End else if connected to vert 2*/
-                                       else if(findedgelist(look,tagged[j]->v1)){   /*If our vert is connected to vert 1 */
-                                               while(nextpos < ect){ /*Find the first open spot in the search array */
-                                                       if(taggedsrch[nextpos] == NULL){
-                                                               taggedsrch[nextpos] = tagged[j]; /*put tagged[j] in it*/
-                                                               addededge = 1;
-                                                               break;
-                                                       }
-                                                       else 
-                                                               nextpos++;
-                                               }
-                                       }
-
-                                       if(addededge)
-                                       {
-                                               break;
-                                       }                                       
-                               }/* End Outer For (j)*/
-                               i++;
-                       } /* End while(j<ect)*/
-                       timesthrough++;
-               } /*end while timesthrough */
-               percentcut = 0.50;
-               searching = 1;
-               cut   = 1;
-               smooth = 0;
-               close = NULL;
-
-
-               /* Count the Number of Faces in the selected loop*/
-               percentfaces = 0;
-               for(efa= em->faces.first; efa ;efa=efa->next){
-                       if(efa->f1 & 8)
-                        {
-                               percentfaces++; 
-                        }
-               }
-                       
-               /* create a dynamic array for those face pointers */
-               percentfacesloop = MEM_mallocN(percentfaces*sizeof(EditFace*), "percentage");
-
-               /* put those faces in the array */
-               i=0;
-               for(efa= em->faces.first; efa ;efa=efa->next){
-                        if(efa->f1 & 8)
-                        {
-                               percentfacesloop[i] = efa;      
-                               i++;
-                        }
-               }
-
-               while(searching){
-                       
-                       /* For the % calculation */
-                       short mval[2];                  
-                       float labda, rc[2], len, slen=0.0;
-                       float v1[2], v2[2], v3[2];
-
-                       /*------------- Percent Cut Preview Lines--------------- */
-                       scrarea_do_windraw(curarea);                    
-                       persp(PERSP_VIEW);
-                       glPushMatrix();
-                       mymultmatrix(G.obedit->obmat);
-                       glColor3ub(0, 255, 255);
-                               
-                       /*Put the preview lines where they should be for the percentage selected.*/
-
-                       for(i=0;i<percentfaces;i++){
-                               efa = percentfacesloop[i];
-                               for(eed = em->edges.first; eed; eed=eed->next){
-                                       if(eed->f2 & 64){       /* color the starting edge */                   
-                                               glBegin(GL_LINES);
-                                                                                               
-                                               glColor3ub(200, 255, 200);
-                                               glVertex3fv(eed->v1->co);                                       
-                                               glVertex3fv(eed->v2->co);
-                                               
-                                               glEnd();
-
-                                               glPointSize(5);
-                                               glBegin(GL_POINTS);
-                                               glColor3ub(255,0,255);
-                                               
-                                               if(eed->f2 & 32)
-                                                       glVertex3fv(eed->v2->co);                       
-                                               else
-                                                       glVertex3fv(eed->v1->co);
-                                               glEnd();
-
-
-                                               /*Get Starting Edge Length*/
-                                               slen = sqrt((eed->v1->co[0]-eed->v2->co[0])*(eed->v1->co[0]-eed->v2->co[0])+
-                                                                       (eed->v1->co[1]-eed->v2->co[1])*(eed->v1->co[1]-eed->v2->co[1])+
-                                                                       (eed->v1->co[2]-eed->v2->co[2])*(eed->v1->co[2]-eed->v2->co[2]));
-                                       }
-                               }
-                               
-                               if(!inset){
-                                       glColor3ub(0,255,255);
-                                       if(efa->f1 & 8)
-                                       {
-                                               float cen[2][3];
-                                               int a=0;                                        
-                                               
-                                               efa->v1->f &= ~8; // xxx
-                                               efa->v2->f &= ~8;
-                                               efa->v3->f &= ~8;
-                                               if(efa->v4)efa->v4->f &= ~8;
-                                               
-                                               if(efa->e1->f2 & 8){
-                                                       float pct;
-                                                       if(efa->e1->f2 & 32)
-                                                               pct = 1-percentcut;
-                                                       else
-                                                               pct = percentcut;
-                                                       cen[a][0]= efa->e1->v1->co[0] - ((efa->e1->v1->co[0] - efa->e1->v2->co[0]) * (pct));
-                                                       cen[a][1]= efa->e1->v1->co[1] - ((efa->e1->v1->co[1] - efa->e1->v2->co[1]) * (pct));
-                                                       cen[a][2]= efa->e1->v1->co[2] - ((efa->e1->v1->co[2] - efa->e1->v2->co[2]) * (pct));
-                                                       efa->e1->v1->f |= 8; // xxx
-                                                       efa->e1->v2->f |= 8;
-                                                       a++;
-                                               }
-                                               if((efa->e2->f2 & 8) && a!=2)
-                                               {
-                                                       float pct;
-                                                       if(efa->e2->f2 & 32)
-                                                               pct = 1-percentcut;
-                                                       else
-                                                               pct = percentcut;
-                                                       cen[a][0]= efa->e2->v1->co[0] - ((efa->e2->v1->co[0] - efa->e2->v2->co[0]) * (pct));
-                                                       cen[a][1]= efa->e2->v1->co[1] - ((efa->e2->v1->co[1] - efa->e2->v2->co[1]) * (pct));
-                                                       cen[a][2]= efa->e2->v1->co[2] - ((efa->e2->v1->co[2] - efa->e2->v2->co[2]) * (pct));
-
-                                                       efa->e2->v1->f |= 8; // xxx
-                                                       efa->e2->v2->f |= 8;
-                                                       
-                                                       a++;
-                                               }
-                                               if((efa->e3->f2 & 8) && a!=2){
-                                                       float pct;
-                                                       if(efa->e3->f2 & 32)
-                                                               pct = 1-percentcut;
-                                                       else
-                                                               pct = percentcut;
-                                                       cen[a][0]= efa->e3->v1->co[0] - ((efa->e3->v1->co[0] - efa->e3->v2->co[0]) * (pct));
-                                                       cen[a][1]= efa->e3->v1->co[1] - ((efa->e3->v1->co[1] - efa->e3->v2->co[1]) * (pct));
-                                                       cen[a][2]= efa->e3->v1->co[2] - ((efa->e3->v1->co[2] - efa->e3->v2->co[2]) * (pct));
-
-                                                       efa->e3->v1->f |= 8; // xxx
-                                                       efa->e3->v2->f |= 8;
-                                                       
-                                                       a++;
-                                               }
-                                                       
-                                               if(efa->e4){
-                                                       if((efa->e4->f2 & 8) && a!=2){
-                                                               float pct;
-                                                               if(efa->e4->f2 & 32)
-                                                                       pct = 1-percentcut;
-                                                               else
-                                                                       pct = percentcut;
-                                                               cen[a][0]= efa->e4->v1->co[0] - ((efa->e4->v1->co[0] - efa->e4->v2->co[0]) * (pct));
-                                                               cen[a][1]= efa->e4->v1->co[1] - ((efa->e4->v1->co[1] - efa->e4->v2->co[1]) * (pct));
-                                                               cen[a][2]= efa->e4->v1->co[2] - ((efa->e4->v1->co[2] - efa->e4->v2->co[2]) * (pct));
-
-                                                               efa->e4->v1->f |= 8; // xxx
-                                                               efa->e4->v2->f |= 8;
-                                                       
-                                                               a++;
-                                                       }
-                                               }
-                                               else {  /* if it's a triangular face, set the remaining vertex as the cutcurve coordinate */
-                                                       if(!(efa->v1->f & 8) && efa->v1->h==0){ // xxx
-                                                               cen[a][0]= efa->v1->co[0];
-                                                               cen[a][1]= efa->v1->co[1];
-                                                               cen[a][2]= efa->v1->co[2];
-                                                               a++;                                                            
-                                                       }
-                                                       else if(!(efa->v2->f & 8) && efa->v2->h==0){ // xxx
-                                                               cen[a][0]= efa->v2->co[0];
-                                                               cen[a][1]= efa->v2->co[1];
-                                                               cen[a][2]= efa->v2->co[2];
-                                                               a++;                                                            
-                                                       }
-                                                       else if(!(efa->v3->f & 8) && efa->v3->h==0){ // xxx
-                                                               cen[a][0]= efa->v3->co[0];
-                                                               cen[a][1]= efa->v3->co[1];
-                                                               cen[a][2]= efa->v3->co[2];
-                                                               a++;                                                                                                    
-                                                       }
-                                               }
-                                               
-                                               if(a==2){
-                                                       glBegin(GL_LINES);
-                                                       
-                                                       glVertex3fv(cen[0]);
-                                                       glVertex3fv(cen[1]);    
-                                                                                               
-                                                       glEnd();
-                                               }       
-                                       }
-                               }/* end preview line drawing */                 
-                               else{
-                                       glColor3ub(0,128,255);
-                                       if(efa->f1 & 8)
-                                       {
-                                               float cen[2][3];
-                                               int a=0;                                        
-                                               
-                                               efa->v1->f &= ~8; // xxx
-                                               efa->v2->f &= ~8;
-                                               efa->v3->f &= ~8;
-                                               if(efa->v4)efa->v4->f &= ~8;
-                                               
-                                               if(efa->e1->f2 & 8){                                                    
-                                                       float nlen,npct;
-                                                       
-                                                       nlen = sqrt((efa->e1->v1->co[0] - efa->e1->v2->co[0])*(efa->e1->v1->co[0] - efa->e1->v2->co[0])+
-                                                                               (efa->e1->v1->co[1] - efa->e1->v2->co[1])*(efa->e1->v1->co[1] - efa->e1->v2->co[1])+
-                                                                               (efa->e1->v1->co[2] - efa->e1->v2->co[2])*(efa->e1->v1->co[2] - efa->e1->v2->co[2]));
-                                                       npct = (percentcut*slen)/nlen;
-                                                       if(npct >= 1) npct = 1;
-                                                       if(efa->e1->f2 & 32)    npct = 1-npct;
-
-                                                       cen[a][0]= efa->e1->v1->co[0] - ((efa->e1->v1->co[0] - efa->e1->v2->co[0]) * (npct));
-                                                       cen[a][1]= efa->e1->v1->co[1] - ((efa->e1->v1->co[1] - efa->e1->v2->co[1]) * (npct));
-                                                       cen[a][2]= efa->e1->v1->co[2] - ((efa->e1->v1->co[2] - efa->e1->v2->co[2]) * (npct));
-
-                                                       efa->e1->f1 = 32768*(npct);
-                                                       efa->e1->v1->f |= 8; // xxx
-                                                       efa->e1->v2->f |= 8;
-                                                       a++;
-                                               }
-                                               if((efa->e2->f2 & 8) && a!=2)
-                                               {
-                                                       float nlen,npct;
-                                                       
-                                                       nlen = sqrt((efa->e2->v1->co[0] - efa->e2->v2->co[0])*(efa->e2->v1->co[0] - efa->e2->v2->co[0])+
-                                                                               (efa->e2->v1->co[1] - efa->e2->v2->co[1])*(efa->e2->v1->co[1] - efa->e2->v2->co[1])+
-                                                                               (efa->e2->v1->co[2] - efa->e2->v2->co[2])*(efa->e2->v1->co[2] - efa->e2->v2->co[2]));
-                                                       npct = (percentcut*slen)/nlen;
-                                                       if(npct >= 1) npct = 1;
-                                                       if(efa->e2->f2 & 32)    npct = 1-npct;
-
-                                                       cen[a][0]= efa->e2->v1->co[0] - ((efa->e2->v1->co[0] - efa->e2->v2->co[0]) * (npct));
-                                                       cen[a][1]= efa->e2->v1->co[1] - ((efa->e2->v1->co[1] - efa->e2->v2->co[1]) * (npct));
-                                                       cen[a][2]= efa->e2->v1->co[2] - ((efa->e2->v1->co[2] - efa->e2->v2->co[2]) * (npct));
-
-                                                       efa->e2->f1 = 32768*(npct);                                                             
-                                                       efa->e2->v1->f |= 8; // xxx
-                                                       efa->e2->v2->f |= 8;
-                                                       a++;
-                                               }
-                                               if((efa->e3->f2 & 8) && a!=2){
-                                                       float nlen,npct;
-                                                       
-                                                       nlen = sqrt((efa->e3->v1->co[0] - efa->e3->v2->co[0])*(efa->e3->v1->co[0] - efa->e3->v2->co[0])+
-                                                                               (efa->e3->v1->co[1] - efa->e3->v2->co[1])*(efa->e3->v1->co[1] - efa->e3->v2->co[1])+
-                                                                               (efa->e3->v1->co[2] - efa->e3->v2->co[2])*(efa->e3->v1->co[2] - efa->e3->v2->co[2]));
-                                                       npct = (percentcut*slen)/nlen;
-                                                       if(npct >= 1) npct = 1;
-                                                       if(efa->e3->f2 & 32)    npct = 1-npct;
-
-                                                       cen[a][0]= efa->e3->v1->co[0] - ((efa->e3->v1->co[0] - efa->e3->v2->co[0]) * (npct));
-                                                       cen[a][1]= efa->e3->v1->co[1] - ((efa->e3->v1->co[1] - efa->e3->v2->co[1]) * (npct));
-                                                       cen[a][2]= efa->e3->v1->co[2] - ((efa->e3->v1->co[2] - efa->e3->v2->co[2]) * (npct));
-
-                                                       efa->e3->f1 = 32768*(npct);                                                             
-                                                       efa->e3->v1->f |= 8; // xxx
-                                                       efa->e3->v2->f |= 8;
-                                                       a++;
-                                               }
-                                                       
-                                               if(efa->e4){
-                                                       if((efa->e4->f2 & 8) && a!=2){
-                                                               float nlen,npct;
-                                                               
-                                                               nlen = sqrt((efa->e4->v1->co[0] - efa->e4->v2->co[0])*(efa->e4->v1->co[0] - efa->e4->v2->co[0])+
-                                                                                       (efa->e4->v1->co[1] - efa->e4->v2->co[1])*(efa->e4->v1->co[1] - efa->e4->v2->co[1])+
-                                                                                       (efa->e4->v1->co[2] - efa->e4->v2->co[2])*(efa->e4->v1->co[2] - efa->e4->v2->co[2]));
-                                                       npct = (percentcut*slen)/nlen;
-                                                       if(npct >= 1) npct = 1;
-                                                       if(efa->e4->f2 & 32)    npct = 1-npct;
-
-                                                               cen[a][0]= efa->e4->v1->co[0] - ((efa->e4->v1->co[0] - efa->e4->v2->co[0]) * (npct));
-                                                               cen[a][1]= efa->e4->v1->co[1] - ((efa->e4->v1->co[1] - efa->e4->v2->co[1]) * (npct));
-                                                               cen[a][2]= efa->e4->v1->co[2] - ((efa->e4->v1->co[2] - efa->e4->v2->co[2]) * (npct));
-
-                                                               efa->e4->f1 = 32768*(npct);                                                                     
-                                                               efa->e4->v1->f |= 8; // xxx
-                                                               efa->e4->v2->f |= 8;
-                                                               a++;
-                                                       }
-                                               }
-                                               else {  /* if it's a triangular face, set the remaining vertex as the cutcurve coordinate */
-                                                       if(!(efa->v1->f & 8) && efa->v1->h==0){ // xxx
-                                                               cen[a][0]= efa->v1->co[0];
-                                                               cen[a][1]= efa->v1->co[1];
-                                                               cen[a][2]= efa->v1->co[2];
-                                                               a++;                                                            
-                                                       }
-                                                       else if(!(efa->v2->f & 8) && efa->v2->h==0){ // xxx
-                                                               cen[a][0]= efa->v2->co[0];
-                                                               cen[a][1]= efa->v2->co[1];
-                                                               cen[a][2]= efa->v2->co[2];
-                                                               a++;                                                            
-                                                       }
-                                                       else if(!(efa->v3->f & 8) && efa->v3->h==0){ // xxx
-                                                               cen[a][0]= efa->v3->co[0];
-                                                               cen[a][1]= efa->v3->co[1];
-                                                               cen[a][2]= efa->v3->co[2];
-                                                               a++;                                                                                                    
-                                                       }
-                                               }
-                                               
-                                               if(a==2){
-                                                       glBegin(GL_LINES);
-                                                       
-                                                       glVertex3fv(cen[0]);
-                                                       glVertex3fv(cen[1]);    
-                                                                                               
-                                                       glEnd();
-                                               }       
-                                       }
-                               }
-                       }
-                       /* restore matrix transform */
-       
-                       glPopMatrix();
-
-                       /*--------- END Preview Lines------------*/
-                       while(qtest()) 
-                       {
-                               unsigned short val=0;                   
-                               event= extern_qread(&val);      /* extern_qread stores important events for the mainloop to handle */
-                               /* val==0 on key-release event */
-               
-                               if(val && (event==SKEY))
-                               {
-                                       if(smooth)smooth = 0;
-                                       else smooth = 1;
-                               }
-
-                               if(val && (event==PKEY))
-                               {
-                                       if(inset)inset = 0;
-                                       else inset = 1;
-                               }
-
-                               if(val && (event==FKEY))
-                               {
-                                               int ct;
-                                               for(ct = 0; ct < ect; ct++){
-                                                       if(tagged[ct]->f2 & 32) 
-                                                               tagged[ct]->f2 &= ~32;
-                                                       else
-                                                               tagged[ct]->f2 |= 32;
-                                               }
-                               }
-
-                               if(val && (event == MIDDLEMOUSE))
-                               {
-                                       cut = 2;
-                                       searching=0;
-                               }
-                               else if(val && (event==LEFTMOUSE || event==RETKEY))
-                               {
-                                       searching=0;
-                               }
-
-                               if(val && (event==ESCKEY || event==RIGHTMOUSE ))
-                               {
-                                       searching=0;
-                                       cut = 0;
-                               }
-                               
-                       }                       
-                       
-                       /* window coords, no clip with vertices f2 flags set (not used) */
-                       calc_meshverts_ext_f2();
-
-
-                       /* Determine the % on wich the loop should be cut */
-                       getmouseco_areawin(mval);                       
-                       v1[0]=(float)mval[0];
-                       v1[1]=(float)mval[1];
-                       
-                       v2[0]=(float)start->v1->xs;
-                       v2[1]=(float)start->v1->ys;
-                       
-                       v3[0]=(float)start->v2->xs;
-                       v3[1]=(float)start->v2->ys;
-                       
-                       rc[0]= v3[0]-v2[0];
-                       rc[1]= v3[1]-v2[1];
-                       len= rc[0]*rc[0]+ rc[1]*rc[1];
-                               
-                       labda= ( rc[0]*(v1[0]-v2[0]) + rc[1]*(v1[1]-v2[1]) )/len;
-
-
-                       if(labda<=0.0) labda=0.0;
-                       else if(labda>=1.0)labda=1.0;
-                                               
-                       percentcut=labda;               
-                       
-                       if(start->f2 & 32)
-                               percentcut = 1.0-percentcut;
-
-               if(cut == 2){
-                       percentcut = 0.5;
-               }
-
-               if (G.qual & LR_SHIFTKEY){
-
-                       percentcut = (int)(percentcut*100.0)/100.0;     
-               }
-               else if (G.qual & LR_CTRLKEY)
-                       percentcut = (int)(percentcut*10.0)/10.0;               
-       
-               outcut = (percentcut*100.0);
-
-               /* Build the Header Line */ 
-
-               if(inset)
-                       sprintf(mesg,"Cut: %0.2f%% ",slen*percentcut);
-               else
-                       sprintf(mesg,"Cut: %0.2f%% ",outcut);
-               
-
-               if(smooth)
-                       sprintf(mesg,"%s| (f)lip side | (s)mooth on  |",mesg);
-               else
-                       sprintf(mesg,"%s| (f)lip side | (s)mooth off |",mesg);
-
-               if(inset)
-                       sprintf(mesg,"%s (p)roportional on ",mesg);
-               else
-                       sprintf(mesg,"%s (p)roportional off",mesg);
-               
-               headerprint(mesg);
-
-               screen_swapbuffers();           
-       }                       
-       
-       if(cut){
-               /* Now that we have selected a cut %, mark the edges for cutting. */
-               if(!inset){
-
-                       for(eed = em->edges.first; eed; eed=eed->next){
-                               if(percentcut == 1.0)
-                                       percentcut = 0.9999;
-                               else if(percentcut == 0.0)
-                                       percentcut = 0.0001;
-                               if(eed->f2 & 8){
-                                       if(eed->f2 & 32)/* Need to offset by a const. (0.5/32768) for consistant roundoff */
-                                               eed->f1 = 32768*(1.0-percentcut - 0.0000153);
-                                       else
-                                               eed->f1 = 32768*(percentcut + 0.0000153);
-                               }
-                       }
-               }
-       /*-------------------------------------*/
-
-                       if(smooth)
-                               subdivideflag(8, 0, B_KNIFE | B_PERCENTSUBD | B_SMOOTH); /* B_KNIFE tells subdivide that edgeflags are already set */
-                       else
-                               subdivideflag(8, 0, B_KNIFE | B_PERCENTSUBD); /* B_KNIFE tells subdivide that edgeflags are already set */
-                       
-                       for(eed = em->edges.first; eed; eed=eed->next){                                                 
-                               if(eed->v1->f & 16) eed->v1->f |= SELECT; //
-                               else eed->v1->f &= ~SELECT;
-                               
-                               if(eed->v2->f & 16) eed->v2->f |= SELECT;
-                               else eed->v2->f &= ~SELECT;
-                               
-                               /* proper edge select state, needed because subdivide still doesnt do it OK */
-                               if(eed->v1->f & eed->v2->f & SELECT) eed->f |= SELECT;
-                               else eed->f &= ~SELECT;
-                       }                       
-               }
-       }
-       /*----------END Cut Loop-----------------------------*/
-
-       
-
-       /* Clear flags */               
-       for(eed = em->edges.first; eed; eed=eed->next){ 
-               eed->f2 &= ~(2|4|8|32|64);
-               eed->v1->f &= ~(2|16); // xxx
-               eed->v2->f &= ~(2|16);          
-       }
-       
-       for(efa= em->faces.first; efa; efa=efa->next){
-               efa->f1 &= ~(4|8);
-
-               /* proper face select state, needed because subdivide still doesnt do it OK */
-               if( faceselectedAND(efa, SELECT) ) efa->f |= SELECT;
-               else efa->f &= ~SELECT;
-       }
-       
-       // flushes vertex -> edge -> face selection
-       EM_select_flush();
-       
-       countall();
-
-       if(tagged)
-               MEM_freeN(tagged);
-       if(taggedsrch)
-               MEM_freeN(taggedsrch);
-       if(percentfacesloop)
-               MEM_freeN(percentfacesloop);
-       
-       /* send event to redraw this window, does header too */ 
-       SetBlenderCursor(SYSCURSOR);
-       addqueue(curarea->win, REDRAW, 1); 
-
-       /* should have check for cancelled (ton) */
-       if(mode==LOOP_CUT) BIF_undo_push("Face Loop Subdivide");
-       else if(mode==LOOP_SELECT) BIF_undo_push("Select Face Loop");   
-
-}
-
-/* ****************************** END LOOPOPERATIONS ********************** */
-
 void LoopMenu(){ /* Called by KKey */
 
        short ret;
        
-       ret=pupmenu("Loop/Cut Menu %t|Face Loop Select %x1|Face Loop Cut %x2|"
-                               "Knife (Exact) %x3|Knife (Midpoints)%x4|");
+       ret=pupmenu("Loop/Cut Menu %t|Loop Cut (CTRL-R)%x2|"
+                               "Knife (Exact) %x3|Knife (Midpoints)%x4|Knife (Multicut)%x5");
                                
        switch (ret){
-               case 1:
-                       loopoperations(LOOP_SELECT);
-                       break;
                case 2:
-                       loopoperations(LOOP_CUT);
+                       CutEdgeloop(1);
                        break;
                case 3: 
                        KnifeSubdivide(KNIFE_EXACT);
                        break;
                case 4:
                        KnifeSubdivide(KNIFE_MIDPOINT);
+                       break;
+               case 5:
+                       KnifeSubdivide(KNIFE_MULTICUT);
+                       break;
        }
 
 }
index 8229f55449f76e090761bf1eb7540f9264fd337b..e09748cf2ccb6b6ae5a2a181544e6192c2c9fc10 100644 (file)
@@ -974,6 +974,74 @@ static void edgeloop_select(EditEdge *starteed, int select)
        }
 }
 
+/* 
+   Almostly exactly the same code as faceloop select
+*/
+static void edgering_select(EditEdge *startedge, int select){
+       EditMesh *em = G.editMesh;
+       EditEdge *eed;
+       EditFace *efa;
+       int looking= 1;
+       
+       /* in eed->f1 we put the valence (amount of faces in edge) */
+       /* in eed->f2 we put tagged flag as correct loop */
+       /* in efa->f1 we put tagged flag as correct to select */
+
+       for(eed= em->edges.first; eed; eed= eed->next) {
+               eed->f1= 0;
+               eed->f2= 0;
+       }
+       for(efa= em->faces.first; efa; efa= efa->next) {
+               efa->f1= 0;
+               if(efa->h==0) {
+                       efa->e1->f1++;
+                       efa->e2->f1++;
+                       efa->e3->f1++;
+                       if(efa->e4) efa->e4->f1++;
+               }
+       }
+       
+       // tag startedge OK
+       startedge->f2= 1;
+       
+       while(looking) {
+               looking= 0;
+               
+               for(efa= em->faces.first; efa; efa= efa->next) {
+                       if(efa->e4 && efa->f1==0) {     // not done quad
+                               if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { // valence ok
+
+                                       // if edge tagged, select opposing edge and mark face ok
+                                       if(efa->e1->f2) {
+                                               efa->e3->f2= 1;
+                                               efa->f1= 1;
+                                               looking= 1;
+                                       }
+                                       else if(efa->e2->f2) {
+                                               efa->e4->f2= 1;
+                                               efa->f1= 1;
+                                               looking= 1;
+                                       }
+                                       if(efa->e3->f2) {
+                                               efa->e1->f2= 1;
+                                               efa->f1= 1;
+                                               looking= 1;
+                                       }
+                                       if(efa->e4->f2) {
+                                               efa->e2->f2= 1;
+                                               efa->f1= 1;
+                                               looking= 1;
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       /* (de)select the edges */
+       for(eed= em->edges.first; eed; eed= eed->next) {
+               if(eed->f2) EM_select_edge(eed, select);
+       }
+}
 /* ***************** MAIN MOUSE SELECTION ************** */
 
 // just to have the functions nice together
@@ -993,8 +1061,14 @@ static void mouse_mesh_loop(void)
                if(G.scene->selectmode & SCE_SELECT_FACE) {
                        faceloop_select(eed, eed->f & SELECT);
                }
-               else {
-                       edgeloop_select(eed, eed->f & SELECT);
+               else if(G.scene->selectmode & SCE_SELECT_EDGE) {
+            if(G.qual == (LR_CTRLKEY | LR_ALTKEY) || G.qual == (LR_CTRLKEY | LR_ALTKEY |LR_SHIFTKEY))
+                       edgering_select(eed, eed->f & SELECT);
+            else if(G.qual & LR_ALTKEY)
+                       edgeloop_select(eed, eed->f & SELECT);
+               }
+        else if(G.scene->selectmode & SCE_SELECT_VERTEX) {
+            edgeloop_select(eed, eed->f & SELECT);
                }
 
                /* frontbuffer draw of last selected only */
@@ -1696,7 +1770,7 @@ void editmesh_mark_seam(int clear)
 void Edge_Menu() {
        short ret;
 
-       ret= pupmenu("Edge Specials%t|Mark Seam %x1|Clear Seam %x2|Rotate Edge CW%x3|Rotate Edge CCW%x4");
+       ret= pupmenu("Edge Specials%t|Mark Seam %x1|Clear Seam %x2|Rotate Edge CW%x3|Rotate Edge CCW%x4|Loopcut%x6|Edge Slide%x5");
 
        switch(ret)
        {
@@ -1712,6 +1786,14 @@ void Edge_Menu() {
        case 4:
                edge_rotate_selected(1);
                break;
+       case 5:
+               EdgeSlide(0,0.0);
+       BIF_undo_push("EdgeSlide");
+               break;
+       case 6:
+        CutEdgeloop(1);
+               BIF_undo_push("Loopcut New");
+               break;
        }
 }
 
index 0f836e5f92fd3fdb31c10e15ca69d760cd8be99c..142678e136967c8dc68cf15939cf5f36840749e6 100644 (file)
@@ -25,7 +25,7 @@
  *
  * The Original Code is: all of this file.
  *
- * Contributor(s): none yet.
+ * Contributor(s): Johnny Matthews.
  *
  * ***** END GPL/BL DUAL LICENSE BLOCK *****
  */
@@ -46,7 +46,7 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise
 
 #include "MEM_guardedalloc.h"
 
-
+#include "BMF_Api.h"
 #include "DNA_mesh_types.h"
 #include "DNA_material_types.h"
 #include "DNA_meshdata_types.h"
@@ -59,6 +59,8 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise
 #include "BLI_arithb.h"
 #include "BLI_editVert.h"
 #include "BLI_rand.h"
+#include "BLI_ghash.h"
+#include "BLI_linklist.h"
 
 #include "BKE_depsgraph.h"
 #include "BKE_global.h"
@@ -90,11 +92,12 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise
 
 #include "editmesh.h"
 
+#include "MTC_vectorops.h"
 
 /* local prototypes ---------------*/
 void bevel_menu(void);
-
-
+static void free_tagged_edgelist(EditEdge *eed);
+static void free_tagged_facelist(EditFace *efa);
 /********* qsort routines *********/
 
 
@@ -1098,2764 +1101,4227 @@ void fill_mesh(void)
        BIF_undo_push("Fill");
 }
 
+/*--------------Edge Based Subdivide------------------*/
+#define EDGENEW    2
+#define EDGEINNER  4
 
+static void alter_co(float* co,EditEdge *edge,float rad,int beauty){
+    float  vec1[3],vec2[3],fac,vec3[3],vec4[4],len,ang;
+    
+       if(rad > 0.0) {   /* subdivide sphere */
+               Normalise(co);
+               co[0]*= rad;
+               co[1]*= rad;
+               co[2]*= rad;
+       }
+       else if(rad< 0.0) {  /* fractal subdivide */
+               fac= rad* VecLenf(edge->v1->co, edge->v2->co);
+               vec1[0]= fac*(float)(0.5-BLI_drand());
+               vec1[1]= fac*(float)(0.5-BLI_drand());
+               vec1[2]= fac*(float)(0.5-BLI_drand());
+               VecAddf(co, co, vec1);
+       }
 
-/* ******************** SUBDIVIDE ********************************** */
+       if(beauty & B_SMOOTH) {         
+        // We are using the 2 ends of the edge vertex normals to 
+        // determine the arc for the smooth 
+
+        // This figures our smooth radius for this edge
+        ang = acos(MTC_dot3Float(edge->v1->no,edge->v2->no))/2;      
+        len = VecLenf(edge->v1->co,edge->v2->co)/2;
+        rad = len/sin(ang);
+        
+        // Now find the centerpoint of the smooth radius
+        // Need to calculate and add the offset. 
+        //
+        //  L1 = v1->co  +  a  v1->no
+        //  L2 = v2->co  +  b  v2->no
+        //
+        //  Assume they intersect
+        //
+        //  Set equal
+        //
+        //  v1->co + a v1->no = v2->co + b v2->no
+        //
+        //  a v1->no = (v2->co - v1->co) + b v2->no
+        //
+        //  Cross v2->no with both sides
+        //
+        //  a (v1->no X v2->no) = (v2->co - v1->co) X v2->no
+        //  a (vec1)            = vec2 X v2->no       
+        //  a vec1              = vec3
+        //  a                   = length(vec3) / length(vec1)
+        //
+        //  Now plug a into L1 = v1->co + a v1->no, this is intersection
+        
+        Crossf(vec1,edge->v1->no,edge->v2->no);
+        VecSubf(vec2,edge->v2->co,edge->v1->co);
+        Crossf(vec3,vec2,edge->v2->no);
+        len = VecLength(vec3)/VecLength(vec1);
+    
+        VECCOPY(vec4,edge->v1->no);  
+        VecMulf(vec4,len);
+        VecAddf(vec1,edge->v1->co,vec4);
 
+        // vec1 *should* be the smooth center offset.
 
-static void merge_weights(EditVert * vt, EditVert *vs )
-{
-       MDeformWeight *newdw;
-       int i,j,done;
-       for (j=0; j<vs->totweight; j++){
-               done=0;
-               /* Is vertex memeber of group */
-               /* If so: Change its weight */
-               for (i=0; i<vt->totweight; i++){
-                       if (vt->dw[i].def_nr == vs->dw[j].def_nr)
-                       {   /* taking the maximum makes it independant from order of occurance */
-                               if (vt->dw[i].weight < vs->dw[j].weight) vt->dw[i].weight = vs->dw[j].weight;
-                               done=1;
-                               break;
-                       }
-               }
-               /* If not: Add the group and set its weight */
-               if (!done){
-                       newdw = MEM_callocN (sizeof(MDeformWeight)*(vt->totweight+1), "deformWeight");
-                       if (vt->dw){
-                               memcpy (newdw, vt->dw, sizeof(MDeformWeight)*vt->totweight);
-                               MEM_freeN (vt->dw);
-                       }
-                       vt->dw=newdw;
-                       vt->dw[vt->totweight].weight=vs->dw[j].weight;
-                       vt->dw[vt->totweight].def_nr=vs->dw[j].def_nr;
-                       vt->totweight++;
-               }
-       }
+        //VecSubf(co,co,vec1);
+        
+               Normalise(co);
+               
+        co[0]*= rad;
+               co[1]*= rad;
+               co[2]*= rad;
+               
+               //VecAddf(co,co,vec1);
+       }    
 }
 
-
-static void set_weights(EditVert * vt, EditVert *vs1,EditVert *vs2,EditVert *vs3,EditVert *vs4 )
-{
-/*
-vt is a new generated vertex with empty deform group information
-vs1..v4 are egde neighbours holding group information
-so let the information ooze into the new one
-*/
-       if (vs1) merge_weights(vt,vs1);
-       if (vs2) merge_weights(vt,vs2);
-       if (vs3) merge_weights(vt,vs3);
-       if (vs4) merge_weights(vt,vs4);
+static void flipvertarray(EditVert** arr, short size){
+    EditVert *hold;
+    int i;
+    
+    for(i=0;i<size/2;i++){
+        hold = arr[i];
+        arr[i] = arr[size-i-1];
+        arr[size-i-1] = hold;   
+    }
 }
 
+static void set_uv_vcol(EditFace *efa, float *co, float *uv, char *col)
+{ 
+    EditVert *v1,*v2,*v3,*v4;
+    float xn, yn, zn;
+    float t00, t01, t10, t11;
+    float detsh, u, v, l;
+    int fac;
+    short i, j;
+    char *cp0, *cp1, *cp2;
+    
+    /* define best projection of face XY, XZ or YZ */
+    xn= fabs(efa->n[0]);
+    yn= fabs(efa->n[1]);
+    zn= fabs(efa->n[2]);
+    if(zn>=xn && zn>=yn) {i= 0; j= 1;}
+    else if(yn>=xn && yn>=zn) {i= 0; j= 2;}
+    else {i= 1; j= 2;} 
+    
+    /* calculate u and v */
+    v1= efa->v1;
+    v2= efa->v2;
+    v3= efa->v3;
+        
+    t00= v3->co[i]-v1->co[i]; t01= v3->co[j]-v1->co[j];
+    t10= v3->co[i]-v2->co[i]; t11= v3->co[j]-v2->co[j];
+        
+    detsh= 1.0/(t00*t11-t10*t01);    /* potential danger */
+    t00*= detsh; t01*=detsh;
+    t10*=detsh; t11*=detsh;
+        
+    u= (co[i]-v3->co[i])*t11-(co[j]-v3->co[j])*t10;
+    v= (co[j]-v3->co[j])*t00-(co[i]-v3->co[i])*t01; 
+    
+    /* btw; u and v range from -1 to 0 */
+        
+    /* interpolate */
+    l= 1.0+u+v;
+        
+        /* outside triangle? */
+    if(efa->v4 && l < 0.0) {
+        /* do it all over, but now with vertex 2 replaced with 4 */
+        
+        /* calculate u and v */
+        v1= efa->v1;
+        v4= efa->v4;
+        v3= efa->v3;
+                
+        t00= v3->co[i]-v1->co[i]; t01= v3->co[j]-v1->co[j];
+        t10= v3->co[i]-v4->co[i]; t11= v3->co[j]-v4->co[j];
+                
+        detsh= 1.0/(t00*t11-t10*t01);    /* potential danger */
+        t00*= detsh; t01*=detsh;
+        t10*=detsh; t11*=detsh;
+                
+        u= (co[i]-v3->co[i])*t11-(co[j]-v3->co[j])*t10;
+        v= (co[j]-v3->co[j])*t00-(co[i]-v3->co[i])*t01; 
+        
+        /* btw; u and v range from -1 to 0 */
+                
+        /* interpolate */
+        l= 1.0+u+v;
+        uv[0] = (l*efa->tf.uv[2][0] - u*efa->tf.uv[0][0] - v*efa->tf.uv[3][0]);
+        uv[1] = (l*efa->tf.uv[2][1] - u*efa->tf.uv[0][1] - v*efa->tf.uv[3][1]);
+
+        cp0= &(efa->tf.col[0]);
+        cp1= &(efa->tf.col[3]);
+        cp2= &(efa->tf.col[2]);
+        
+        for(i=0; i<4; i++) {
+                fac= (int)(l*cp2[i] - u*cp0[i] - v*cp1[i]);
+                col[i]= CLAMPIS(fac, 0, 255);
+        }              
+    } else {            
+        //new = l*vertex3_val - u*vertex1_val - v*vertex2_val;
+        uv[0] = (l*efa->tf.uv[2][0] - u*efa->tf.uv[0][0] - v*efa->tf.uv[1][0]);
+        uv[1] = (l*efa->tf.uv[2][1] - u*efa->tf.uv[0][1] - v*efa->tf.uv[1][1]);
+
+        cp0= &(efa->tf.col[0]);
+        cp1= &(efa->tf.col[1]);
+        cp2= &(efa->tf.col[2]);
+        
+        for(i=0; i<4; i++) {
+                fac= (int)(l*cp2[i] - u*cp0[i] - v*cp1[i]);
+                col[i]= CLAMPIS(fac, 0, 255);
+        }                       
+    }
+} 
 
+static void facecopy(EditFace *source,EditFace *target){
+    
+    set_uv_vcol(source,target->v1->co,target->tf.uv[0],(char*)target->tf.col);
+    set_uv_vcol(source,target->v2->co,target->tf.uv[1],(char*)target->tf.col+1);
+    set_uv_vcol(source,target->v3->co,target->tf.uv[2],(char*)target->tf.col+2);
+    if(target->v4){
+        set_uv_vcol(source,target->v4->co,target->tf.uv[3],target->tf.col+3);
+    }
 
-
-static unsigned int cpack_fact(unsigned int col1, unsigned int col2, float fact)
-{
-       char *cp1, *cp2, *cp;
-       unsigned int col=0;
-       float facti;
-       
-       facti=1-fact; /*result is (1-fact) * col1 and fact * col2 */
-               
-       cp1= (char *)&col1;
-       cp2= (char *)&col2;
-       cp=  (char *)&col;
-       
-       cp[0]= (char)(facti*cp1[0]+fact*cp2[0]);
-       cp[1]= (char)(facti*cp1[1]+fact*cp2[1]);
-       cp[2]= (char)(facti*cp1[2]+fact*cp2[2]);
-       cp[3]= (char)(facti*cp1[3]+fact*cp2[3]);
-       
-       return col;
+       target->mat_nr     = source->mat_nr;
+       target->tf.flag    = source->tf.flag;
+       target->tf.transp  = source->tf.transp;
+       target->tf.mode    = source->tf.mode;
+       target->tf.tile    = source->tf.tile;
+       target->tf.unwrap  = source->tf.unwrap;
+       target->tf.tpage   = source->tf.tpage;
+       target->flag       = source->flag;    
+    
 }
 
+static void fill_quad_single(EditFace *efa, struct GHash *gh, int numcuts){
+       EditEdge *cedge;
+       EditVert *v[4], **verts;
+       EditFace *hold;
+       short start, end, left, right, vertsize,i;   
+                                
+       v[0] = efa->v1;
+       v[1] = efa->v2;
+       v[2] = efa->v3;
+       v[3] = efa->v4;     
+       
+       if(efa->e1->f & SELECT)      { cedge = efa->e1; start = 0;}
+       else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}       
+       else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}       
+       else if(efa->e4->f & SELECT) { cedge = efa->e4; start = 3;}         
+       // Point verts to the array of new verts for cedge
+       verts = BLI_ghash_lookup(gh, cedge);
+       //This is the index size of the verts array
+       vertsize = numcuts+2;
+       
+       // Is the original v1 the same as the first vert on the selected edge?
+       // if not, the edge is running the opposite direction in this face so flip
+       // the array to the correct direction
+       
+       if(verts[0] != v[start]){flipvertarray(verts,numcuts+2);}
+           end    = (start+1)%4;
+           left   = (start+2)%4;
+           right  = (start+3)%4; 
+               
+       /*
+       We should have something like this now
+       
+                  end         start                 
+                   3   2   1   0   
+                   |---*---*---|
+                   |           |
+                   |           |       
+                   |           |
+                   -------------       
+                  left       right
+
+        where start,end,left, right are indexes of EditFace->v1, etc (stored in v)
+        and 0,1,2... are the indexes of the new verts stored in verts
+        
+        We will fill this case like this or this depending on even or odd cuts
+         
+                   |---*---*---|          |---*---|
+                   |  /     \  |          |  / \  |
+                   | /       \ |          | /   \ |     
+                   |/         \|          |/     \|
+                   -------------          ---------  
+       */
+    
+        // Make center face
+        if(vertsize % 2 == 0){
+                hold = addfacelist(verts[(vertsize-1)/2],verts[((vertsize-1)/2)+1],v[left],v[right], NULL,NULL);
+        }else{
+                hold = addfacelist(verts[(vertsize-1)/2],v[left],v[right],NULL, NULL,NULL);            
+        }
+        facecopy(efa,hold);
+        
+        // Make side faces
+        for(i=0;i<(vertsize-1)/2;i++){
+                hold = addfacelist(verts[i],verts[i+1],v[right],NULL,NULL,NULL);  
+                facecopy(efa,hold);
+                hold = addfacelist(verts[vertsize-2-i],verts[vertsize-1-i],v[left],NULL,NULL,NULL); 
+                facecopy(efa,hold);
+        }      
+}
 
-static void uv_half(float *uv, float *uv1, float *uv2)
-{
-       uv[0]= (uv1[0]+uv2[0])/2.0f;
-       uv[1]= (uv1[1]+uv2[1])/2.0f;
-       
+static void fill_tri_single(EditFace *efa, struct GHash *gh, int numcuts){
+       EditEdge *cedge;
+       EditVert *v[3], **verts;
+       EditFace *hold;
+       short start, end, op, vertsize,i;   
+                                
+       v[0] = efa->v1;
+       v[1] = efa->v2;
+       v[2] = efa->v3;    
+       
+       if(efa->e1->f & SELECT)      { cedge = efa->e1; start = 0;}
+       else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}       
+       else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}         
+       // Point verts to the array of new verts for cedge
+       verts = BLI_ghash_lookup(gh, cedge);
+       //This is the index size of the verts array
+       vertsize = numcuts+2;
+       
+       // Is the original v1 the same as the first vert on the selected edge?
+       // if not, the edge is running the opposite direction in this face so flip
+       // the array to the correct direction
+       
+       if(verts[0] != v[start]){flipvertarray(verts,numcuts+2);}
+           end    = (start+1)%3;
+           op     = (start+2)%3;
+               
+       /*
+       We should have something like this now
+       
+                  end         start                 
+                   3   2   1   0   
+                   |---*---*---|
+                   \           |
+                     \         |       
+                       \       |
+                         \     |
+                           \   |
+                             \ |
+                               |op
+                               
+        where start,end,op are indexes of EditFace->v1, etc (stored in v)
+        and 0,1,2... are the indexes of the new verts stored in verts
+        
+        We will fill this case like this or this depending on even or odd cuts
+         
+                   3   2   1   0   
+                   |---*---*---|
+                   \    \  \   |
+                     \    \ \  |       
+                       \   \ \ |
+                         \  \ \|
+                           \ \\|
+                             \ |
+                               |op
+       */
+        
+        // Make side faces
+        for(i=0;i<(vertsize-1);i++){
+                hold = addfacelist(verts[i],verts[i+1],v[op],NULL,NULL,NULL);  
+                facecopy(efa,hold);
+        }      
 }
 
-static void uv_fact(float *uv, float *uv1, float *uv2, float fact)
-{
-       float facti = 1.0f - fact;
-       uv[0] = facti * uv1[0] + fact * uv2[0];
-       uv[1] = facti * uv1[1] + fact * uv2[1];
+static void fill_quad_double_op(EditFace *efa, struct GHash *gh, int numcuts){
+       EditEdge *cedge[2];
+       EditVert *v[4], **verts[2];
+       EditFace *hold;
+       short start, end, left, right, vertsize,i;
+                                
+       v[0] = efa->v1;
+       v[1] = efa->v2;
+       v[2] = efa->v3;
+       v[3] = efa->v4;     
+       
+       if(efa->e1->f & SELECT)      { cedge[0] = efa->e1;  cedge[1] = efa->e3; start = 0;}
+       else if(efa->e2->f & SELECT)      { cedge[0] = efa->e2;  cedge[1] = efa->e4; start = 1;}
+       // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+       verts[0] = BLI_ghash_lookup(gh, cedge[0]);
+       verts[1] = BLI_ghash_lookup(gh, cedge[1]);
+       //This is the index size of the verts array
+       vertsize = numcuts+2;
+       
+       // Is the original v1 the same as the first vert on the selected edge?
+       // if not, the edge is running the opposite direction in this face so flip
+       // the array to the correct direction
+       
+       if(verts[0][0] != v[start]){flipvertarray(verts[0],numcuts+2);}
+           end    = (start+1)%4;
+           left   = (start+2)%4;
+           right  = (start+3)%4; 
+       if(verts[1][0] != v[left]){flipvertarray(verts[1],numcuts+2);}    
+       /*
+       We should have something like this now
+       
+                  end         start                 
+                   3   2   1   0   
+                   |---*---*---|
+                   |           |
+                   |           |       
+                   |           |
+                   |---*---*---|      
+                   0   1   2   3
+                  left       right
+        
+        We will fill this case like this or this depending on even or odd cuts
+         
+                   |---*---*---|
+                   |   |   |   |
+                   |   |   |   |       
+                   |   |   |   |
+                   |---*---*---| 
+       */
+           
+        // Make side faces
+        for(i=0;i<vertsize-1;i++){
+                hold = addfacelist(verts[0][i],verts[0][i+1],verts[1][vertsize-2-i],verts[1][vertsize-1-i],NULL,NULL);  
+                if(i < vertsize-2){
+                    hold->e2->f2 |= EDGEINNER;
+                }
+                facecopy(efa,hold);
+        }      
 }
 
-static void uv_quart(float *uv, float *uv1)
-{
-       uv[0]= (uv1[0]+uv1[2]+uv1[4]+uv1[6])/4.0f;
-       uv[1]= (uv1[1]+uv1[3]+uv1[5]+uv1[7])/4.0f;
+
+static void fill_quad_double_adj(EditFace *efa, struct GHash *gh, int numcuts){
+       EditEdge *cedge[2];
+       EditVert *v[4], **verts[2];
+       EditFace *hold;
+       short start, start2, vertsize,i;
+                                
+       v[0] = efa->v1;
+       v[1] = efa->v2;
+       v[2] = efa->v3;
+       v[3] = efa->v4;     
+       
+       if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1;  cedge[1] = efa->e2; start = 0; start2 = 1;}
+       if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2;  cedge[1] = efa->e3; start = 1; start2 = 2;}
+       if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3;  cedge[1] = efa->e4; start = 2; start2 = 3;}
+       if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4;  cedge[1] = efa->e1; start = 3; start2 = 0;}
+       // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+       verts[0] = BLI_ghash_lookup(gh, cedge[0]);
+       verts[1] = BLI_ghash_lookup(gh, cedge[1]);
+       //This is the index size of the verts array
+       vertsize = numcuts+2;
+       
+       // Is the original v1 the same as the first vert on the selected edge?
+       // if not, the edge is running the opposite direction in this face so flip
+       // the array to the correct direction
+       
+       if(verts[0][0] != v[start]){flipvertarray(verts[0],numcuts+2);}
+       if(verts[1][0] != v[start2]){flipvertarray(verts[1],numcuts+2);}    
+       /*
+       We should have something like this now
+       
+                   end         start                 
+                    3   2   1   0   
+            start2 0|---*---*---|
+                    |           |
+                   1*           |
+                    |           |
+                   2*           |       
+                    |           |
+             end2  3|-----------|   
+        
+        We will fill this case like this or this depending on even or odd cuts
+                   |---*---*---|
+                   | /   /   / |
+                   *   /   /   |
+                   | /   /     |
+                   *   /       |       
+                   | /         |
+                   |-----------|  
+     */
+
+        // Make outside tris
+        hold = addfacelist(verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);  
+        facecopy(efa,hold);       
+        hold = addfacelist(verts[0][0],verts[1][vertsize-1],v[(start2+2)%4],NULL,NULL,NULL);  
+        facecopy(efa,hold);               
+        // Make side faces
+
+        for(i=0;i<numcuts;i++){
+                hold = addfacelist(verts[0][i],verts[0][i+1],verts[1][vertsize-1-(i+1)],verts[1][vertsize-1-i],NULL,NULL);  
+                facecopy(efa,hold);
+        }      
 }
 
-static void face_pin_vertex(EditFace *efa, EditVert *vertex)
-{
-       if(efa->v1 == vertex) efa->tf.unwrap |= TF_PIN1;
-       else if(efa->v2 == vertex) efa->tf.unwrap |= TF_PIN2;
-       else if(efa->v3 == vertex) efa->tf.unwrap |= TF_PIN3;
-       else if(efa->v4 && vertex && efa->v4 == vertex) efa->tf.unwrap |= TF_PIN4;
+static void fill_tri_double(EditFace *efa, struct GHash *gh, int numcuts){
+       EditEdge *cedge[2];
+       EditVert *v[3], **verts[2];
+       EditFace *hold;
+       short start, start2, vertsize,i;
+                                
+       v[0] = efa->v1;
+       v[1] = efa->v2;
+       v[2] = efa->v3;
+       
+       if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1;  cedge[1] = efa->e2; start = 0; start2 = 1;}
+       if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2;  cedge[1] = efa->e3; start = 1; start2 = 2;}
+       if(efa->e3->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e3;  cedge[1] = efa->e1; start = 2; start2 = 0;}
+       // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+       verts[0] = BLI_ghash_lookup(gh, cedge[0]);
+       verts[1] = BLI_ghash_lookup(gh, cedge[1]);
+       //This is the index size of the verts array
+       vertsize = numcuts+2;
+       
+       // Is the original v1 the same as the first vert on the selected edge?
+       // if not, the edge is running the opposite direction in this face so flip
+       // the array to the correct direction
+       
+       if(verts[0][0] != v[start]){flipvertarray(verts[0],numcuts+2);}
+       if(verts[1][0] != v[start2]){flipvertarray(verts[1],numcuts+2);}    
+       /*
+       We should have something like this now
+       
+                   end         start                 
+                    3   2   1   0   
+            start2 0|---*---*---|
+                    |         /     
+                   1*       /        
+                    |     /         
+                   2*   /                 
+                    | /           
+             end2  3|  
+        
+        We will fill this case like this or this depending on even or odd cuts
+                   |---*---*---|
+                   | /   /   / 
+                   *   /   /   
+                   | /   /     
+                   *   /              
+                   | /         
+                   |
+     */
+
+        // Make outside tri
+        hold = addfacelist(verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);  
+        facecopy(efa,hold);              
+        // Make side faces
+
+        for(i=0;i<numcuts;i++){
+                hold = addfacelist(verts[0][i],verts[0][i+1],verts[1][vertsize-1-(i+1)],verts[1][vertsize-1-i],NULL,NULL);  
+                facecopy(efa,hold);
+        }      
 }
 
-static int vert_offset(EditFace *efa, EditVert *eve)
-{
-       if (efa->v1 == eve)
-               return 0;
-       if (efa->v2 == eve)
-               return 1;
-       if (efa->v3 == eve)
-               return 2;
-       if (efa->v4)
-               if (efa->v4 == eve)
-                       return 3;
-       return -1;
+static void fill_quad_triple(EditFace *efa, struct GHash *gh, int numcuts){
+       EditEdge *cedge[3];
+       EditVert *v[4], **verts[3];
+       EditFace *hold;
+       short start, start2, start3, vertsize, i, repeats;
+                                
+       v[0] = efa->v1;
+       v[1] = efa->v2;
+       v[2] = efa->v3;
+       v[3] = efa->v4;     
+           
+       if(!(efa->e1->f & SELECT)) {
+            cedge[0] = efa->e2;  
+            cedge[1] = efa->e3; 
+            cedge[2] = efa->e4;
+            start = 1;start2 = 2;start3 = 3;   
+       }
+       if(!(efa->e2->f & SELECT)) {
+            cedge[0] = efa->e3;  
+            cedge[1] = efa->e4; 
+            cedge[2] = efa->e1;
+            start = 2;start2 = 3;start3 = 0;   
+       }
+        if(!(efa->e3->f & SELECT)) {
+            cedge[0] = efa->e4;  
+            cedge[1] = efa->e1; 
+            cedge[2] = efa->e2;
+            start = 3;start2 = 0;start3 = 1;   
+       }
+       if(!(efa->e4->f & SELECT)) {
+            cedge[0] = efa->e1;  
+            cedge[1] = efa->e2; 
+            cedge[2] = efa->e3;
+            start = 0;start2 = 1;start3 = 2;   
+       }       
+       // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+       verts[0] = BLI_ghash_lookup(gh, cedge[0]);
+       verts[1] = BLI_ghash_lookup(gh, cedge[1]);
+       verts[2] = BLI_ghash_lookup(gh, cedge[2]);
+       //This is the index size of the verts array
+       vertsize = numcuts+2;
+       
+       // Is the original v1 the same as the first vert on the selected edge?
+       // if not, the edge is running the opposite direction in this face so flip
+       // the array to the correct direction
+       
+       if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
+       if(verts[1][0] != v[start2]){flipvertarray(verts[1],numcuts+2);}  
+       if(verts[2][0] != v[start3]){flipvertarray(verts[2],numcuts+2);}   
+       /*
+       We should have something like this now
+       
+                              start2                 
+                    3   2   1   0   
+            start3 0|---*---*---|3 
+                    |           |
+                   1*           *2
+                    |           |
+                   2*           *1       
+                    |           |
+                   3|-----------|0 start   
+        
+        We will fill this case like this or this depending on even or odd cuts  
+        there are a couple of differences. For odd cuts, there is a tri in the
+        middle as well as 1 quad at the bottom (not including the extra quads
+        for odd cuts > 1          
+        
+        For even cuts, there is a quad in the middle and 2 quads on the bottom
+        
+        they are numbered here for clarity
+        
+        1 outer tris and bottom quads
+        2 inner tri or quad
+        3 repeating quads
+        
+                   |---*---*---*---|
+                   |1/   /  \   \ 1|
+                   |/ 3 /    \  3 \|
+                   *  /    2   \   *
+                   | /          \  |
+                   |/            \ | 
+                   *---------------*
+                   |      3        |
+                   |               |  
+                   *---------------*
+                   |               |
+                   |      1        |                  
+                   |               |
+                   |---------------|
+
+                   |---*---*---*---*---|
+                   | 1/   /     \   \ 1|   
+                   | /   /       \   \ |  
+                   |/ 3 /         \ 3 \|
+                   *   /           \   *
+                   |  /             \  |    
+                   | /       2       \ |   
+                   |/                 \|
+                   *-------------------*
+                   |                   |
+                   |         3         |
+                   |                   | 
+                   *-------------------*
+                   |                   |
+                   |         1         |
+                   |                   | 
+                   *-------------------*
+                   |                   |
+                   |        1          |
+                   |                   | 
+                   |-------------------|
+          
+     */
+
+        // Make outside tris
+        hold = addfacelist(verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);  
+        facecopy(efa,hold);      
+        hold = addfacelist(verts[1][vertsize-2],verts[1][vertsize-1],verts[2][1],NULL,NULL,NULL);  
+        facecopy(efa,hold);              
+        // Make bottom quad
+        hold = addfacelist(verts[0][0],verts[0][1],verts[2][vertsize-2],verts[2][vertsize-1],NULL,NULL);  
+        facecopy(efa,hold);         
+        //If it is even cuts, add the 2nd lower quad
+        if(numcuts % 2 == 0){
+            hold = addfacelist(verts[0][1],verts[0][2],verts[2][vertsize-3],verts[2][vertsize-2],NULL,NULL);  
+            facecopy(efa,hold);         
+            // Also Make inner quad
+            hold = addfacelist(verts[1][numcuts/2],verts[1][(numcuts/2)+1],verts[2][numcuts/2],verts[0][(numcuts/2)+1],NULL,NULL);           
+            facecopy(efa,hold);
+            repeats = (numcuts / 2) -1;
+        } else {
+            // Make inner tri     
+            hold = addfacelist(verts[1][(numcuts/2)+1],verts[2][(numcuts/2)+1],verts[0][(numcuts/2)+1],NULL,NULL,NULL);           
+            facecopy(efa,hold);   
+            repeats = ((numcuts+1) / 2)-1;
+        }
+        
+        // cuts for 1 and 2 do not have the repeating quads
+        if(numcuts < 3){repeats = 0;}
+        for(i=0;i<repeats;i++){
+            //Make side repeating Quads
+            hold = addfacelist(verts[1][i+1],verts[1][i+2],verts[0][vertsize-i-3],verts[0][vertsize-i-2],NULL,NULL);           
+            facecopy(efa,hold);               
+            hold = addfacelist(verts[1][vertsize-i-3],verts[1][vertsize-i-2],verts[2][i+1],verts[2][i+2],NULL,NULL);           
+            facecopy(efa,hold); 
+        }
+        // Do repeating bottom quads 
+        for(i=0;i<repeats;i++){
+            if(numcuts % 2 == 1){     
+                hold = addfacelist(verts[0][1+i],verts[0][2+i],verts[2][vertsize-3-i],verts[2][vertsize-2-i],NULL,NULL);  
+            } else {
+                hold = addfacelist(verts[0][2+i],verts[0][3+i],verts[2][vertsize-4-i],verts[2][vertsize-3-i],NULL,NULL);                  
+            }
+            facecopy(efa,hold);                
+        }    
 }
 
-static void set_wuv(int tot, EditFace *efa, int v1, int v2, int v3, int v4, EditFace *efapin)
-{
-       /* this weird function only to be used for subdivide, the 'w' in the name has no meaning! */
-       float *uv, uvo[4][2];
-       unsigned int *col, colo[4], col1, col2;
-       int a, v;
+static void fill_quad_quadruple(EditFace *efa, struct GHash *gh, int numcuts,float rad,int beauty){
+       EditVert **verts[4], ***innerverts;
+       short vertsize, i, j;
+       float co[3];                
+       EditFace *hold;    
+       EditEdge temp;
+       // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+       verts[0] = BLI_ghash_lookup(gh, efa->e1);
+       verts[1] = BLI_ghash_lookup(gh, efa->e2);
+       verts[2] = BLI_ghash_lookup(gh, efa->e3);
+       verts[3] = BLI_ghash_lookup(gh, efa->e4);
+       
+       //This is the index size of the verts array
+       vertsize = numcuts+2;
+       
+       // Is the original v1 the same as the first vert on the selected edge?
+       // if not, the edge is running the opposite direction in this face so flip
+       // the array to the correct direction
+       
+       if(verts[0][0] != efa->v1) {flipvertarray(verts[0],numcuts+2);}
+       if(verts[1][0] != efa->v2) {flipvertarray(verts[1],numcuts+2);}  
+       if(verts[2][0] == efa->v3) {flipvertarray(verts[2],numcuts+2);}
+       if(verts[3][0] == efa->v4) {flipvertarray(verts[3],numcuts+2);}     
+       /*
+       We should have something like this now
+                          1
+                                              
+                    3   2   1   0   
+                   0|---*---*---|0 
+                    |           |
+                   1*           *1
+             2      |           |      4
+                   2*           *2       
+                    |           |
+                   3|---*---*---|3    
+                    3   2   1   0
+        
+                          3
+    // we will fill a 2 dim array of editvert*s to make filling easier
+    //  the innervert order is shown
+
+                0   0---1---2---3 
+                    |   |   |   |
+                1   0---1---2---3 
+                    |   |   |   |
+                2   0---1---2---3        
+                    |   |   |   |
+                3   0---1---2---3  
+          
+     */
+    innerverts = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"quad-quad subdiv inner verts outer array"); 
+    for(i=0;i<numcuts+2;i++){
+          innerverts[i] = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"quad-quad subdiv inner verts inner array");
+    }   
+    // first row is e1 last row is e3
+    for(i=0;i<numcuts+2;i++){
+          innerverts[0][i]          = verts[0][(numcuts+1)-i];
+          innerverts[numcuts+1][i]  = verts[2][(numcuts+1)-i];
+    }           
+    for(i=1;i<=numcuts;i++){
+        innerverts[i][0]          = verts[1][i];
+        innerverts[i][numcuts+1]  = verts[3][i];
+        for(j=1;j<=numcuts;j++){ 
+             co[0] = ((verts[1][i]->co[0] - verts[3][i]->co[0]) * (j /(float)(numcuts+1))) + verts[3][i]->co[0];
+             co[1] = ((verts[1][i]->co[1] - verts[3][i]->co[1]) * (j /(float)(numcuts+1))) + verts[3][i]->co[1];
+             co[2] = ((verts[1][i]->co[2] - verts[3][i]->co[2]) * (j /(float)(numcuts+1))) + verts[3][i]->co[2];          
+
+             temp.v1 = innerverts[i][0];
+             temp.v2 = innerverts[i][numcuts+1];
+           
+             // Call alter co for things like fractal and smooth
+             alter_co(co,&temp,rad,beauty);
+
+             innerverts[i][(numcuts+1)-j] = addvertlist(co); 
+             
+             //VECCOPY(innerverts[i][(numcuts+1)-j]->no,nor);
+             
+        }    
+    }    
+    // Fill with faces
+    for(i=0;i<numcuts+1;i++){
+        for(j=0;j<numcuts+1;j++){
+            hold = addfacelist(innerverts[i][j+1],innerverts[i][j],innerverts[i+1][j],innerverts[i+1][j+1],NULL,NULL);     
+            hold->e1->f2 = EDGENEW;      
+            hold->e2->f2 = EDGENEW;  
+            hold->e3->f2 = EDGENEW;            
+            hold->e4->f2 = EDGENEW;   
+            facecopy(efa,hold);        
+        }        
+    }
+    // Clean up our dynamic multi-dim array
+    for(i=0;i<numcuts+2;i++){
+       MEM_freeN(innerverts[i]);   
+    }    
+    MEM_freeN(innerverts);
+}
 
-       /* recover pinning */
-       if(efapin){
-               efa->tf.unwrap= 0;
-               if(efapin->tf.unwrap & TF_PIN1) face_pin_vertex(efa, efapin->v1);
-               if(efapin->tf.unwrap & TF_PIN2) face_pin_vertex(efa, efapin->v2);
-               if(efapin->tf.unwrap & TF_PIN3) face_pin_vertex(efa, efapin->v3);
-               if(efapin->tf.unwrap & TF_PIN4) face_pin_vertex(efa, efapin->v4);
-       }
+static void fill_tri_triple(EditFace *efa, struct GHash *gh, int numcuts,float rad,int beauty){
+       EditVert **verts[3], ***innerverts;
+       short vertsize, i, j;
+       float co[3];                
+       EditFace *hold;  
+       EditEdge temp;
+       
+       // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+       verts[0] = BLI_ghash_lookup(gh, efa->e1);
+       verts[1] = BLI_ghash_lookup(gh, efa->e2);
+       verts[2] = BLI_ghash_lookup(gh, efa->e3);
+       
+       //This is the index size of the verts array
+       vertsize = numcuts+2;
+       
+       // Is the original v1 the same as the first vert on the selected edge?
+       // if not, the edge is running the opposite direction in this face so flip
+       // the array to the correct direction
+       
+       if(verts[0][0] != efa->v1) {flipvertarray(verts[0],numcuts+2);}
+       if(verts[1][0] != efa->v2) {flipvertarray(verts[1],numcuts+2);}  
+       if(verts[2][0] != efa->v3) {flipvertarray(verts[2],numcuts+2);}   
+       /*
+       We should have something like this now
+                           3
+                                              
+                    3   2   1   0   
+                   0|---*---*---|3 
+                    |          /    
+              1    1*        *2   
+                    |      /      
+                   2*    *1       2         
+                    |  /           
+                   3|/ 
+                     0
+        
+     we will fill a 2 dim array of editvert*s to make filling easier
+
+                            3
+
+                 0  0---1---2---3---4
+                    | / | /  |/  | /    
+                 1  0---1----2---3 
+           1        | /  | / | /    
+                 2  0----1---2     2
+                    |  / |  /       
+                    |/   |/   
+                 3  0---1 
+                    |  /
+                    |/
+                 4  0  
+          
+     */
+    
+    innerverts = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"tri-tri subdiv inner verts outer array"); 
+    for(i=0;i<numcuts+2;i++){
+          innerverts[i] = MEM_mallocN(sizeof(EditVert*)*((numcuts+2)-i),"tri-tri subdiv inner verts inner array");
+    }
+    //top row is e3 backwards
+    for(i=0;i<numcuts+2;i++){
+          innerverts[0][i]          = verts[2][(numcuts+1)-i];
+    }   
+           
+    for(i=1;i<=numcuts+1;i++){
+        //first vert is from e1, last is from e2
+        innerverts[i][0]              = verts[0][i];
+        innerverts[i][(numcuts+1)-i]  = verts[1][(numcuts+1)-i];        
+        for(j=1;j<(numcuts+1)-i;j++){
+             co[0] = ((verts[0][i]->co[0] - verts[1][(numcuts+1)-i]->co[0]) * (j/(float)((numcuts+1)-i))) + verts[1][(numcuts+1)-i]->co[0];
+             co[1] = ((verts[0][i]->co[1] - verts[1][(numcuts+1)-i]->co[1]) * (j/(float)((numcuts+1)-i))) + verts[1][(numcuts+1)-i]->co[1];
+             co[2] = ((verts[0][i]->co[2] - verts[1][(numcuts+1)-i]->co[2]) * (j/(float)((numcuts+1)-i))) + verts[1][(numcuts+1)-i]->co[2];                          
+             
+             temp.v1 = innerverts[i][0];
+             temp.v2 = innerverts[i][(numcuts+1)-i];
+             
+             alter_co(co,&temp,rad,beauty);
+      
+             innerverts[i][((numcuts+1)-i)-j] = addvertlist(co);             
+             //VECCOPY(innerverts[i][((numcuts+1)-i)-j]->no,nor);
+        }
+    }
+    
+   
+    // Now fill the verts with happy little tris :)
+    for(i=0;i<=numcuts+1;i++){
+        for(j=0;j<(numcuts+1)-i;j++){   
+            //We always do the first tri
+            hold = addfacelist(innerverts[i][j+1],innerverts[i][j],innerverts[i+1][j],NULL,NULL,NULL);    
+            hold->e1->f2 = EDGENEW;      
+            hold->e2->f2 = EDGENEW;  
+            hold->e3->f2 = EDGENEW;  
+            facecopy(efa,hold);        
+            //if there are more to come, we do the 2nd     
+            if(j+1 <= numcuts-i){
+                hold = addfacelist(innerverts[i+1][j],innerverts[i+1][j+1],innerverts[i][j+1],NULL,NULL,NULL);           
+                facecopy(efa,hold); 
+                hold->e1->f2 = EDGENEW;      
+                hold->e2->f2 = EDGENEW;  
+                hold->e3->f2 = EDGENEW;  
+           }
+        } 
+    }
+    
+    // Clean up our dynamic multi-dim array
+    for(i=0;i<numcuts+2;i++){
+       MEM_freeN(innerverts[i]);   
+    }    
+    MEM_freeN(innerverts);
+}
 
-       memcpy(uvo, efa->tf.uv, sizeof(uvo));   
-       uv= efa->tf.uv[0];
-       memcpy(colo, efa->tf.col, sizeof(colo));
-       col= efa->tf.col;
+// This function takes an example edge, the current point to create and 
+// the total # of points to create, then creates the point and return the
+// editvert pointer to it.
+static EditVert *subdivideedgenum(EditEdge *edge,int curpoint,int totpoint,float rad,int beauty){
+         float co[3];
+         float percent;
+         EditVert *ev;
+         
+                if (beauty & (B_PERCENTSUBD) && totpoint == 1){
+             percent=(float)(edge->f1)/32768.0f;
+             co[0] = (edge->v2->co[0]-edge->v1->co[0])*percent+edge->v1->co[0];
+             co[1] = (edge->v2->co[1]-edge->v1->co[1])*percent+edge->v1->co[1];
+             co[2] = (edge->v2->co[2]-edge->v1->co[2])*percent+edge->v1->co[2];                    
+         } else {                 
+             co[0] = (edge->v2->co[0]-edge->v1->co[0])*(curpoint/(float)(totpoint+1))+edge->v1->co[0];
+             co[1] = (edge->v2->co[1]-edge->v1->co[1])*(curpoint/(float)(totpoint+1))+edge->v1->co[1];
+             co[2] = (edge->v2->co[2]-edge->v1->co[2])*(curpoint/(float)(totpoint+1))+edge->v1->co[2];
+        }
+                
+        alter_co(co,edge,rad,beauty);
+        ev = addvertlist(co);
+        ev->f = edge->v1->f;
+        
+        return ev;
+}
 
-       /* 
-               Quads and Triangles reuse the same cases numbers, so we migh as well do both in the
-               same loop. Especially now that the offsets are calculated and not hardcoded, it's
-               much easier to reduce the code size (and make it less buggy).
-       */
+void esubdivideflag(int flag, float rad, int beauty, int numcuts, int seltype)
+{
+    EditMesh *em = G.editMesh;
+    EditFace *ef;
+    EditEdge *eed, *cedge;
+    EditVert **templist;
+    struct GHash *gh;
+    int i,edgecount,facetype;
+    short cuttype=0;
+
+    //Set faces f1 to 0 cause we need it later
+               
+    for(ef=em->faces.first;ef;ef = ef->next){
+        ef->f1 = 0;
+    }
+    for(eed = em->edges.first;eed;eed = eed->next){
+        //Flush vertext flags upward to the edges
+        //if(eed->f & flag && eed->v1->f == eed->v2->f){
+        //    eed->f |= eed->v1->f;   
+        // }
+        eed->f2 = 0;   
+    }   
+    // We store an array of verts for each edge that is subdivided,
+    // we put this array as a value in a ghash which is keyed by the EditEdge*
+    
+    gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); 
+    
+       // If we are knifing, We only need the selected edges that were cut, so deselect if it was not cut
+    if(beauty & B_KNIFE) {     
+               for(eed= em->edges.first;eed;eed=eed->next){    
+                       if( eed->f1 == 0 ){
+                EM_select_edge(eed,0);   
+            }
+               }
+       }  
+    // So for each edge, if it is selected, we allocate an array of size cuts+2
+    // so we can have a place for the v1, the new verts and v2  
+    for(eed=em->edges.first;eed;eed = eed->next){
+         if(eed->f & flag){
+              templist = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"vertlist");
+              templist[0] = eed->v1;
+              for(i=0;i<numcuts;i++){
+                  // This function creates the new vert and returns it back
+                  // to the array
+                  templist[i+1] = subdivideedgenum(eed,i+1,numcuts,rad,beauty);
+                  //while we are here, we can copy edge info from the original edge
+                  cedge = addedgelist(templist[i],templist[i+1],eed);
+                  // Also set the edge f2 to EDGENEW so that we can use this info later
+                  cedge->f2 = EDGENEW;
+              }
+              templist[i+1] = eed->v2;
+              //Do the last edge too
+              cedge = addedgelist(templist[i],templist[i+1],eed);
+              cedge->f2 = EDGENEW;
+              // Now that the edge is subdivided, we can put its verts in the ghash 
+              BLI_ghash_insert(gh, eed, templist);               
+          }                                  
+    }
+    vertexnormals(0);
+    // Now for each face in the mesh we need to figure out How many edges were cut
+    // and which filling method to use for that face
+    for(ef = em->faces.first;ef;ef = ef->next){
+           edgecount = 0;
+           facetype = 3;
+           if(ef->e1->f & flag) {edgecount++;}
+           if(ef->e2->f & flag) {edgecount++;}
+           if(ef->e3->f & flag) {edgecount++;}
+           if(ef->v4){
+               facetype = 4;
+               if(ef->e4->f & flag){edgecount++;}
+           }  
+           if(facetype == 4){
+                   switch(edgecount){
+                       case 0: break;
+                       case 1: ef->f1 = SELECT;
+                               fill_quad_single(ef, gh, numcuts);
+                               break;   
+                       case 2: ef->f1 = SELECT;
+                               // if there are 2, we check if edge 1 and 3 are either both on or off that way
+                               // we can tell if the selected pair is Adjacent or Opposite of each other
+                               if((ef->e1->f & flag && ef->e3->f & flag) || 
+                                  (ef->e2->f & flag && ef->e4->f & flag)){
+                                    fill_quad_double_op(ef, gh, numcuts);                              
+                               }else{
+                                    //printf("adj\n");
+                                    fill_quad_double_adj(ef, gh, numcuts);                          
+                               }
+                               break;    
+                       case 3: ef->f1 = SELECT;
+                               fill_quad_triple(ef, gh, numcuts); 
+                               break;    
+                       case 4: ef->f1 = SELECT;
+                               fill_quad_quadruple(ef, gh, numcuts,rad,beauty); 
+                               break;    
+                   }
+            } else {
+                   switch(edgecount){
+                       case 0: break;
+                       case 1: ef->f1 = SELECT;
+                               fill_tri_single(ef, gh, numcuts);
+                               break;   
+                       case 2: ef->f1 = SELECT;
+                               fill_tri_double(ef, gh, numcuts);
+                               break;    
+                       case 3: ef->f1 = SELECT;
+                               fill_tri_triple(ef, gh, numcuts,rad,beauty);
+                               break;  
+                   }    
+            }    
+    }
+    
+    // Delete Old Faces
+    free_tagged_facelist(em->faces.first);     
+    //Delete Old Edges
+    for(eed = em->edges.first;eed;eed = eed->next){
+        if(BLI_ghash_haskey(gh,eed)){
+             eed->f1 = SELECT; 
+        } else {
+             eed->f1 = 0;   
+        }
+    } 
+    free_tagged_edgelist(em->edges.first); 
+    
+    if(seltype == 0){
+        for(eed = em->edges.first;eed;eed = eed->next){
+            if(eed->f2 & EDGENEW){
+                eed->f |= flag;
+                EM_select_edge(eed,1); 
+            }else{
+                eed->f &= !flag;
+                EM_select_edge(eed,0); 
+            }
+        }   
+    } else if (seltype == 1){
+        for(eed = em->edges.first;eed;eed = eed->next){
+            if(eed->f2 & EDGEINNER){
+                eed->f |= flag;
+                EM_select_edge(eed,1);   
+            }else{
+                eed->f &= !flag;
+                EM_select_edge(eed,0); 
+            }
+        }          
+    } 
+    // Free the ghash and call MEM_freeN on all the value entries to return 
+    // that memory
+    BLI_ghash_free(gh, NULL, MEM_freeN);   
+     
+       recalc_editnormals();
+       countall();
+       allqueue(REDRAWVIEW3D, 0);
+       DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+}
 
-       /* ******************************************** */
-       /*                                              */
-       /* Numbers corespond to verts (corner points),  */
-       /* edge->vn's (center edges), the Center            */
-       /* And the quincunx points of a face                */
-       /*                                              */
-       /* ******************************************** */
 
-       /* ******************************************** */
-       /* as shown here for quads:                     */
-       /*                                              */
-       /*           2 ------- 5 -------- 1             */
-       /*           | \    /  |  \    /  |             */
-       /*           |   10    |    13    |             */
-       /*           | /    \  |  /    \  |             */
-       /*           6 ------- 9 -------- 8             */
-       /*           | \    /  |  \    /  |             */
-       /*           |   11    |    12    |             */
-       /*           | /    \  |  /    \  |             */
-       /*           3 ------- 7 -------- 4             */
-       /*                                              */
-       /* ******************************************** */
 
-       /* ******************************************** */
-       /* and for triangles:                           */
-       /*                     1                        */
-       /*                   /   \                      */
-       /*                 /       \                    */
-       /*               5           7                  */
-       /*             /              \                 */
-       /*           /                  \               */
-       /*         2 --------- 6 -------- 3             */
-       /*                                              */
-       /* ******************************************** */
+static int count_selected_edges(EditEdge *ed)
+{
+       int totedge = 0;
+       while(ed) {
+               ed->vn= 0;
+               if( ed->f & SELECT ) totedge++;
+               ed= ed->next;
+       }
+       return totedge;
+}
 
-       /* ******************************************** */
-       /*                                              */
-       /* My talents in ascii arts are minimal so the  */
-       /* drawings don't show all possible subdivision */
-       /* just draw them on paper if you need to.      */
-       /*                                              */
-       /* ******************************************** */
+/* hurms, as if this makes code readable! It's pointerpointer hiding... (ton) */
+typedef EditFace *EVPtr;
+typedef EVPtr EVPTuple[2];
 
-       for(a=0; a<tot; a++, uv+=2, col++) {
-               /* edges that are subdivided, if any */
-               EditEdge *e1 = NULL, *e2 = NULL;
+/** builds EVPTuple array efaa of face tuples (in fact pointers to EditFaces)
+    sharing one edge.
+       arguments: selected edge list, face list.
+       Edges will also be tagged accordingly (see eed->f2)          */
 
-               if(a==0) v= v1;
-               else if(a==1) v= v2;
-               else if(a==2) v= v3;
-               else v= v4;
-               
-               if(a==3 && v4==0) break;
+static int collect_quadedges(EVPTuple *efaa, EditEdge *eed, EditFace *efa)
+{
+       int i = 0;
+       EditEdge *e1, *e2, *e3;
+       EVPtr *evp;
 
-               switch (v) {
-               /* Face corners, direct copy of the UVs and VCol */
-               case 1:
-               case 2:
-               case 3:
-               case 4:
-                       uv[0]= uvo[v-1][0];
-                       uv[1]= uvo[v-1][1];
-                       *col= colo[v-1];
-                       break;
-               /* Face sides (cutting an edge) */
-               /*
-                       set the edge pointer accordingly, it's used latter to do the
-                       actual calculations of the new UV and VCol 
-               */
-               case 5:
-                       e1 = efapin->e1;
-                       break;
-               case 6:
-                       e1 = efapin->e2;
-                       break;
-               case 7:
-                       e1 = efapin->e3;
-                       break;
-               case 8:
-                       e1 = efapin->e4;
-                       break;
-
-               /* The following applies to Quads only */
-
-               /* Quad middle, just used when subdividing a quad as a whole */
-               /* (not knife nor loop cut) */
-               /* UVs and VCol is just the average of the four corners */
-               case 9:
-                       uv_quart(uv, uvo[0]);
-                       col1= cpack_fact(colo[1], colo[0], 0.5f);
-                       col2= cpack_fact(colo[2], colo[3], 0.5f);
-                       *col= cpack_fact(col1, col2, 0.5f);
-                       break;
-               /* Quad corner cuts */
-               /* only when two adjacent edges are subdivided (and no others) */
-               /* Set both edge pointers accordingly, used later for calculations */
-               case 10: // case test==3 in subdivideflag()     
-                       e1 = efapin->e1;
-                       e2 = efapin->e2;
-                       break;
-               case 11: // case of test==6
-                       e1 = efapin->e2;
-                       e2 = efapin->e3;
-                       break;
-               case 12: // case of test==12
-                       e1 = efapin->e3;
-                       e2 = efapin->e4;
-                       break;
-               case 13: // case of test==9
-                       e1 = efapin->e4;
-                       e2 = efapin->e1;
-                       break;
+       /* run through edges, if selected, set pointer edge-> facearray */
+       while(eed) {
+               eed->f2= 0;
+               eed->f1= 0;
+               if( eed->f & SELECT ) {
+                       eed->vn= (EditVert *) (&efaa[i]);
+                       i++;
                }
-               /* if splitting at least an edge */
-               if (e1) {
-                       float percent;
-                       int off1, off2;
-                       /* if splitting two edges */
-                       if (e2) {
-                               float uv1[2], uv2[2];
-                               /*
-                                       UV and VCol is obtained by using the middle ground of the weighted
-                                       average for both edges (weighted with Percent cut flag).
-                                       In a nutshell, the average of the cuts on both edges.
-                               */
-                               /* first cut */
-                               off1 = vert_offset(efapin, e1->v1);
-                               off2 = vert_offset(efapin, e1->v2);
-                               percent = e1->f1 / 32768.0f;
-                               uv_fact(uv1, uvo[off1], uvo[off2], percent);
-                               col1= cpack_fact(colo[off1], colo[off2], percent);
-
-                               /* second cut */
-                               off1 = vert_offset(efapin, e2->v1);
-                               off2 = vert_offset(efapin, e2->v2);
-                               percent = e2->f1 / 32768.0f;
-                               uv_fact(uv2, uvo[off1], uvo[off2], percent);
-                               col2= cpack_fact(colo[off1], colo[off1], percent);
+               
+               eed= eed->next;
+       }
+               
+       
+       /* find edges pointing to 2 faces by procedure:
+       
+       - run through faces and their edges, increase
+         face counter e->f1 for each face 
+       */
 
-                               /* average the two */
-                               uv_half(uv, uv1, uv2);
-                               *col= cpack_fact(col1, col2, 0.5f);
-                       }
-                       /* or only one */
-                       else {
-                               /*
-                                       UV and VCol is obtained by using the weighted average 
-                                       of both vertice (weighted with Percent cut flag).
-                               */
-                               off1 = vert_offset(efapin, e1->v1);
-                               off2 = vert_offset(efapin, e1->v2);
-                               percent = e1->f1 / 32768.0f;
-                               uv_fact(uv, uvo[off1], uvo[off2], percent);
-                               *col= cpack_fact(colo[off1], colo[off2], percent);
+       while(efa) {
+               efa->f1= 0;
+               if(efa->v4==0) {  /* if triangle */
+                       if(efa->f & SELECT) {
+                               
+                               e1= efa->e1;
+                               e2= efa->e2;
+                               e3= efa->e3;
+                               if(e1->f2<3) {
+                                       if(e1->f2<2) {
+                                               evp= (EVPtr *) e1->vn;
+                                               evp[(int)e1->f2]= efa;
+                                       }
+                                       e1->f2+= 1;
+                               }
+                               if(e2->f2<3) {
+                                       if(e2->f2<2) {
+                                               evp= (EVPtr *) e2->vn;
+                                               evp[(int)e2->f2]= efa;
+                                       }
+                                       e2->f2+= 1;
+                               }
+                               if(e3->f2<3) {
+                                       if(e3->f2<2) {
+                                               evp= (EVPtr *) e3->vn;
+                                               evp[(int)e3->f2]= efa;
+                                       }
+                                       e3->f2+= 1;
+                               }
                        }
                }
+               efa= efa->next;
        }
+       return i;
 }
 
-static EditVert *vert_from_number(EditFace *efa, int nr)
-{
-       switch(nr) {
-       case 0:
-               return 0;
-       case 1:
-               return efa->v1;
-       case 2:
-               return efa->v2;
-       case 3:
-               return efa->v3;
-       case 4:
-               return efa->v4;
-       case 5:
-               return efa->e1->vn;
-       case 6:
-               return efa->e2->vn;
-       case 7:
-               return efa->e3->vn;
-       case 8:
-               return efa->e4->vn;
-       }
-       
-       return NULL;
-}
-
-static void addface_subdiv(EditFace *efa, int val1, int val2, int val3, int val4, EditVert *eve, EditFace *efapin)
-{
-       EditFace *w;
-       EditVert *v1, *v2, *v3, *v4;
-       
-       if(val1>=9) v1= eve;
-       else v1= vert_from_number(efa, val1);
-       
-       if(val2>=9) v2= eve;
-       else v2= vert_from_number(efa, val2);
 
-       if(val3>=9) v3= eve;
-       else v3= vert_from_number(efa, val3);
+/* returns vertices of two adjacent triangles forming a quad 
+   - can be righthand or lefthand
 
-       if(val4>=9) v4= eve;
-       else v4= vert_from_number(efa, val4);
-       
-       w= addfacelist(v1, v2, v3, v4, efa, NULL);
-       if(w) {
-               if(efa->v4) set_wuv(4, w, val1, val2, val3, val4, efapin);
-               else set_wuv(3, w, val1, val2, val3, val4, efapin);
-       }
-}
+                       4-----3
+                       |\    |
+                       | \ 2 | <- efa1
+                       |  \  | 
+         efa-> | 1 \ | 
+                       |    \| 
+                       1-----2
 
-static float smoothperc= 0.0;
+*/
+#define VTEST(face, num, other) \
+       (face->v##num != other->v1 && face->v##num != other->v2 && face->v##num != other->v3) 
 
-static void smooth_subdiv_vec(float *v1, float *v2, float *n1, float *n2, float *vec)
+static void givequadverts(EditFace *efa, EditFace *efa1, EditVert **v1, EditVert **v2, EditVert **v3, EditVert **v4, float **uv, unsigned int *col)
 {
-       float len, fac, nor[3], nor1[3], nor2[3];
-       
-       VecSubf(nor, v1, v2);
-       len= 0.5f*Normalise(nor);
-
-       VECCOPY(nor1, n1);
-       VECCOPY(nor2, n2);
-
-       /* cosine angle */
-       fac= nor[0]*nor1[0] + nor[1]*nor1[1] + nor[2]*nor1[2] ;
+       if VTEST(efa, 1, efa1) {
+       //if(efa->v1!=efa1->v1 && efa->v1!=efa1->v2 && efa->v1!=efa1->v3) {
+               *v1= efa->v1;
+               *v2= efa->v2;
+               uv[0] = efa->tf.uv[0];
+               uv[1] = efa->tf.uv[1];
+               col[0] = efa->tf.col[0];
+               col[1] = efa->tf.col[1];
+       }
+       else if VTEST(efa, 2, efa1) {
+       //else if(efa->v2!=efa1->v1 && efa->v2!=efa1->v2 && efa->v2!=efa1->v3) {
+               *v1= efa->v2;
+               *v2= efa->v3;
+               uv[0] = efa->tf.uv[1];
+               uv[1] = efa->tf.uv[2];
+               col[0] = efa->tf.col[1];
+               col[1] = efa->tf.col[2];
+       }
+       else if VTEST(efa, 3, efa1) {
+       // else if(efa->v3!=efa1->v1 && efa->v3!=efa1->v2 && efa->v3!=efa1->v3) {
+               *v1= efa->v3;
+               *v2= efa->v1;
+               uv[0] = efa->tf.uv[2];
+               uv[1] = efa->tf.uv[0];
+               col[0] = efa->tf.col[2];
+               col[1] = efa->tf.col[0];
+       }
        
-       vec[0]= fac*nor1[0];
-       vec[1]= fac*nor1[1];
-       vec[2]= fac*nor1[2];
+       if VTEST(efa1, 1, efa) {
+       // if(efa1->v1!=efa->v1 && efa1->v1!=efa->v2 && efa1->v1!=efa->v3) {
+               *v3= efa1->v1;
+               uv[2] = efa1->tf.uv[0];
+               col[2] = efa1->tf.col[0];
 
-       /* cosine angle */
-       fac= -nor[0]*nor2[0] - nor[1]*nor2[1] - nor[2]*nor2[2] ;
-       
-       vec[0]+= fac*nor2[0];
-       vec[1]+= fac*nor2[1];
-       vec[2]+= fac*nor2[2];
+               *v4= efa1->v2;
+               uv[3] = efa1->tf.uv[1];
+               col[3] = efa1->tf.col[1];
+/*
+if(efa1->v2== *v2) {
+                       *v4= efa1->v3;
+                       uv[3] = efa1->tf.uv[2];
+               } else {
+                       *v4= efa1->v2;
+                       uv[3] = efa1->tf.uv[1];
+               }       
+               */
+       }
+       else if VTEST(efa1, 2, efa) {
+       // else if(efa1->v2!=efa->v1 && efa1->v2!=efa->v2 && efa1->v2!=efa->v3) {
+               *v3= efa1->v2;
+               uv[2] = efa1->tf.uv[1];
+               col[2] = efa1->tf.col[1];
 
-       vec[0]*= smoothperc*len;
-       vec[1]*= smoothperc*len;
-       vec[2]*= smoothperc*len;
-}
+               *v4= efa1->v3;
+               uv[3] = efa1->tf.uv[2];
+               col[3] = efa1->tf.col[2];
+/*
+if(efa1->v3== *v2) {
+                       *v4= efa1->v1;
+                       uv[3] = efa1->tf.uv[0];
+               } else {        
+                       *v4= efa1->v3;
+                       uv[3] = efa1->tf.uv[2];
+               }       
+               */
+       }
+       else if VTEST(efa1, 3, efa) {
+       // else if(efa1->v3!=efa->v1 && efa1->v3!=efa->v2 && efa1->v3!=efa->v3) {
+               *v3= efa1->v3;
+               uv[2] = efa1->tf.uv[2];
+               col[2] = efa1->tf.col[2];
 
-static void smooth_subdiv_quad(EditFace *efa, float *vec)
-{
-       
-       float nor1[3], nor2[3];
-       float vec1[3], vec2[3];
-       float cent[3];
-       
-       /* vlr->e1->vn is new vertex inbetween v1 / v2 */
+               *v4= efa1->v1;
+               uv[3] = efa1->tf.uv[0];
+               col[3] = efa1->tf.col[0];
+/*
+if(efa1->v1== *v2) {
+                       *v4= efa1->v2;
+                       uv[3] = efa1->tf.uv[3];
+               } else {        
+                       *v4= efa1->v1;
+                       uv[3] = efa1->tf.uv[0];
+               }       
+               */
+       }
+       else {
+               *v3= *v4= NULL;
+               
+               return;
+       }
        
-       VecMidf(nor1, efa->v1->no, efa->v2->no);
-       Normalise(nor1);
-       VecMidf(nor2, efa->v3->no, efa->v4->no);
-       Normalise(nor2);
-
-       smooth_subdiv_vec( efa->e1->vn->co, efa->e3->vn->co, nor1, nor2, vec1);
-
-       VecMidf(nor1, efa->v2->no, efa->v3->no);
-       Normalise(nor1);
-       VecMidf(nor2, efa->v4->no, efa->v1->no);
-       Normalise(nor2);
-
-       smooth_subdiv_vec( efa->e2->vn->co, efa->e4->vn->co, nor1, nor2, vec2);
+}
 
-       VecAddf(vec1, vec1, vec2);
+/* Helper functions for edge/quad edit features*/
 
-       CalcCent4f(cent, efa->v1->co,  efa->v2->co,  efa->v3->co,  efa->v4->co);
-       VecAddf(vec, cent, vec1);
+static void untag_edges(EditFace *f)
+{
+       f->e1->f2 = 0;
+       f->e2->f2 = 0;
+       if (f->e3) f->e3->f2 = 0;
+       if (f->e4) f->e4->f2 = 0;
 }
 
-void subdivideflag(int flag, float rad, int beauty)
+/** remove and free list of tagged edges */
+static void free_tagged_edgelist(EditEdge *eed)
 {
-       EditMesh *em = G.editMesh;
-       /* subdivide all with (vertflag & flag) */
-       /* if rad>0.0 it's a 'sphere' subdivide */
-       /* if rad<0.0 it's a fractal subdivide */
-       extern float doublimit;
-       EditVert *eve;
-       EditEdge *eed, *e1, *e2, *e3, *e4, *nexted;
-       EditFace *efa, efapin;
-       float fac, vec[3], vec1[3], len1, len2, len3, percent;
-       short test;
-       
-       if(beauty & B_SMOOTH) {
-               short perc= 100;
-
-               if(button(&perc, 10, 500, "Percentage:")==0) return;
-               
-               smoothperc= 0.292f*perc/100.0f;
-       }
-
-       /* edgeflags */
-       if((beauty & B_KNIFE)==0) {             // knife option sets own flags
-               eed= em->edges.first;
-               while(eed) {    
-                       if( (eed->v1->f & flag) && (eed->v2->f & flag) ) eed->f2= flag;
-                       else eed->f2= 0;        
-                       eed= eed->next;
-               }
-       }
-       
-       /* if beauty: test for area and clear edge flags of 'ugly' edges */
-       if(beauty & B_BEAUTY) {
-               efa= em->faces.first;
-               while(efa) {
-                       if( faceselectedAND(efa, flag) ) {
-                               if(efa->v4) {
-                               
-                                       /* area */
-                                       len1= AreaQ3Dfl(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
-                                       if(len1 <= doublimit) {
-                                               efa->e1->f2 = 0;
-                                               efa->e2->f2 = 0;
-                                               efa->e3->f2 = 0;
-                                               efa->e4->f2 = 0;
-                                       }
-                                       else {
-                                               len1= VecLenf(efa->v1->co, efa->v2->co) + VecLenf(efa->v3->co, efa->v4->co);
-                                               len2= VecLenf(efa->v2->co, efa->v3->co) + VecLenf(efa->v1->co, efa->v4->co);
-                                               
-                                               if(len1 < len2) {
-                                                       efa->e1->f2 = 0;
-                                                       efa->e3->f2 = 0;
-                                               }
-                                               else if(len1 > len2) {
-                                                       efa->e2->f2 = 0;
-                                                       efa->e4->f2 = 0;
-                                               }
-                                       }
-                               }
-                               else {
-                                       /* area */
-                                       len1= AreaT3Dfl(efa->v1->co, efa->v2->co, efa->v3->co);
-                                       if(len1 <= doublimit) {
-                                               efa->e1->f2 = 0;
-                                               efa->e2->f2 = 0;
-                                               efa->e3->f2 = 0;
-                                       }
-                                       else {
-                                               len1= VecLenf(efa->v1->co, efa->v2->co) ;
-                                               len2= VecLenf(efa->v2->co, efa->v3->co) ;
-                                               len3= VecLenf(efa->v3->co, efa->v1->co) ;
-                                               
-                                               if(len1<len2 && len1<len3) {
-                                                       efa->e1->f2 = 0;
-                                               }
-                                               else if(len2<len3 && len2<len1) {
-                                                       efa->e2->f2 = 0;
-                                               }
-                                               else if(len3<len2 && len3<len1) {
-                                                       efa->e3->f2 = 0;
-                                               }
-                                       }
-                               }
-                       }
-                       efa= efa->next;
-               }
-       }
+       EditEdge *nexted;
 
-       if(beauty & B_SMOOTH) {
-               
-               vertexnormals(0);               /* no1*/
-                       
-       }
-       
-       /* make new normal and put in edge, clear flag! needed for face creation part below */
-       eed= em->edges.first;
        while(eed) {
-               if(eed->f2 & flag) {
-                       /* for now */
-                       eed->h &= ~EM_FGON;
-               
-                       /* Subdivide percentage is stored in 1/32768ths in eed->f1 */
-                       if (beauty & B_PERCENTSUBD) percent=(float)(eed->f1)/32768.0f;
-                       else {
-                               eed->f1 = 32768 / 2;
-                               percent=0.5f;
-                       }
-                       
-                       vec[0]= (1-percent)*eed->v1->co[0] + percent*eed->v2->co[0];
-                       vec[1]= (1-percent)*eed->v1->co[1] + percent*eed->v2->co[1];
-                       vec[2]= (1-percent)*eed->v1->co[2] + percent*eed->v2->co[2];
-
-                       if(rad > 0.0) {   /* subdivide sphere */
-                               Normalise(vec);
-                               vec[0]*= rad;
-                               vec[1]*= rad;
-                               vec[2]*= rad;
-                       }
-                       else if(rad< 0.0) {  /* fractal subdivide */
-                               fac= rad* VecLenf(eed->v1->co, eed->v2->co);
-                               vec1[0]= fac*(float)(0.5-BLI_drand());
-                               vec1[1]= fac*(float)(0.5-BLI_drand());
-                               vec1[2]= fac*(float)(0.5-BLI_drand());
-                               VecAddf(vec, vec, vec1);
-                       }
-                       
-                       if(beauty & B_SMOOTH) {
-                               smooth_subdiv_vec(eed->v1->co, eed->v2->co, eed->v1->no, eed->v2->no, vec1);
-                               VecAddf(vec, vec, vec1);
-                       }
-                       
-                       eed->vn= addvertlist(vec);
-                       eed->vn->f= eed->v1->f;
-
+               nexted= eed->next;
+               if(eed->f1) {
+                       remedge(eed);
+                       free_editedge(eed);
                }
-               else eed->vn= 0;
-               
-               eed->f2= 0; /* needed! */
-               
-               eed= eed->next;
-       }
+               eed= nexted;
+       }       
+}      
+/** remove and free list of tagged faces */
 
-       /* test all faces for subdivide edges, there are 8 or 16 cases (ugh)! */
+static void free_tagged_facelist(EditFace *efa)
+{      
+       EditMesh *em = G.editMesh;
+       EditFace *nextvl;
 
-       efa= em->faces.last;
        while(efa) {
+               nextvl= efa->next;
+               if(efa->f1) {
+                       BLI_remlink(&em->faces, efa);
+                       free_editface(efa);
+               }
+               efa= nextvl;
+       }
+}      
 
-               efapin= *efa; /* make a copy of efa to recover uv pinning later */
 
-               if( faceselectedOR(efa, flag) ) {
-                       /* for now */
-                       efa->fgonf= 0;
-                       
-                       e1= efa->e1;
-                       e2= efa->e2;
-                       e3= efa->e3;
-                       e4= efa->e4;
-
-                       test= 0;
-                       if(e1 && e1->vn) { 
-                               test+= 1;
-                               e1->f2= 1;
-                               /* add edges here, to copy correct edge data */
-                               eed= addedgelist(e1->v1, e1->vn, e1);
-                               eed= addedgelist(e1->vn, e1->v2, e1);
-                               set_weights(e1->vn, e1->v1,e1->v2,NULL,NULL);
-                       }
-                       if(e2 && e2->vn) {
-                               test+= 2;
-                               e2->f2= 1;
-                               /* add edges here, to copy correct edge data */
-                               eed= addedgelist(e2->v1, e2->vn, e2);
-                               eed= addedgelist(e2->vn, e2->v2, e2);
-                               set_weights(e2->vn, e2->v1,e2->v2,NULL,NULL);
-                       }
-                       if(e3 && e3->vn) {
-                               test+= 4;
-                               e3->f2= 1;
-                               /* add edges here, to copy correct edge data */
-                               eed= addedgelist(e3->v1, e3->vn, e3);
-                               eed= addedgelist(e3->vn, e3->v2, e3);
-                               set_weights(e3->vn, e3->v1,e3->v2,NULL,NULL);
-                       }
-                       if(e4 && e4->vn) {
-                               test+= 8;
-                               e4->f2= 1;
-                               /* add edges here, to copy correct edge data */
-                               eed= addedgelist(e4->v1, e4->vn, e4);
-                               eed= addedgelist(e4->vn, e4->v2, e4);
-                               set_weights(e4->vn, e4->v1,e4->v2,NULL,NULL);
-                       }
-                       if(test) {
-                               if(efa->v4==0) {  /* All the permutations of 3 edges*/
-                                       if((test & 3)==3) addface_subdiv(efa, 2, 2+4, 1+4, 0, 0, &efapin);
-                                       if((test & 6)==6) addface_subdiv(efa, 3, 3+4, 2+4, 0, 0, &efapin);
-                                       if((test & 5)==5) addface_subdiv(efa, 1, 1+4, 3+4, 0, 0, &efapin);
+void beauty_fill(void)
+{
+    EditMesh *em = G.editMesh;
+    EditVert *v1, *v2, *v3, *v4;
+    EditEdge *eed, *nexted;
+    EditEdge dia1, dia2;
+    EditFace *efa, *w;
+    // void **efaar, **efaa;
+    EVPTuple *efaar;
+    EVPtr *efaa;
+    float *uv[4];
+    unsigned int col[4];
+    float len1, len2, len3, len4, len5, len6, opp1, opp2, fac1, fac2;
+    int totedge, ok, notbeauty=8, onedone;
 
-                                       if(test==7) {  /* four new faces, old face renews */
-                                               efa->v1= e1->vn;
-                                               efa->v2= e2->vn;
-                                               efa->v3= e3->vn;
-                                               set_wuv(3, efa, 1+4, 2+4, 3+4, 0, &efapin);
-                                       }
-                                       else if(test==3) {
-                                               addface_subdiv(efa, 1+4, 2+4, 3, 0, 0, &efapin);
-                                               efa->v2= e1->vn;
-                                               set_wuv(3, efa, 1, 1+4, 3, 0, &efapin);
-                                       }
-                                       else if(test==6) {
-                                               addface_subdiv(efa, 2+4, 3+4, 1, 0, 0, &efapin);
-                                               efa->v3= e2->vn;
-                                               set_wuv(3, efa, 1, 2, 2+4, 0, &efapin);
-                                       }
-                                       else if(test==5) {
-                                               addface_subdiv(efa, 3+4, 1+4, 2, 0, 0, &efapin);
-                                               efa->v1= e3->vn;
-                                               set_wuv(3, efa, 3+4, 2, 3, 0, &efapin);
-                                       }
-                                       else if(test==1) {
-                                               addface_subdiv(efa, 1+4, 2, 3, 0, 0, &efapin);
-                                               efa->v2= e1->vn;
-                                               set_wuv(3, efa, 1, 1+4, 3, 0, &efapin);
-                                       }
-                                       else if(test==2) {
-                                               addface_subdiv(efa, 2+4, 3, 1, 0, 0, &efapin);
-                                               efa->v3= e2->vn;
-                                               set_wuv(3, efa, 1, 2, 2+4, 0, &efapin);
-                                       }
-                                       else if(test==4) {
-                                               addface_subdiv(efa, 3+4, 1, 2, 0, 0, &efapin);
-                                               efa->v1= e3->vn;
-                                               set_wuv(3, efa, 3+4, 2, 3, 0, &efapin);
-                                       }
-                                       efa->e1= addedgelist(efa->v1, efa->v2, NULL);
-                                       efa->e2= addedgelist(efa->v2, efa->v3, NULL);
-                                       efa->e3= addedgelist(efa->v3, efa->v1, NULL);
+       /* - all selected edges with two faces
+               * - find the faces: store them in edges (using datablock)
+               * - per edge: - test convex
+               *                          - test edge: flip?
+               *               - if true: remedge,  addedge, all edges at the edge get new face pointers
+               */
+       
+       EM_selectmode_flush();  // makes sure in selectmode 'face' the edges of selected faces are selected too 
 
-                               }
-                               else {  /* All the permutations of 4 faces */
-                                       if(test==15) {
-                                               /* add a new point in center */
-                                               CalcCent4f(vec, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
-                                               
-                                               if(beauty & B_SMOOTH) {
-                                                       smooth_subdiv_quad(efa, vec);   /* adds */
-                                               }
-                                               eve= addvertlist(vec);
-                                               set_weights(eve, efa->v1,efa->v2,efa->v3,efa->v4);
-                                               eve->f |= flag;
+    totedge = count_selected_edges(em->edges.first);
+    if(totedge==0) return;
 
-                                               addface_subdiv(efa, 2, 2+4, 9, 1+4, eve, &efapin);
-                                               addface_subdiv(efa, 3, 3+4, 9, 2+4, eve, &efapin);
-                                               addface_subdiv(efa, 4, 4+4, 9, 3+4, eve, &efapin);
+    if(okee("Beautify fill")==0) return;
+    
+    /* temp block with face pointers */
+    efaar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "beautyfill");
 
-                                               efa->v2= e1->vn;
-                                               efa->v3= eve;
-                                               efa->v4= e4->vn;
-                                               set_wuv(4, efa, 1, 1+4, 9, 4+4, &efapin);
-                                       }
-                                       else {
-                                               if(((test & 3)==3)&&(test!=3)) addface_subdiv(efa, 1+4, 2, 2+4, 0, 0, &efapin);
-                                               if(((test & 6)==6)&&(test!=6)) addface_subdiv(efa, 2+4, 3, 3+4, 0, 0, &efapin);
-                                               if(((test & 12)==12)&&(test!=12)) addface_subdiv(efa, 3+4, 4, 4+4, 0, 0, &efapin);
-                                               if(((test & 9)==9)&&(test!=9)) addface_subdiv(efa, 4+4, 1, 1+4, 0, 0, &efapin);
+    while (notbeauty) {
+        notbeauty--;
 
-                                               if(test==1) { /* Edge 1 has new vert */
-                                                       addface_subdiv(efa, 1+4, 2, 3, 0, 0, &efapin);
-                                                       addface_subdiv(efa, 1+4, 3, 4, 0, 0, &efapin);
-                                                       efa->v2= e1->vn;
-                                                       efa->v3= efa->v4;
-                                                       efa->v4= 0;
-                                                       set_wuv(4, efa, 1, 1+4, 4, 0, &efapin);
-                                               }
-                                               else if(test==2) { /* Edge 2 has new vert */
-                                                       addface_subdiv(efa, 2+4, 3, 4, 0, 0, &efapin);
-                                                       addface_subdiv(efa, 2+4, 4, 1, 0, 0, &efapin);
-                                                       efa->v3= e2->vn;
-                                                       efa->v4= 0;
-                                                       set_wuv(4, efa, 1, 2, 2+4, 0, &efapin);
-                                               }
-                                               else if(test==4) { /* Edge 3 has new vert */
-                                                       addface_subdiv(efa, 3+4, 4, 1, 0, 0, &efapin);
-                                                       addface_subdiv(efa, 3+4, 1, 2, 0, 0, &efapin);
-                                                       efa->v1= efa->v2;
-                                                       efa->v2= efa->v3;
-                                                       efa->v3= e3->vn;
-                                                       efa->v4= 0;
-                                                       set_wuv(4, efa, 2, 3, 3+4, 0, &efapin);
-                                               }
-                                               else if(test==8) { /* Edge 4 has new vert */
-                                                       addface_subdiv(efa, 4+4, 1, 2, 0, 0, &efapin);
-                                                       addface_subdiv(efa, 4+4, 2, 3, 0, 0, &efapin);
-                                                       efa->v1= efa->v3;
-                                                       efa->v2= efa->v4;
-                                                       efa->v3= e4->vn;
-                                                       efa->v4= 0;
-                                                       set_wuv(4, efa, 3, 4, 4+4, 0, &efapin);
-                                               }
-                                               else if(test==3) { /*edge 1&2 */
-                                                       /* make new vert in center of new edge */
-                                                       vec[0]=(e1->vn->co[0]+e2->vn->co[0])/2;
-                                                       vec[1]=(e1->vn->co[1]+e2->vn->co[1])/2;
-                                                       vec[2]=(e1->vn->co[2]+e2->vn->co[2])/2;
-                                                       eve= addvertlist(vec);
-                                                       set_weights(eve, e1->vn,e2->vn,NULL,NULL);
-                                                       eve->f |= flag;
-                                                       /* Add new faces */
-                                                       addface_subdiv(efa, 4, 10, 2+4, 3, eve, &efapin);
-                                                       addface_subdiv(efa, 4, 1, 1+4, 10, eve, &efapin);
-                                                       /* orig face becomes small corner */
-                                                       efa->v1=e1->vn;
-                                                       //efa->v2=efa->v2;
-                                                       efa->v3=e2->vn;
-                                                       efa->v4=eve;
+        ok = collect_quadedges(efaar, em->edges.first, em->faces.first);
 
-                                                       set_wuv(4, efa, 1+4, 2, 2+4, 10, &efapin);
-                                               }
-                                               else if(test==6) { /* 2&3 */
-                                                       /* make new vert in center of new edge */
-                                                       vec[0]=(e2->vn->co[0]+e3->vn->co[0])/2;
-                                                       vec[1]=(e2->vn->co[1]+e3->vn->co[1])/2;
-                                                       vec[2]=(e2->vn->co[2]+e3->vn->co[2])/2;
-                                                       eve= addvertlist(vec);
-                                                       set_weights(eve, e2->vn,e3->vn,NULL,NULL);
-                                                       eve->f |= flag;
-                                                       /*New faces*/
-                                                       addface_subdiv(efa, 1, 11, 3+4, 4, eve, &efapin);
-                                                       addface_subdiv(efa, 1, 2, 2+4, 11, eve, &efapin);
-                                                       /* orig face becomes small corner */
-                                                       efa->v1=e2->vn;
-                                                       efa->v2=efa->v3;
-                                                       efa->v3=e3->vn;
-                                                       efa->v4=eve;
+        /* there we go */
+        onedone= 0;
 
-                                                       set_wuv(4, efa, 2+4, 3, 3+4, 11, &efapin);
-                                               }
-                                               else if(test==12) { /* 3&4 */
-                                                       /* make new vert in center of new edge */
-                                                       vec[0]=(e3->vn->co[0]+e4->vn->co[0])/2;
-                                                       vec[1]=(e3->vn->co[1]+e4->vn->co[1])/2;
-                                                       vec[2]=(e3->vn->co[2]+e4->vn->co[2])/2;
-                                                       eve= addvertlist(vec);
-                                                       set_weights(eve, e3->vn,e4->vn,NULL,NULL);
-                                                       eve->f |= flag;
-                                                       /*New Faces*/
-                                                       addface_subdiv(efa, 2, 12, 4+4, 1, eve, &efapin);
-                                                       addface_subdiv(efa, 2, 3, 3+4, 12, eve, &efapin);
-                                                       /* orig face becomes small corner */
-                                                       efa->v1=e3->vn;
-                                                       efa->v2=efa->v4;
-                                                       efa->v3=e4->vn;
-                                                       efa->v4=eve;
+        eed= em->edges.first;
+        while(eed) {
+            nexted= eed->next;
+                       
+                       /* f2 is set in collect_quadedges() */
+            if(eed->f2==2 && eed->h==0) {
 
-                                                       set_wuv(4, efa, 3+4, 4, 4+4, 12, &efapin);
-                                               }
-                                               else if(test==9) { /* 4&1 */
-                                                       /* make new vert in center of new edge */
-                                                       vec[0]=(e1->vn->co[0]+e4->vn->co[0])/2;
-                                                       vec[1]=(e1->vn->co[1]+e4->vn->co[1])/2;
-                                                       vec[2]=(e1->vn->co[2]+e4->vn->co[2])/2;
-                                                       eve= addvertlist(vec);
-                                                       set_weights(eve, e1->vn,e4->vn,NULL,NULL);
-                                                       eve->f |= flag;
-                                                       /*New Faces*/
-                                                       addface_subdiv(efa, 3, 13, 1+4, 2, eve, &efapin);
-                                                       addface_subdiv(efa, 3, 4,  4+4,13, eve, &efapin);
-                                                       /* orig face becomes small corner */
-                                                       efa->v2=efa->v1;
-                                                       efa->v1=e4->vn;
-                                                       efa->v3=e1->vn;
-                                                       efa->v4=eve;
+                efaa = (EVPtr *) eed->vn;
 
-                                                       set_wuv(4, efa, 4+4, 1, 1+4, 13, &efapin);
-                                               }
-                                               else if(test==5) { /* 1&3 */
-                                                       addface_subdiv(efa, 1+4, 2, 3, 3+4, 0, &efapin);
-                                                       efa->v2= e1->vn;
-                                                       efa->v3= e3->vn;
-                                                       set_wuv(4, efa, 1, 1+4, 3+4, 4, &efapin);
-                                               }
-                                               else if(test==10) { /* 2&4 */
-                                                       addface_subdiv(efa, 2+4, 3, 4, 4+4, 0, &efapin);
-                                                       efa->v3= e2->vn;
-                                                       efa->v4= e4->vn;
-                                                       set_wuv(4, efa, 1, 2, 2+4, 4+4, &efapin);
-                                               }/* Unfortunately, there is no way to avoid tris on 1 or 3 edges*/
-                                               else if(test==7) { /*1,2&3 */
-                                                       addface_subdiv(efa, 1+4, 2+4, 3+4, 0, 0, &efapin);
-                                                       efa->v2= e1->vn;
-                                                       efa->v3= e3->vn;
-                                                       set_wuv(4, efa, 1, 1+4, 3+4, 4, &efapin);
-                                               }
-                                               
-                                               else if(test==14) { /* 2,3&4 */
-                                                       addface_subdiv(efa, 2+4, 3+4, 4+4, 0, 0, &efapin);
-                                                       efa->v3= e2->vn;
-                                                       efa->v4= e4->vn;
-                                                       set_wuv(4, efa, 1, 2, 2+4, 4+4, &efapin);
-                                               }
-                                               else if(test==13) {/* 1,3&4 */
-                                                       addface_subdiv(efa, 3+4, 4+4, 1+4, 0, 0, &efapin);
-                                                       efa->v4= e3->vn;
-                                                       efa->v1= e1->vn;
-                                                       set_wuv(4, efa, 1+4, 2, 3, 3+4, &efapin);
+                /* none of the faces should be treated before, nor be part of fgon */
+                ok= 1;
+                efa= efaa[0];
+                if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0;
+                               if(efa->fgonf) ok= 0;
+                efa= efaa[1];
+                if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0;
+                               if(efa->fgonf) ok= 0;
+                               
+                if(ok) {
+                    /* test convex */
+                    givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, uv, col);
+                                       if(v1 && v2 && v3 && v4) {
+                                               if( convex(v1->co, v2->co, v3->co, v4->co) ) {
+
+                                                       /* test edges */
+                                                       if( ((long)v1) > ((long)v3) ) {
+                                                               dia1.v1= v3;
+                                                               dia1.v2= v1;
+                                                       }
+                                                       else {
+                                                               dia1.v1= v1;
+                                                               dia1.v2= v3;
+                                                       }
+
+                                                       if( ((long)v2) > ((long)v4) ) {
+                                                               dia2.v1= v4;
+                                                               dia2.v2= v2;
+                                                       }
+                                                       else {
+                                                               dia2.v1= v2;
+                                                               dia2.v2= v4;
+                                                       }
+
+                                                       /* testing rule:
+                                                        * the area divided by the total edge lengths
+                                                        */
+
+                                                       len1= VecLenf(v1->co, v2->co);
+                                                       len2= VecLenf(v2->co, v3->co);
+                                                       len3= VecLenf(v3->co, v4->co);
+                                                       len4= VecLenf(v4->co, v1->co);
+                                                       len5= VecLenf(v1->co, v3->co);
+                                                       len6= VecLenf(v2->co, v4->co);
+
+                                                       opp1= AreaT3Dfl(v1->co, v2->co, v3->co);
+                                                       opp2= AreaT3Dfl(v1->co, v3->co, v4->co);
+
+                                                       fac1= opp1/(len1+len2+len5) + opp2/(len3+len4+len5);
+
+                                                       opp1= AreaT3Dfl(v2->co, v3->co, v4->co);
+                                                       opp2= AreaT3Dfl(v2->co, v4->co, v1->co);
+
+                                                       fac2= opp1/(len2+len3+len6) + opp2/(len4+len1+len6);
+
+                                                       ok= 0;
+                                                       if(fac1 > fac2) {
+                                                               if(dia2.v1==eed->v1 && dia2.v2==eed->v2) {
+                                                                       eed->f1= 1;
+                                                                       efa= efaa[0];
+                                                                       efa->f1= 1;
+                                                                       efa= efaa[1];
+                                                                       efa->f1= 1;
+
+                                                                       w= addfacelist(v1, v2, v3, 0, efa, NULL);
+
+                                                                       UVCOPY(w->tf.uv[0], uv[0]);
+                                                                       UVCOPY(w->tf.uv[1], uv[1]);
+                                                                       UVCOPY(w->tf.uv[2], uv[2]);
+
+                                                                       w->tf.col[0] = col[0]; w->tf.col[1] = col[1]; w->tf.col[2] = col[2];
+                                                                       w= addfacelist(v1, v3, v4, 0, efa, NULL);
+
+                                                                       UVCOPY(w->tf.uv[0], uv[0]);
+                                                                       UVCOPY(w->tf.uv[1], uv[2]);
+                                                                       UVCOPY(w->tf.uv[2], uv[3]);
+
+                                                                       w->tf.col[0] = col[0]; w->tf.col[1] = col[2]; w->tf.col[2] = col[3];
+
+                                                                       onedone= 1;
+                                                               }
+                                                       }
+                                                       else if(fac1 < fac2) {
+                                                               if(dia1.v1==eed->v1 && dia1.v2==eed->v2) {
+                                                                       eed->f1= 1;
+                                                                       efa= efaa[0];
+                                                                       efa->f1= 1;
+                                                                       efa= efaa[1];
+                                                                       efa->f1= 1;
+
+                                                                       w= addfacelist(v2, v3, v4, 0, efa, NULL);
+
+                                                                       UVCOPY(w->tf.uv[0], uv[1]);
+                                                                       UVCOPY(w->tf.uv[1], uv[3]);
+                                                                       UVCOPY(w->tf.uv[2], uv[4]);
+
+                                                                       w= addfacelist(v1, v2, v4, 0, efa, NULL);
+
+                                                                       UVCOPY(w->tf.uv[0], uv[0]);
+                                                                       UVCOPY(w->tf.uv[1], uv[1]);
+                                                                       UVCOPY(w->tf.uv[2], uv[3]);
+
+                                                                       onedone= 1;
+                                                               }
+                                                       }
                                                }
-                                               else if(test==11) { /* 1,2,&4 */
-                                                       addface_subdiv(efa, 4+4, 1+4, 2+4, 0, 0, &efapin);
-                                                       efa->v1= e4->vn;
-                                                       efa->v2= e2->vn;
-                                                       set_wuv(4, efa, 4+4, 2+4, 3, 4, &efapin);
+                    }
+                }
+
+            }
+            eed= nexted;
+        }
+
+        free_tagged_edgelist(em->edges.first);
+        free_tagged_facelist(em->faces.first);
+
+        if(onedone==0) break;
+               
+               EM_select_flush();      // new edges/faces were added
+    }
+
+    MEM_freeN(efaar);
+
+       EM_select_flush();
+       
+    allqueue(REDRAWVIEW3D, 0);
+    DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+       BIF_undo_push("Beauty Fill");
+}
+
+
+/* ******************** FLIP EDGE ************************************* */
+
+
+#define FACE_MARKCLEAR(f) (f->f1 = 1)
+
+void join_triangles(void)
+{
+       EditMesh *em = G.editMesh;
+       EditVert *v1, *v2, *v3, *v4;
+       EditFace *efa, *w;
+       EVPTuple *efaar;
+       EVPtr *efaa;
+       EditEdge *eed, *nexted;
+       int totedge, ok;
+       float *uv[4];
+       unsigned int col[4];
+
+       EM_selectmode_flush();  // makes sure in selectmode 'face' the edges of selected faces are selected too 
+       
+       totedge = count_selected_edges(em->edges.first);
+       if(totedge==0) return;
+
+       efaar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "jointris");
+
+       ok = collect_quadedges(efaar, em->edges.first, em->faces.first);
+       if (G.f & G_DEBUG) {
+               printf("Edges selected: %d\n", ok);
+       }       
+
+       eed= em->edges.first;
+       while(eed) {
+               nexted= eed->next;
+               
+               if(eed->f2==2) {  /* points to 2 faces */
+                       
+                       efaa= (EVPtr *) eed->vn;
+                       
+                       /* don't do it if flagged */
+
+                       ok= 1;
+                       efa= efaa[0];
+                       if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0;
+                       efa= efaa[1];
+                       if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0;
+                       
+                       if(ok) {
+                               /* test convex */
+                               givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, uv, col);
+
+/*
+               4-----3        4-----3
+               |\    |        |     |
+               | \ 1 |        |     |
+               |  \  |  ->    |     |  
+               | 0 \ |        |     | 
+               |    \|        |     |
+               1-----2        1-----2
+*/
+                               /* make new faces */
+                               if(v1 && v2 && v3 && v4) {
+                                       if( convex(v1->co, v2->co, v3->co, v4->co) ) {
+                                               if(exist_face(v1, v2, v3, v4)==0) {
+                                                       w = addfacelist(v1, v2, v3, v4, efaa[0], NULL); /* seam edge may get broken */
+                                                       w->f= efaa[0]->f;       /* copy selection flag */
+                                                       untag_edges(w);
+
+                                                       UVCOPY(w->tf.uv[0], uv[0]);
+                                                       UVCOPY(w->tf.uv[1], uv[1]);
+                                                       UVCOPY(w->tf.uv[2], uv[2]);
+                                                       UVCOPY(w->tf.uv[3], uv[3]);
+
+                                                       memcpy(w->tf.col, col, sizeof(w->tf.col));
                                                }
-                                       }
-                                       efa->e1= addedgelist(efa->v1, efa->v2, NULL);
-                                       efa->e2= addedgelist(efa->v2, efa->v3, NULL);
-                                       if(efa->v4) efa->e3= addedgelist(efa->v3, efa->v4, NULL);
-                                       else efa->e3= addedgelist(efa->v3, efa->v1, NULL);
-                                       if(efa->v4) efa->e4= addedgelist(efa->v4, efa->v1, NULL);
-                                       else efa->e4= NULL;
+                                               /* tag as to-be-removed */
+                                               FACE_MARKCLEAR(efaa[0]);
+                                               FACE_MARKCLEAR(efaa[1]);
+                                               eed->f1 = 1; 
+                                       } /* endif test convex */
                                }
                        }
                }
-               efa= efa->prev;
+               eed= nexted;
        }
+       free_tagged_edgelist(em->edges.first);
+       free_tagged_facelist(em->faces.first);
 
-       /* remove all old edges, if needed make new ones */
-       eed= em->edges.first;
-       while(eed) {
-               nexted= eed->next;
-               if( eed->vn ) {
-                       eed->vn->f |= 16;                       
-                       if(eed->f2==0) {  /* not used in face */                                
-                               addedgelist(eed->v1, eed->vn, eed);
-                               addedgelist(eed->vn, eed->v2, eed);
-                       }                                               
-                       remedge(eed);
-                       free_editedge(eed);
+       MEM_freeN(efaar);
+       
+       allqueue(REDRAWVIEW3D, 0);
+       DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+       BIF_undo_push("Convert Triangles to Quads");
+}
+
+/* quick hack, basically a copy of beauty_fill */
+void edge_flip(void)
+{
+       EditMesh *em = G.editMesh;
+       EditVert *v1, *v2, *v3, *v4;
+       EditEdge *eed, *nexted;
+       EditFace *efa, *w;
+       //void **efaar, **efaa;
+       EVPTuple *efaar;
+       EVPtr *efaa;
+
+       float *uv[4];
+       unsigned int col[4];
+
+       int totedge, ok;
+       
+       /* - all selected edges with two faces
+        * - find the faces: store them in edges (using datablock)
+        * - per edge: - test convex
+        *                         - test edge: flip?
+                                               - if true: remedge,  addedge, all edges at the edge get new face pointers
+        */
+
+       EM_selectmode_flush();  // makes sure in selectmode 'face' the edges of selected faces are selected too 
+
+       totedge = count_selected_edges(em->edges.first);
+       if(totedge==0) return;
+
+       /* temporary array for : edge -> face[1], face[2] */
+       efaar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "edgeflip");
+
+       ok = collect_quadedges(efaar, em->edges.first, em->faces.first);
+       
+       eed= em->edges.first;
+       while(eed) {
+               nexted= eed->next;
+               
+               if(eed->f2==2) {  /* points to 2 faces */
+                       
+                       efaa= (EVPtr *) eed->vn;
+                       
+                       /* don't do it if flagged */
+
+                       ok= 1;
+                       efa= efaa[0];
+                       if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0;
+                       efa= efaa[1];
+                       if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0;
+                       
+                       if(ok) {
+                               /* test convex */
+                               givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, uv, col);
+
+/*
+               4-----3        4-----3
+               |\    |        |    /|
+               | \ 1 |        | 1 / |
+               |  \  |  ->    |  /  |  
+               | 0 \ |        | / 0 | 
+               |    \|        |/    |
+               1-----2        1-----2
+*/
+                               /* make new faces */
+                               if (v1 && v2 && v3){
+                                       if( convex(v1->co, v2->co, v3->co, v4->co) ) {
+                                               if(exist_face(v1, v2, v3, v4)==0) {
+                                                       w = addfacelist(v1, v2, v3, 0, efaa[1], NULL); /* outch this may break seams */ 
+                                                       EM_select_face(w, 1);
+                                                       untag_edges(w);
+
+                                                       UVCOPY(w->tf.uv[0], uv[0]);
+                                                       UVCOPY(w->tf.uv[1], uv[1]);
+                                                       UVCOPY(w->tf.uv[2], uv[2]);
+
+                                                       w->tf.col[0] = col[0]; w->tf.col[1] = col[1]; w->tf.col[2] = col[2]; 
+                                                       
+                                                       w = addfacelist(v1, v3, v4, 0, efaa[1], NULL); /* outch this may break seams */
+                                                       EM_select_face(w, 1);
+                                                       untag_edges(w);
+
+                                                       UVCOPY(w->tf.uv[0], uv[0]);
+                                                       UVCOPY(w->tf.uv[1], uv[2]);
+                                                       UVCOPY(w->tf.uv[2], uv[3]);
+
+                                                       w->tf.col[0] = col[0]; w->tf.col[1] = col[2]; w->tf.col[2] = col[3]; 
+                                                       
+                                                       /* erase old faces and edge */
+                                               }
+                                               /* tag as to-be-removed */
+                                               FACE_MARKCLEAR(efaa[1]);
+                                               FACE_MARKCLEAR(efaa[0]);
+                                               eed->f1 = 1; 
+                                               
+                                       } /* endif test convex */
+                               }
+                       }
                }
                eed= nexted;
        }
+
+       /* clear tagged edges and faces: */
+       free_tagged_edgelist(em->edges.first);
+       free_tagged_facelist(em->faces.first);
+       
+       MEM_freeN(efaar);
+       
+       allqueue(REDRAWVIEW3D, 0);
+       DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+       BIF_undo_push("Flip Triangle Edges");
+       
+}
+
+static void edge_rotate(EditEdge *eed,int dir)
+{
+       EditMesh *em = G.editMesh;
+       EditFace *face[2], *efa, *newFace[2];
+       EditVert *faces[2][4],*v1,*v2,*v3,*v4,*vtemp;
+       EditEdge *srchedge = NULL;
+       short facecount=0, p1=0,p2=0,p3=0,p4=0,fac1=4,fac2=4,i,j,numhidden;
+    EditEdge **hiddenedges;
+    
+       /* check to make sure that the edge is only part of 2 faces */
+       for(efa = em->faces.first;efa;efa = efa->next){
+               if((efa->e1 == eed || efa->e2 == eed) || (efa->e3 == eed || efa->e4 == eed)){
+                       if(facecount == 2){
+                               return;
+                       }
+                       if(facecount < 2)
+                               face[facecount] = efa;
+                       facecount++;
+               }
+       }
+       if(facecount < 2){
+               return;
+       }
+
+       /* how many edges does each face have */
+       if(face[0]->e4 == NULL)
+               fac1=3;
+       else
+               fac1=4;
+       if(face[1]->e4 == NULL)
+               fac2=3;
+       else
+               fac2=4;
+       
+       /*store the face info in a handy array */                       
+       faces[0][0] =  face[0]->v1;
+       faces[0][1] =  face[0]->v2;
+       faces[0][2] =  face[0]->v3;
+       if(face[0]->e4 != NULL)
+               faces[0][3] =  face[0]->v4;
+       else
+               faces[0][3] = NULL;
+                       
+       faces[1][0] =  face[1]->v1;
+       faces[1][1] =  face[1]->v2;
+       faces[1][2] =  face[1]->v3;
+       if(face[1]->e4 != NULL)
+               faces[1][3] =  face[1]->v4;
+       else
+               faces[1][3] = NULL;
+       
+
+       /* we don't want to rotate edges between faces that share more than one edge */
+       
+       j=0;
+       if(face[0]->e1 == face[1]->e1 ||
+          face[0]->e1 == face[1]->e2 ||
+          face[0]->e1 == face[1]->e3 ||
+          ((face[1]->e4) && face[0]->e1 == face[1]->e4) )
+          j++;
+          
+       if(face[0]->e2 == face[1]->e1 ||
+          face[0]->e2 == face[1]->e2 ||
+          face[0]->e2 == face[1]->e3 ||
+          ((face[1]->e4) && face[0]->e2 == face[1]->e4) )
+          j++;
+          
+       if(face[0]->e3 == face[1]->e1 ||
+          face[0]->e3 == face[1]->e2 ||
+          face[0]->e3 == face[1]->e3 ||
+          ((face[1]->e4) && face[0]->e3 == face[1]->e4) )
+          j++;    
+
+       if(face[0]->e4){
+               if(face[0]->e4 == face[1]->e1 ||
+                  face[0]->e4 == face[1]->e2 ||
+                  face[0]->e4 == face[1]->e3 ||
+                  ((face[1]->e4) && face[0]->e4 == face[1]->e4) )
+                          j++; 
+        }                 
+       if(j > 1){
+               return;
+       }
+       
+       /* Coplaner Faces Only Please */
+       if(Inpf(face[0]->n,face[1]->n) <= 0.000001){    
+               return;
+       }
+       
+       /*get the edges verts */
+       v1 = eed->v1;
+       v2 = eed->v2;
+       v3 = eed->v1;
+       v4 = eed->v2;
+
+       /*figure out where the edges verts lie one the 2 faces */
+       for(i=0;i<4;i++){
+               if(v1 == faces[0][i])
+                       p1 = i;
+               if(v2 == faces[0][i])
+                       p2 = i;
+               if(v1 == faces[1][i])
+                       p3 = i;
+               if(v2 == faces[1][i])
+                       p4 = i;
+       }
+       
+       /*make sure the verts are in the correct order */
+       if((p1+1)%fac1 == p2){
+               vtemp = v2;
+               v2 = v1;
+               v1 = vtemp;
+               
+               i = p1;
+               p1 = p2;
+               p2 = i;
+       }
+       if((p3+1)%fac2 == p4){
+               vtemp = v4;
+               v4 = v3;
+               v3 = vtemp;
+               
+               i = p3;
+               p3 = p4;
+               p4 = i; 
+       }       
+
+
+    /* Create an Array of the Edges who have h set prior to rotate */
+    numhidden = 0;
+    for(srchedge = em->edges.first;srchedge;srchedge = srchedge->next){
+        if(srchedge->h){
+            numhidden++;
+        }
+    }
+       hiddenedges = MEM_mallocN(sizeof(EditVert*)*numhidden+1,"Hidden Vert Scratch Array for Rotate Edges");
+    numhidden = 0;
+    for(srchedge = em->edges.first;srchedge;srchedge = srchedge->next){
+        if(srchedge->h){
+            hiddenedges[numhidden] = srchedge;
+            numhidden++;
+        }
+    }  
+                                               
+       /* create the 2 new faces */                                                            
+       if(fac1 == 3 && fac2 == 3){
+               /*No need of reverse setup*/
+               newFace[0] = addfacelist(faces[0][(p1+1 )%3],faces[0][(p1+2 )%3],faces[1][(p3+1 )%3],NULL,NULL,NULL);
+               newFace[1] = addfacelist(faces[1][(p3+1 )%3],faces[1][(p3+2 )%3],faces[0][(p1+1 )%3],NULL,NULL,NULL);
+       
+               newFace[0]->tf.col[0] = face[0]->tf.col[(p1+1 )%3];
+               newFace[0]->tf.col[1] = face[0]->tf.col[(p1+2 )%3];
+               newFace[0]->tf.col[2] = face[1]->tf.col[(p3+1 )%3];
+               newFace[1]->tf.col[0] = face[1]->tf.col[(p3+1 )%3];
+               newFace[1]->tf.col[1] = face[1]->tf.col[(p3+2 )%3];
+               newFace[1]->tf.col[2] = face[0]->tf.col[(p1+1 )%3];
+       
+               UVCOPY(newFace[0]->tf.uv[0],face[0]->tf.uv[(p1+1 )%3]);
+               UVCOPY(newFace[0]->tf.uv[1],face[0]->tf.uv[(p1+2 )%3]); 
+               UVCOPY(newFace[0]->tf.uv[2],face[1]->tf.uv[(p3+1 )%3]);
+               UVCOPY(newFace[1]->tf.uv[0],face[1]->tf.uv[(p3+1 )%3]);
+               UVCOPY(newFace[1]->tf.uv[1],face[1]->tf.uv[(p3+2 )%3]);
+               UVCOPY(newFace[1]->tf.uv[2],face[0]->tf.uv[(p1+1 )%3]);
+       }
+       else if(fac1 == 4 && fac2 == 3){
+               if(dir == 1){
+                       newFace[0] = addfacelist(faces[0][(p1+1 )%4],faces[0][(p1+2 )%4],faces[0][(p1+3 )%4],faces[1][(p3+1 )%3],NULL,NULL);
+                       newFace[1] = addfacelist(faces[1][(p3+1 )%3],faces[1][(p3+2 )%3],faces[0][(p1+1 )%4],NULL,NULL,NULL);
+       
+                       newFace[0]->tf.col[0] = face[0]->tf.col[(p1+1 )%4];
+                       newFace[0]->tf.col[1] = face[0]->tf.col[(p1+2 )%4];
+                       newFace[0]->tf.col[2] = face[0]->tf.col[(p1+3 )%4];
+                       newFace[0]->tf.col[3] = face[1]->tf.col[(p3+1 )%3];
+                       newFace[1]->tf.col[0] = face[1]->tf.col[(p3+1 )%3];
+                       newFace[1]->tf.col[1] = face[1]->tf.col[(p3+2 )%3];
+                       newFace[1]->tf.col[2] = face[0]->tf.col[(p1+1 )%4];
+       
+                       UVCOPY(newFace[0]->tf.uv[0],face[0]->tf.uv[(p1+1 )%4]);
+                       UVCOPY(newFace[0]->tf.uv[1],face[0]->tf.uv[(p1+2 )%4]); 
+                       UVCOPY(newFace[0]->tf.uv[2],face[0]->tf.uv[(p1+3 )%4]);         
+                       UVCOPY(newFace[0]->tf.uv[3],face[1]->tf.uv[(p3+1 )%3]);
+                       UVCOPY(newFace[1]->tf.uv[0],face[1]->tf.uv[(p3+1 )%3]);
+                       UVCOPY(newFace[1]->tf.uv[1],face[1]->tf.uv[(p3+2 )%3]);
+                       UVCOPY(newFace[1]->tf.uv[2],face[0]->tf.uv[(p1+1 )%4]); 
+               } else if (dir == 2){
+                       newFace[0] = addfacelist(faces[0][(p1+2 )%4],faces[1][(p3+1)%3],faces[0][(p1)%4],faces[0][(p1+1 )%4],NULL,NULL);
+                       newFace[1] = addfacelist(faces[0][(p1+2 )%4],faces[1][(p3)%3],faces[1][(p3+1 )%3],NULL,NULL,NULL);
+
+                       newFace[0]->tf.col[0] = face[0]->tf.col[(p1+2)%4];
+                       newFace[0]->tf.col[1] = face[1]->tf.col[(p3+1)%3];
+                       newFace[0]->tf.col[2] = face[0]->tf.col[(p1  )%4];
+                       newFace[0]->tf.col[3] = face[0]->tf.col[(p1+1)%4];
+                       newFace[1]->tf.col[0] = face[0]->tf.col[(p1+2)%4];
+                       newFace[1]->tf.col[1] = face[1]->tf.col[(p3  )%3];
+                       newFace[1]->tf.col[2] = face[1]->tf.col[(p3+1)%3];
+       
+                       UVCOPY(newFace[0]->tf.uv[0],face[0]->tf.uv[(p1+2)%4]);
+                       UVCOPY(newFace[0]->tf.uv[1],face[1]->tf.uv[(p3+1)%3]);  
+                       UVCOPY(newFace[0]->tf.uv[2],face[0]->tf.uv[(p1  )%4]);          
+                       UVCOPY(newFace[0]->tf.uv[3],face[0]->tf.uv[(p1+1)%4]);
+                       UVCOPY(newFace[1]->tf.uv[0],face[0]->tf.uv[(p1+2)%4]);
+                       UVCOPY(newFace[1]->tf.uv[1],face[1]->tf.uv[(p3  )%3]);
+                       UVCOPY(newFace[1]->tf.uv[2],face[1]->tf.uv[(p3+1)%3]);  
+                       
+                       faces[0][(p1+2)%fac1]->f |= SELECT;
+                       faces[1][(p3+1)%fac2]->f |= SELECT;             
+               }
+       }
+
+       else if(fac1 == 3 && fac2 == 4){
+               if(dir == 1){
+                       newFace[0] = addfacelist(faces[0][(p1+1 )%3],faces[0][(p1+2 )%3],faces[1][(p3+1 )%4],NULL,NULL,NULL);
+                       newFace[1] = addfacelist(faces[1][(p3+1 )%4],faces[1][(p3+2 )%4],faces[1][(p3+3 )%4],faces[0][(p1+1 )%3],NULL,NULL);
+       
+                       newFace[0]->tf.col[0] = face[0]->tf.col[(p1+1 )%3];
+                       newFace[0]->tf.col[1] = face[0]->tf.col[(p1+2 )%3];
+                       newFace[0]->tf.col[2] = face[1]->tf.col[(p3+1 )%4];
+                       newFace[1]->tf.col[0] = face[1]->tf.col[(p3+1 )%4];
+                       newFace[1]->tf.col[1] = face[1]->tf.col[(p3+2 )%4];
+                       newFace[1]->tf.col[2] = face[1]->tf.col[(p3+3 )%4];             
+                       newFace[1]->tf.col[3] = face[0]->tf.col[(p1+1 )%3];
+       
+                       UVCOPY(newFace[0]->tf.uv[0],face[0]->tf.uv[(p1+1 )%3]);
+                       UVCOPY(newFace[0]->tf.uv[1],face[0]->tf.uv[(p1+2 )%3]); 
+                       UVCOPY(newFace[0]->tf.uv[2],face[1]->tf.uv[(p3+1 )%4]);
+                       UVCOPY(newFace[1]->tf.uv[0],face[1]->tf.uv[(p3+1 )%4]);
+                       UVCOPY(newFace[1]->tf.uv[1],face[1]->tf.uv[(p3+2 )%4]);
+                       UVCOPY(newFace[1]->tf.uv[2],face[1]->tf.uv[(p3+3 )%4]);
+                       UVCOPY(newFace[1]->tf.uv[3],face[0]->tf.uv[(p1+1 )%3]);
+               } else if (dir == 2){
+                       newFace[0] = addfacelist(faces[0][(p1)%3],faces[0][(p1+1 )%3],faces[1][(p3+2 )%4],NULL,NULL,NULL);
+                       newFace[1] = addfacelist(faces[1][(p3+1 )%4],faces[1][(p3+2 )%4],faces[0][(p1+1 )%3],faces[0][(p1+2 )%3],NULL,NULL);
+       
+                       newFace[0]->tf.col[0] = face[0]->tf.col[(p1 )%3];
+                       newFace[0]->tf.col[1] = face[0]->tf.col[(p1+1 )%3];
+                       newFace[0]->tf.col[2] = face[1]->tf.col[(p3+2 )%4];
+                       newFace[1]->tf.col[0] = face[1]->tf.col[(p3+1 )%4];
+                       newFace[1]->tf.col[1] = face[1]->tf.col[(p3+2 )%4];
+                       newFace[1]->tf.col[2] = face[0]->tf.col[(p1+1 )%3];             
+                       newFace[1]->tf.col[3] = face[0]->tf.col[(p1+2 )%3];
+       
+                       UVCOPY(newFace[0]->tf.uv[0],face[0]->tf.uv[(p1 )%3]);
+                       UVCOPY(newFace[0]->tf.uv[1],face[0]->tf.uv[(p1+1 )%3]); 
+                       UVCOPY(newFace[0]->tf.uv[2],face[1]->tf.uv[(p3+2 )%4]);
+                       UVCOPY(newFace[1]->tf.uv[0],face[1]->tf.uv[(p3+1 )%4]);
+                       UVCOPY(newFace[1]->tf.uv[1],face[1]->tf.uv[(p3+2 )%4]);
+                       UVCOPY(newFace[1]->tf.uv[2],face[0]->tf.uv[(p1+1 )%3]);
+                       UVCOPY(newFace[1]->tf.uv[3],face[0]->tf.uv[(p1+2 )%3]); 
+                       
+                       faces[0][(p1+1)%fac1]->f |= SELECT;
+                       faces[1][(p3+2)%fac2]->f |= SELECT;     
+               }
+       
+       }
+       
+       else if(fac1 == 4 && fac2 == 4){
+               if(dir == 1){
+            newFace[0] = addfacelist(faces[0][(p1+1 )%4],faces[0][(p1+2 )%4],faces[0][(p1+3 )%4],faces[1][(p3+1 )%4],NULL,NULL);
+            newFace[1] = addfacelist(faces[1][(p3+1 )%4],faces[1][(p3+2 )%4],faces[1][(p3+3 )%4],faces[0][(p1+1 )%4],NULL,NULL);
+       
+                       newFace[0]->tf.col[0] = face[0]->tf.col[(p1+1 )%4];
+                       newFace[0]->tf.col[1] = face[0]->tf.col[(p1+2 )%4];
+                       newFace[0]->tf.col[2] = face[0]->tf.col[(p1+3 )%4];
+                       newFace[0]->tf.col[3] = face[1]->tf.col[(p3+1 )%4];
+                       newFace[1]->tf.col[0] = face[1]->tf.col[(p3+1 )%4];
+                       newFace[1]->tf.col[1] = face[1]->tf.col[(p3+2 )%4];
+                       newFace[1]->tf.col[2] = face[1]->tf.col[(p3+3 )%4];             
+                       newFace[1]->tf.col[3] = face[0]->tf.col[(p1+1 )%4];
+                                                                       
+                       UVCOPY(newFace[0]->tf.uv[0],face[0]->tf.uv[(p1+1 )%4]);
+                       UVCOPY(newFace[0]->tf.uv[1],face[0]->tf.uv[(p1+2 )%4]); 
+                       UVCOPY(newFace[0]->tf.uv[2],face[0]->tf.uv[(p1+3 )%4]);         
+                       UVCOPY(newFace[0]->tf.uv[3],face[1]->tf.uv[(p3+1 )%4]);
+                       UVCOPY(newFace[1]->tf.uv[0],face[1]->tf.uv[(p3+1 )%4]);
+                       UVCOPY(newFace[1]->tf.uv[1],face[1]->tf.uv[(p3+2 )%4]);
+                       UVCOPY(newFace[1]->tf.uv[2],face[1]->tf.uv[(p3+3 )%4]);
+                       UVCOPY(newFace[1]->tf.uv[3],face[0]->tf.uv[(p1+1 )%4]);         
+               } else if (dir == 2){
+                       newFace[0] = addfacelist(faces[0][(p1+2 )%4],faces[0][(p1+3 )%4],faces[1][(p3+1 )%4],faces[1][(p3+2 )%4],NULL,NULL);
+                       newFace[1] = addfacelist(faces[1][(p3+2 )%4],faces[1][(p3+3 )%4],faces[0][(p1+1 )%4],faces[0][(p1+2 )%4],NULL,NULL);
+       
+                       newFace[0]->tf.col[0] = face[0]->tf.col[(p1+2 )%4];
+                       newFace[0]->tf.col[1] = face[0]->tf.col[(p1+3 )%4];
+                       newFace[0]->tf.col[2] = face[1]->tf.col[(p3+1 )%4];
+                       newFace[0]->tf.col[3] = face[1]->tf.col[(p3+2 )%4];
+                       newFace[1]->tf.col[0] = face[1]->tf.col[(p3+2 )%4];
+                       newFace[1]->tf.col[1] = face[1]->tf.col[(p3+3 )%4];
+                       newFace[1]->tf.col[2] = face[0]->tf.col[(p1+1 )%4];             
+                       newFace[1]->tf.col[3] = face[0]->tf.col[(p1+2 )%4];
+                                                                       
+                       UVCOPY(newFace[0]->tf.uv[0],face[0]->tf.uv[(p1+2 )%4]);
+                       UVCOPY(newFace[0]->tf.uv[1],face[0]->tf.uv[(p1+3 )%4]); 
+                       UVCOPY(newFace[0]->tf.uv[2],face[1]->tf.uv[(p3+1 )%4]);         
+                       UVCOPY(newFace[0]->tf.uv[3],face[1]->tf.uv[(p3+2 )%4]);
+                       UVCOPY(newFace[1]->tf.uv[0],face[1]->tf.uv[(p3+2 )%4]);
+                       UVCOPY(newFace[1]->tf.uv[1],face[1]->tf.uv[(p3+3 )%4]);
+                       UVCOPY(newFace[1]->tf.uv[2],face[0]->tf.uv[(p1+1 )%4]);
+                       UVCOPY(newFace[1]->tf.uv[3],face[0]->tf.uv[(p1+2 )%4]);         
+                       
+                       faces[0][(p1+2)%fac1]->f |= SELECT;
+                       faces[1][(p3+2)%fac2]->f |= SELECT;     
+               }
+               
+
+       }               
+       else{
+               /*This should never happen*/
+               return;
+       }
+
+       if(dir == 1){
+               faces[0][(p1+1)%fac1]->f |= SELECT;
+               faces[1][(p3+1)%fac2]->f |= SELECT;
+       }
+       
+       /*Copy old edge's flags to new center edge*/
+       for(srchedge=em->edges.first;srchedge;srchedge=srchedge->next){
+               if(srchedge->v1->f & SELECT &&srchedge->v2->f & SELECT  ){
+                       srchedge->f = eed->f;
+                       srchedge->h = eed->h;
+                       srchedge->dir = eed->dir;
+                       srchedge->seam = eed->seam;
+                       srchedge->crease = eed->crease;
+        }
+       }
+       
+       
+       /* copy flags and material */
+       
+       newFace[0]->mat_nr     = face[0]->mat_nr;
+       newFace[0]->tf.flag    = face[0]->tf.flag;
+       newFace[0]->tf.transp  = face[0]->tf.transp;
+       newFace[0]->tf.mode    = face[0]->tf.mode;
+       newFace[0]->tf.tile    = face[0]->tf.tile;
+       newFace[0]->tf.unwrap  = face[0]->tf.unwrap;
+       newFace[0]->tf.tpage   = face[0]->tf.tpage;
+       newFace[0]->flag       = face[0]->flag;
+
+       newFace[1]->mat_nr     = face[1]->mat_nr;
+       newFace[1]->tf.flag    = face[1]->tf.flag;
+       newFace[1]->tf.transp  = face[1]->tf.transp;
+       newFace[1]->tf.mode    = face[1]->tf.mode;
+       newFace[1]->tf.tile    = face[1]->tf.tile;
+       newFace[1]->tf.unwrap  = face[1]->tf.unwrap;
+       newFace[1]->tf.tpage   = face[1]->tf.tpage;
+       newFace[1]->flag       = face[1]->flag;
+       
+       /* Resetting Hidden Flag */
+       for(numhidden--;numhidden>=0;numhidden--){
+        hiddenedges[numhidden]->h = 1;
+           
+    }
+    
+    /* check for orhphan edges */
+    for(srchedge=em->edges.first;srchedge;srchedge = srchedge->next){
+        srchedge->f1 = -1;   
+    }
+    
+       /*for(efa = em->faces.first;efa;efa = efa->next){
+               if(efa->h == 0){
+            efa->e1->f1 = 1;   
+            efa->e2->f1 = 1;   
+            efa->e3->f1 = 1;   
+            if(efa->e4){
+                efa->e4->f1 = 1;   
+            }
+        }
+               if(efa->h == 1){
+            if(efa->e1->f1 == -1){
+                efa->e1->f1 = 0; 
+            }  
+            if(efa->e2->f1 == -1){
+                efa->e2->f1 = 0; 
+            } 
+                        if(efa->e1->f1 == -1){
+                efa->e1->f1 = 0; 
+            }    
+            if(efa->e4){
+                efa->e4->f1 = 1;   
+            }
+        }        
+       }
+        A Little Cleanup */
+       MEM_freeN(hiddenedges);
        
-       /* since this is all on vertex level, flush vertex selection */
-       EM_select_flush();
-       recalc_editnormals();
-       
-       countall();
-       allqueue(REDRAWVIEW3D, 0);
-       DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
-}
-
-static int count_selected_edges(EditEdge *ed)
-{
-       int totedge = 0;
-       while(ed) {
-               ed->vn= 0;
-               if( ed->f & SELECT ) totedge++;
-               ed= ed->next;
-       }
-       return totedge;
-}
-
-/* hurms, as if this makes code readable! It's pointerpointer hiding... (ton) */
-typedef EditFace *EVPtr;
-typedef EVPtr EVPTuple[2];
-
-/** builds EVPTuple array efaa of face tuples (in fact pointers to EditFaces)
-    sharing one edge.
-       arguments: selected edge list, face list.
-       Edges will also be tagged accordingly (see eed->f2)          */
+       /* get rid of the old edge and faces*/
+       remedge(eed);
+       free_editedge(eed);     
+       BLI_remlink(&em->faces, face[0]);
+       free_editface(face[0]); 
+       BLI_remlink(&em->faces, face[1]);
+       free_editface(face[1]);         
+       return;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
+}                                              
 
-static int collect_quadedges(EVPTuple *efaa, EditEdge *eed, EditFace *efa)
+/* only accepts 1 selected edge, or 2 selected faces */
+void edge_rotate_selected(int dir)
 {
-       int i = 0;
-       EditEdge *e1, *e2, *e3;
-       EVPtr *evp;
-
-       /* run through edges, if selected, set pointer edge-> facearray */
-       while(eed) {
-               eed->f2= 0;
+       EditEdge *eed;
+       EditFace *efa;
+       short edgeCount = 0;
+       
+       /*clear new flag for new edges, count selected edges */
+       for(eed= G.editMesh->edges.first; eed; eed= eed->next){