svn merge -r41638:41648 ^/trunk/blender
authorCampbell Barton <ideasman42@gmail.com>
Thu, 10 Nov 2011 01:50:22 +0000 (01:50 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 10 Nov 2011 01:50:22 +0000 (01:50 +0000)
1  2 
source/blender/blenkernel/intern/particle_system.c
source/blender/editors/armature/reeb.c
source/blender/editors/space_view3d/drawobject.c
source/blender/editors/space_view3d/view3d_snap.c
source/blender/editors/transform/transform.c
source/blender/editors/transform/transform_generics.c

index c759641f6a90ab24fd182676813515986e33befb,cb12230615ec70550b638af5355a2da641a923c2..0caad66622689655694459acc4b02bc59d35658c
@@@ -57,6 -57,7 +57,6 @@@
  #include "DNA_ipo_types.h" // XXX old animation system stuff... to be removed!
  #include "DNA_listBase.h"
  
 -#include "BLI_edgehash.h"
  #include "BLI_rand.h"
  #include "BLI_jitter.h"
  #include "BLI_math.h"
@@@ -66,8 -67,6 +66,8 @@@
  #include "BLI_threads.h"
  #include "BLI_utildefines.h"
  #include "BLI_linklist.h"
 +#include "BLI_edgehash.h"
 +#include "BLI_cellalloc.h"
  
  #include "BKE_main.h"
  #include "BKE_animsys.h"
@@@ -348,9 -347,9 +348,9 @@@ void psys_calc_dmcache(Object *ob, Deri
                        origindex= dm->getVertDataArray(dm, CD_ORIGINDEX);
                }
                else { /* FROM_FACE/FROM_VOLUME */
 -                      totdmelem= dm->getNumFaces(dm);
 +                      totdmelem= dm->getNumTessFaces(dm);
                        totelem= me->totface;
 -                      origindex= dm->getFaceDataArray(dm, CD_ORIGINDEX);
 +                      origindex= dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
                }
        
                nodedmelem= MEM_callocN(sizeof(LinkNode)*totdmelem, "psys node elems");
@@@ -519,8 -518,8 +519,8 @@@ static void distribute_grid(DerivedMes
                int a, a1, a2, a0mul, a1mul, a2mul, totface;
                int amax= from==PART_FROM_FACE ? 3 : 1;
  
 -              totface=dm->getNumFaces(dm);
 -              mface_array= dm->getFaceDataArray(dm,CD_MFACE);
 +              totface=dm->getNumTessFaces(dm);
 +              mface=mface_array=dm->getTessFaceDataArray(dm,CD_MFACE);
                
                for(a=0; a<amax; a++){
                        if(a==0){ a0mul=res*res; a1mul=res; a2mul=1; }
@@@ -779,7 -778,7 +779,7 @@@ static void distribute_threads_exec(Par
                MFace *mface;
  
                pa->num = i = ctx->index[p];
 -              mface = dm->getFaceData(dm,i,CD_MFACE);
 +              mface = dm->getTessFaceData(dm,i,CD_MFACE);
                
                switch(distr){
                case PART_DISTR_JIT:
                if(from==PART_FROM_VOLUME){
                        MVert *mvert=dm->getVertDataArray(dm,CD_MVERT);
  
 -                      tot=dm->getNumFaces(dm);
 +                      tot=dm->getNumTessFaces(dm);
  
                        psys_interpolate_face(mvert,mface,0,0,pa->fuv,co1,nor,0,0,0,0);
  
                        min_d=2.0;
                        intersect=0;
  
 -                      for(i=0,mface=dm->getFaceDataArray(dm,CD_MFACE); i<tot; i++,mface++){
 +                      for(i=0,mface=dm->getTessFaceDataArray(dm,CD_MFACE); i<tot; i++,mface++){
                                if(i==pa->num) continue;
  
                                v1=mvert[mface->v1].co;
                        return;
                }
  
 -              mf= dm->getFaceData(dm, ctx->index[p], CD_MFACE);
 +              mf= dm->getTessFaceData(dm, ctx->index[p], CD_MFACE);
  
                randu= rng_getFloat(thread->rng);
                randv= rng_getFloat(thread->rng);
@@@ -1036,7 -1035,7 +1036,7 @@@ static int distribute_threads_init_data
        if(totpart==0)
                return 0;
  
 -      if (!finaldm->deformedOnly && !finaldm->getFaceDataArray(finaldm, CD_ORIGINDEX)) {
 +      if (!finaldm->deformedOnly && !finaldm->getTessFaceDataArray(finaldm, CD_ORIGINDEX)) {
                printf("Can't create particles with the current modifier stack, disable destructive modifiers\n");
  // XXX                error("Can't paint with the current modifier stack, disable destructive modifiers");
                return 0;
        }
  
        /* Get total number of emission elements and allocate needed arrays */
 -      totelem = (from == PART_FROM_VERT) ? dm->getNumVerts(dm) : dm->getNumFaces(dm);
 +      totelem = (from == PART_FROM_VERT) ? dm->getNumVerts(dm) : dm->getNumTessFaces(dm);
  
        if(totelem == 0){
                distribute_invalid(scene, psys, children ? PART_FROM_CHILD : 0);
                orcodata= dm->getVertDataArray(dm, CD_ORCO);
  
                for(i=0; i<totelem; i++){
 -                      MFace *mf=dm->getFaceData(dm,i,CD_MFACE);
 +                      MFace *mf=dm->getTessFaceData(dm,i,CD_MFACE);
  
                        if(orcodata) {
                                copy_v3_v3(co1, orcodata[mf->v1]);
                }
                else { /* PART_FROM_FACE / PART_FROM_VOLUME */
                        for(i=0;i<totelem; i++){
 -                              MFace *mf=dm->getFaceData(dm,i,CD_MFACE);
 +                              MFace *mf=dm->getTessFaceData(dm,i,CD_MFACE);
                                tweight = vweight[mf->v1] + vweight[mf->v2] + vweight[mf->v3];
                                
                                if(mf->v4) {
                }
                else {
                        if(dm->numFaceData)
 -                              COMPARE_ORIG_INDEX= dm->getFaceDataArray(dm, CD_ORIGINDEX);
 +                              COMPARE_ORIG_INDEX= dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
                }
  
                if(COMPARE_ORIG_INDEX) {
@@@ -3177,7 -3176,7 +3177,7 @@@ static int collision_response(ParticleD
                                mul_v3_fl(v1_tan, 1.0f - 0.01f * frict);
  
                                /* surface_velocity is opposite to cm velocity */
-                               mul_v3_v3fl(vr_tan, v1_tan, -1.0f);
+                               negate_v3_v3(vr_tan, v1_tan);
  
                                /* get back to global coordinates */
                                add_v3_v3(v1_tan, vc_tan);
@@@ -3449,7 -3448,7 +3449,7 @@@ static void do_hair_dynamics(ParticleSi
        }
  
        if(!dm) {
 -              dm = psys->hair_in_dm = CDDM_new(totpoint, totedge, 0);
 +              dm = psys->hair_in_dm = CDDM_new(totpoint, totedge, 0, 0, 0);
                DM_add_vert_layer(dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
        }
  
  
                                if(dvert) {
                                        if(!dvert->totweight) {
 -                                              dvert->dw = MEM_callocN (sizeof(MDeformWeight), "deformWeight");
 +                                              dvert->dw = BLI_cellalloc_calloc(sizeof(MDeformWeight), "deformWeight");
                                                dvert->totweight = 1;
                                        }
  
  
                        if(dvert) {
                                if(!dvert->totweight) {
 -                                      dvert->dw = MEM_callocN (sizeof(MDeformWeight), "deformWeight");
 +                                      dvert->dw = BLI_cellalloc_calloc(sizeof(MDeformWeight), "deformWeight");
                                        dvert->totweight = 1;
                                }
                                /* roots should be 1.0, the rest can be anything from 0.0 to 1.0 */
index 2e5dafeb5071dafbfa45397450b5037b9eb2e7e7,ce4092b2b845c9ca63c663a6c85b05ae6300fc1d..c5c8b149713adf1c59c5c2763804827437f7732c
@@@ -55,7 -55,6 +55,7 @@@
  //#include "BIF_toolbox.h"
  //#include "BIF_graphics.h"
  
 +#include "BKE_mesh.h"
  
  //#include "blendef.h"
  
@@@ -3382,12 -3381,9 +3382,12 @@@ static int iteratorStopped(void *arg
  
  ReebGraph *BIF_ReebGraphMultiFromEditMesh(bContext *C)
  {
 +      (void)C;
 +      return NULL;
 +#if 0
        Scene *scene = CTX_data_scene(C);
        Object *obedit = CTX_data_edit_object(C);
 -      EditMesh *em =( (Mesh*)obedit->data)->edit_mesh;
 +      EditMesh *em =BKE_mesh_get_editmesh(((Mesh*)obedit->data));
        EdgeIndex indexed_edges;
        VertexData *data;
        ReebGraph *rg = NULL;
        
        MEM_freeN(data);
  
 +      /*no need to load the editmesh back into the object, just
 +        free it (avoids ngon conversion issues too going back the
 +                 other way)*/
 +      free_editMesh(em);
 +      MEM_freeN(em);
 +      
        return rg;
 +#endif
  }
  
  #if 0
@@@ -3695,7 -3684,7 +3695,7 @@@ void REEB_draw(
                
                if (G.scene->toolsettings->skgen_options & SKGEN_DISP_INDEX)
                {
-                       interp_v3_v3v3(vec, arc->head->p, arc->tail->p, 0.5f);
+                       mid_v3_v3v3(vec, arc->head->p, arc->tail->p);
                        s += sprintf(s, "%i (%i-%i-%i) ", i, arc->symmetry_level, arc->symmetry_flag, arc->symmetry_group);
                
                        if (G.scene->toolsettings->skgen_options & SKGEN_DISP_WEIGHT)
index a297f9bdf0fe4868aae66aa74a1f726111ed3134,f2bd4b51d94a9326d9c1774b513a6a41a26753f4..fbadf4d394ad9a7290e4e57e581b09aa5aac3e39
@@@ -47,7 -47,6 +47,7 @@@
  #include "DNA_world_types.h"
  #include "DNA_armature_types.h"
  
 +#include "BLI_utildefines.h"
  #include "BLI_blenlib.h"
  #include "BLI_math.h"
  #include "BLI_editVert.h"
@@@ -80,8 -79,6 +80,8 @@@
  #include "BKE_movieclip.h"
  #include "BKE_tracking.h"
  
 +#include "BKE_tessmesh.h"
 +
  #include "smoke_API.h"
  
  #include "IMB_imbuf.h"
@@@ -1889,18 -1886,16 +1889,18 @@@ static void drawlattice(Scene *scene, V
   * use the object matrix in the useual way */
  static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
  {
 -      struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
 -      EditVert *eve = EM_get_vert_for_index(index);
 +      struct { void (*func)(void *userData, BMVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData;
 +      BMVert *eve = EDBM_get_vert_for_index(data->vc.em, index);
  
 -      if (eve->h==0) {
 +      if (!BM_TestHFlag(eve, BM_HIDDEN)) {
                short s[2]= {IS_CLIPPED, 0};
  
                if (data->clipVerts) {
                        view3d_project_short_clip(data->vc.ar, co, s, 1);
                } else {
 -                      view3d_project_short_noclip(data->vc.ar, co, s);
 +                      float co2[2];
 +                      mul_v3_m4v3(co2, data->vc.obedit->obmat, co);
 +                      project_short_noclip(data->vc.ar, co2, s);
                }
  
                if (s[0]!=IS_CLIPPED)
        }
  }
  
 -void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
 +void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BMVert *eve, int x, int y, int index), void *userData, int clipVerts)
  {
 -      struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } data;
 -      DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
 +      struct { void (*func)(void *userData, BMVert *eve, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } data;
 +      DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
        
        data.vc= *vc;
        data.func = func;
        data.userData = userData;
        data.clipVerts = clipVerts;
  
 +      EDBM_init_index_arrays(vc->em, 1, 0, 0);
        if(clipVerts)
                ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
  
 -      EM_init_index_arrays(vc->em, 1, 0, 0);
        dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
 -      EM_free_index_arrays();
 +      EDBM_free_index_arrays(vc->em);
  
        dm->release(dm);
  }
@@@ -1956,23 -1951,17 +1956,23 @@@ static void drawSelectedVertices(Derive
  }
  static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
  {
 -      struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
 -      EditEdge *eed = EM_get_edge_for_index(index);
 -      short s[2][2];
 +      struct { void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData;
 +      BMEdge *eed = EDBM_get_edge_for_index(data->vc.em, index);
 +
 +      if (!BM_TestHFlag(eed, BM_HIDDEN)) {
 +              short s[2][2];
  
 -      if (eed->h==0) {
                if (data->clipVerts==1) {
                        view3d_project_short_clip(data->vc.ar, v0co, s[0], 1);
                        view3d_project_short_clip(data->vc.ar, v1co, s[1], 1);
                } else {
 -                      view3d_project_short_noclip(data->vc.ar, v0co, s[0]);
 -                      view3d_project_short_noclip(data->vc.ar, v1co, s[1]);
 +                      float v1_co[3], v2_co[3];
 +
 +                      mul_v3_m4v3(v1_co, data->vc.obedit->obmat, v0co);
 +                      mul_v3_m4v3(v2_co, data->vc.obedit->obmat, v1co);
 +
 +                      project_short_noclip(data->vc.ar, v1_co, s[0]);
 +                      project_short_noclip(data->vc.ar, v2_co, s[1]);
  
                        if (data->clipVerts==2) {
                                if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->vc.ar->winx && s[0][1]<data->vc.ar->winy))
        }
  }
  
 -void mesh_foreachScreenEdge(ViewContext *vc, void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts)
 +void mesh_foreachScreenEdge(ViewContext *vc, void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts)
  {
 -      struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } data;
 -      DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
 +      struct { void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; float pmat[4][4], vmat[4][4]; } data;
 +      DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
  
        data.vc= *vc;
        data.func = func;
        data.userData = userData;
        data.clipVerts = clipVerts;
  
 +      EDBM_init_index_arrays(vc->em, 0, 1, 0);
        if(clipVerts)
                ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
  
 -      EM_init_index_arrays(vc->em, 0, 1, 0);
        dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
 -      EM_free_index_arrays();
 +      EDBM_free_index_arrays(vc->em);
  
        dm->release(dm);
  }
  
  static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
  {
 -      struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } *data = userData;
 -      EditFace *efa = EM_get_face_for_index(index);
 -      short s[2];
 +      struct { void (*func)(void *userData, BMFace *efa, int x, int y, int index); void *userData; ViewContext vc; float pmat[4][4], vmat[4][4]; } *data = userData;
 +      BMFace *efa = EDBM_get_face_for_index(data->vc.em, index);
 +
 +      if (efa && !BM_TestHFlag(efa, BM_HIDDEN)) {
 +              float cent2[3];
 +              short s[2];
  
 -      if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
 -              view3d_project_short_clip(data->vc.ar, cent, s, 1);
 +              mul_v3_m4v3(cent2, data->vc.obedit->obmat, cent);
 +              project_short(data->vc.ar, cent2, s);
  
                if (s[0] != IS_CLIPPED) {
                        data->func(data->userData, efa, s[0], s[1], index);
        }
  }
  
 -void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
 +void mesh_foreachScreenFace(ViewContext *vc, void (*func)(void *userData, BMFace *efa, int x, int y, int index), void *userData)
  {
 -      struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ViewContext vc; } data;
 -      DerivedMesh *dm = editmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
 +      struct { void (*func)(void *userData, BMFace *efa, int x, int y, int index); void *userData; ViewContext vc; float pmat[4][4], vmat[4][4]; } data;
 +      DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
  
        data.vc= *vc;
        data.func = func;
        data.userData = userData;
  
 +      EDBM_init_index_arrays(vc->em, 0, 0, 1);
        //if(clipVerts)
        ED_view3d_local_clipping(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
  
 -      EM_init_index_arrays(vc->em, 0, 0, 1);
        dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
 -      EM_free_index_arrays();
 +      EDBM_free_index_arrays(vc->em);
  
        dm->release(dm);
  }
@@@ -2104,53 -2090,46 +2104,53 @@@ void nurbs_foreachScreenVert(ViewContex
  
  static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
  {
 -      ToolSettings *ts= ((Scene *)userData)->toolsettings;
 -      EditFace *efa = EM_get_face_for_index(index);
 +      Scene *scene= ((void **)userData)[0];
 +      BMEditMesh *em = ((void **)userData)[1];
 +      BMFace *efa = EDBM_get_face_for_index(em, index);
 +      ToolSettings *ts= scene->toolsettings;
  
 -      if (efa->h==0 && efa->fgonf!=EM_FGON) {
 +      if (!BM_TestHFlag(efa, BM_HIDDEN)) {
                glVertex3fv(cent);
                glVertex3f(     cent[0] + no[0]*ts->normalsize,
                                        cent[1] + no[1]*ts->normalsize,
                                        cent[2] + no[2]*ts->normalsize);
        }
  }
 -static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm) 
 +static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, DerivedMesh *dm) 
  {
 +      void *ptrs[2] = {scene, em};
 +
        glBegin(GL_LINES);
 -      dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene);
 +      dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, ptrs);
        glEnd();
  }
  
  static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *UNUSED(no))
  {
 -      EditFace *efa = EM_get_face_for_index(index);
 -      int sel = *((int*) userData);
 -
 -      if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
 +      BMFace *efa = EDBM_get_face_for_index(((void **)userData)[0], index);
 +      int sel = *(((int **)userData)[1]);
 +      
 +      if (efa && !BM_TestHFlag(efa, BM_HIDDEN) && BM_TestHFlag(efa, BM_SELECT)==sel) {
                bglVertex3fv(cent);
        }
  }
 -static void draw_dm_face_centers(DerivedMesh *dm, int sel)
 +static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, int sel)
  {
 +      void *ptrs[2] = {em, &sel};
 +
        bglBegin(GL_POINTS);
 -      dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
 +      dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, ptrs);
        bglEnd();
  }
  
  static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
  {
 -      Scene *scene= (Scene *)userData;
 +      Scene *scene= ((void **)userData)[0];
        ToolSettings *ts= scene->toolsettings;
 -      EditVert *eve = EM_get_vert_for_index(index);
 +      BMEditMesh *em = ((void **)userData)[1];
 +      BMVert *eve = EDBM_get_vert_for_index(em, index);
  
 -      if (eve->h==0) {
 +      if (!BM_TestHFlag(eve, BM_HIDDEN)) {
                glVertex3fv(co);
  
                if (no_f) {
                }
        }
  }
 -static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm) 
 +static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, DerivedMesh *dm) 
  {
 +      void *ptrs[2] = {scene, em};
 +
        glBegin(GL_LINES);
 -      dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene);
 +      dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, ptrs);
        glEnd();
  }
  
 -      /* Draw verts with color set based on selection */
 +/* Draw verts with color set based on selection */
  static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
  {
 -      struct { int sel; EditVert *eve_act; } * data = userData;
 -      EditVert *eve = EM_get_vert_for_index(index);
 +      struct { BMEditMesh *em; int sel; BMVert *eve_act; } *data = userData;
 +      BMVert *eve = EDBM_get_vert_for_index(data->em, index);
  
 -      if (eve->h==0 && (eve->f&SELECT)==data->sel) {
 +      if (!BM_TestHFlag(eve, BM_HIDDEN) && BM_TestHFlag(eve, BM_SELECT)==data->sel) {
                /* draw active larger - need to stop/start point drawing for this :/ */
                if (eve==data->eve_act) {
                        float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
        }
  }
  
 -static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
 +static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, int sel, BMVert *eve_act)
  {
 -      struct { int sel; EditVert *eve_act; } data;
 +      struct { BMEditMesh *em; int sel; BMVert *eve_act; } data;
        data.sel = sel;
        data.eve_act = eve_act;
 +      data.em = em;
 +      
 +      bglBegin(GL_POINTS);
 +      dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
 +      bglEnd();
  
        bglBegin(GL_POINTS);
        dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
        /* Draw edges with color set based on selection */
  static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
  {
 -      EditEdge *eed = EM_get_edge_for_index(index);
 +      BMEdge *eed;
        //unsigned char **cols = userData, *col;
 -      struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
 +      struct { BMEditMesh *em; unsigned char *baseCol, *selCol, *actCol; BMEdge *eed_act; } * data = userData;
        unsigned char *col;
  
 -      if (eed->h==0) {
 +      eed = EDBM_get_edge_for_index(data->em, index);
 +
 +      if (!BM_TestHFlag(eed, BM_HIDDEN)) {
                if (eed==data->eed_act) {
                        glColor4ubv(data->actCol);
                } else {
 -                      if (eed->f&SELECT) {
 +                      if (BM_TestHFlag(eed, BM_SELECT)) {
                                col = data->selCol;
                        } else {
                                col = data->baseCol;
                return 0;
        }
  }
 -static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act) 
 +static void draw_dm_edges_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, 
 +                            unsigned char *selCol, unsigned char *actCol, BMEdge *eed_act) 
  {
 -      struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
 +      struct { BMEditMesh *em; unsigned char *baseCol, *selCol, *actCol; BMEdge *eed_act; } data;
        
        data.baseCol = baseCol;
        data.selCol = selCol;
        data.actCol = actCol;
 +      data.em = em;
        data.eed_act = eed_act;
        dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
  }
  
        /* Draw edges */
 -static int draw_dm_edges__setDrawOptions(void *UNUSED(userData), int index)
 +static int draw_dm_edges__setDrawOptions(void *userData, int index)
  {
 -      return EM_get_edge_for_index(index)->h==0;
 +      return !BM_TestHFlag(EDBM_get_edge_for_index(userData, index), BM_HIDDEN);
  }
 -static void draw_dm_edges(DerivedMesh *dm) 
 +static void draw_dm_edges(BMEditMesh *em, DerivedMesh *dm) 
  {
 -      dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
 +      dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, em);
  }
  
        /* Draw edges with color interpolated based on selection */
 -static int draw_dm_edges_sel_interp__setDrawOptions(void *UNUSED(userData), int index)
 +static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
  {
 -      return EM_get_edge_for_index(index)->h==0;
 +      return !BM_TestHFlag(EDBM_get_edge_for_index(((void**)userData)[0], index), BM_HIDDEN);
  }
  static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
  {
 -      EditEdge *eed = EM_get_edge_for_index(index);
 +      BMEdge *eed = EDBM_get_edge_for_index(((void**)userData)[0], index);
        unsigned char **cols = userData;
 -      unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
 -      unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
 +      unsigned char *col0 = cols[(BM_TestHFlag(eed->v1, BM_SELECT))?2:1];
 +      unsigned char *col1 = cols[(BM_TestHFlag(eed->v2, BM_SELECT))?2:1];
  
        glColor4ub(     col0[0] + (col1[0]-col0[0])*t,
                                col0[1] + (col1[1]-col0[1])*t,
                                col0[3] + (col1[3]-col0[3])*t);
  }
  
 -static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
 +static void draw_dm_edges_sel_interp(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
  {
 -      unsigned char *cols[2];
 -      cols[0]= baseCol;
 -      cols[1]= selCol;
 +      void *cols[3] = {em, baseCol, selCol};
 +
        dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
  }
  
        /* Draw only seam edges */
 -static int draw_dm_edges_seams__setDrawOptions(void *UNUSED(userData), int index)
 +static int draw_dm_edges_seams__setDrawOptions(void *userData, int index)
  {
 -      EditEdge *eed = EM_get_edge_for_index(index);
 +      BMEdge *eed = EDBM_get_edge_for_index(userData, index);
  
 -      return (eed->h==0 && eed->seam);
 +      return !BM_TestHFlag(eed, BM_HIDDEN) && BM_TestHFlag(eed, BM_SEAM);
  }
 -static void draw_dm_edges_seams(DerivedMesh *dm)
 +
 +static void draw_dm_edges_seams(BMEditMesh *em, DerivedMesh *dm)
  {
 -      dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
 +      dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, em);
  }
  
        /* Draw only sharp edges */
 -static int draw_dm_edges_sharp__setDrawOptions(void *UNUSED(userData), int index)
 +static int draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
  {
 -      EditEdge *eed = EM_get_edge_for_index(index);
 +      BMEdge *eed = EDBM_get_edge_for_index(userData, index);
  
 -      return (eed->h==0 && eed->sharp);
 +      return !BM_TestHFlag(eed, BM_HIDDEN) && BM_TestHFlag(eed, BM_SHARP);
  }
 -static void draw_dm_edges_sharp(DerivedMesh *dm)
 +static void draw_dm_edges_sharp(BMEditMesh *em, DerivedMesh *dm)
  {
 -      dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
 +      dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, em);
  }
  
  
         * return 2 for the active face so it renders with stipple enabled */
  static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
  {
 -      struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
 -      EditFace *efa = EM_get_face_for_index(index);
 +      struct { unsigned char *cols[3]; BMEditMesh *em; BMFace *efa_act; Mesh *me;} *data = userData;
 +      BMFace *efa = EDBM_get_face_for_index(data->em, index);
        unsigned char *col;
        
 -      if (efa->h==0) {
 +      if (!efa)
 +              return 0;
 +      
 +      if (!BM_TestHFlag(efa, BM_HIDDEN)) {
                if (efa == data->efa_act) {
                        glColor4ubv(data->cols[2]);
                        return 2; /* stipple */
                } else {
 -                      col = data->cols[(efa->f&SELECT)?1:0];
 +                      col = data->cols[BM_TestHFlag(efa, BM_SELECT)?1:0];
                        if (col[3]==0) return 0;
                        glColor4ubv(col);
                        return 1;
  
  static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
  {
 -      struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
 -      EditFace *efa = EM_get_face_for_index(index);
 -      EditFace *next_efa = EM_get_face_for_index(next_index);
 +      struct { unsigned char *cols[3]; BMEditMesh *em; BMFace *efa_act; Mesh *me;} * data = userData;
 +      BMFace *efa = EDBM_get_face_for_index(data->em, index);
 +      BMFace *next_efa = EDBM_get_face_for_index(data->em, next_index);
        unsigned char *col, *next_col;
  
        if(efa == next_efa)
        if(efa == data->efa_act || next_efa == data->efa_act)
                return 0;
  
 -      col = data->cols[(efa->f&SELECT)?1:0];
 -      next_col = data->cols[(next_efa->f&SELECT)?1:0];
 +      col = data->cols[BM_TestHFlag(efa, BM_SELECT)?1:0];
 +      next_col = data->cols[BM_TestHFlag(next_efa, BM_SELECT)?1:0];
  
        if(col[3]==0 || next_col[3]==0)
                return 0;
  }
  
  /* also draws the active face */
 -static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act) 
 +static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, 
 +                            unsigned char *selCol, unsigned char *actCol, BMFace *efa_act, Mesh *me) 
  {
 -      struct { unsigned char *cols[3]; EditFace *efa_act; } data;
 +      struct { unsigned char *cols[3]; BMEditMesh *em; BMFace *efa_act; Mesh *me;} data;
 +
        data.cols[0] = baseCol;
 +      data.em = em;
        data.cols[1] = selCol;
        data.cols[2] = actCol;
        data.efa_act = efa_act;
 +      data.me = me;
  
        dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions);
  }
  
 -static int draw_dm_creases__setDrawOptions(void *UNUSED(userData), int index)
 +static int draw_dm_creases__setDrawOptions(void *userData, int index)
  {
 -      EditEdge *eed = EM_get_edge_for_index(index);
 -
 -      if (eed->h==0 && eed->crease != 0.0f) {
 -              UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, eed->crease);
 +      BMEditMesh *em = userData;
 +      BMEdge *eed = EDBM_get_edge_for_index(userData, index);
 +      float *crease = eed ? bm_get_cd_float(&em->bm->edata, eed->head.data, CD_CREASE) : NULL;
 +      
 +      if (!crease)
 +              return 0;
 +      
 +      if (!BM_TestHFlag(eed, BM_HIDDEN) && *crease!=0.0f) {
 +              UI_ThemeColorBlend(TH_WIRE, TH_EDGE_CREASE, *crease);
                return 1;
        } else {
                return 0;
        }
  }
 -static void draw_dm_creases(DerivedMesh *dm)
 +static void draw_dm_creases(BMEditMesh *em, DerivedMesh *dm)
  {
        glLineWidth(3.0);
 -      dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
 +      dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, em);
        glLineWidth(1.0);
  }
  
 -static int draw_dm_bweights__setDrawOptions(void *UNUSED(userData), int index)
 +static int draw_dm_bweights__setDrawOptions(void *userData, int index)
  {
 -      EditEdge *eed = EM_get_edge_for_index(index);
 +      BMEditMesh *em = userData;
 +      BMEdge *eed = EDBM_get_edge_for_index(userData, index);
 +      float *bweight = bm_get_cd_float(&em->bm->edata, eed->head.data, CD_BWEIGHT);
  
 -      if (eed->h==0 && eed->bweight != 0.0f) {
 -              UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
 +      if (!bweight)
 +              return 0;
 +      
 +      if (!BM_TestHFlag(eed, BM_HIDDEN) && *bweight!=0.0f) {
 +              UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, *bweight);
                return 1;
        } else {
                return 0;
        }
  }
 -static void draw_dm_bweights__mapFunc(void *UNUSED(userData), int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
 +static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
  {
 -      EditVert *eve = EM_get_vert_for_index(index);
 -
 -      if (eve->h==0 && eve->bweight != 0.0f) {
 -              UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
 +      BMEditMesh *em = userData;
 +      BMVert *eve = EDBM_get_vert_for_index(userData, index);
 +      float *bweight = bm_get_cd_float(&em->bm->vdata, eve->head.data, CD_BWEIGHT);
 +      
 +      if (!bweight)
 +              return;
 +      
 +      if (!BM_TestHFlag(eve, BM_HIDDEN) && *bweight!=0.0f) {
 +              UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, *bweight);
                bglVertex3fv(co);
        }
  }
 -static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
 +static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
  {
        ToolSettings *ts= scene->toolsettings;
  
        if (ts->selectmode & SCE_SELECT_VERTEX) {
                glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
                bglBegin(GL_POINTS);
 -              dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
 +              dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, em);
                bglEnd();
        }
        else {
                glLineWidth(3.0);
 -              dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
 +              dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, em);
                glLineWidth(1.0);
        }
  }
  
  /* EditMesh drawing routines*/
  
 -static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, DerivedMesh *cageDM, EditVert *eve_act)
 +static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, 
 +                              BMEditMesh *em, DerivedMesh *cageDM, BMVert *eve_act)
  {
        ToolSettings *ts= scene->toolsettings;
        int sel;
                        if(ts->selectmode & SCE_SELECT_VERTEX) {
                                glPointSize(size);
                                glColor4ubv(col);
 -                              draw_dm_verts(cageDM, sel, eve_act);
 +                              draw_dm_verts(em, cageDM, sel, eve_act);
                        }
                        
                        if(check_ob_drawface_dot(scene, v3d, obedit->dt)) {
                                glPointSize(fsize);
                                glColor4ubv(fcol);
 -                              draw_dm_face_centers(cageDM, sel);
 +                              draw_dm_face_centers(em, cageDM, sel);
                        }
                        
                        if (pass==0) {
        glPointSize(1.0);
  }
  
 -static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
 +static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d, 
 +                              Mesh *me, DerivedMesh *cageDM, short sel_only, 
 +                              BMEdge *eed_act)
  {
        ToolSettings *ts= scene->toolsettings;
        int pass;
                }
  
                if(ts->selectmode == SCE_SELECT_FACE) {
 -                      draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
 +                      draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
                }       
                else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {        
                        if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
                                glShadeModel(GL_SMOOTH);
 -                              draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
 +                              draw_dm_edges_sel_interp(em, cageDM, wireCol, selCol);
                                glShadeModel(GL_FLAT);
                        } else {
 -                              draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
 +                              draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
                        }
                }
                else {
                        if (!sel_only) {
                                glColor4ubv(wireCol);
 -                              draw_dm_edges(cageDM);
 +                              draw_dm_edges(em, cageDM);
                        }
                }
  
        }
  }     
  
 -static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, UnitSettings *unit)
 +static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, 
 +                                Object *ob, BMEditMesh *em, UnitSettings *unit)
  {
        Mesh *me= ob->data;
 -      EditEdge *eed;
 -      EditFace *efa;
 -      float v1[3], v2[3], v3[3], v4[3], vmid[3];
 -      float fvec[3];
 +      float v1[3], v2[3], v3[3], vmid[3], fvec[3];
        char val[32]; /* Stores the measurement display text here */
        const char *conv_float; /* Use a float conversion matching the grid size */
        unsigned char col[4]= {0, 0, 0, 255}; /* color of the text to draw */
        const int do_global= v3d->flag & V3D_GLOBAL_STATS;
        const int do_moving= G.moving;
  
 +      BMIter iter;
 +      int i;
 +
        /* make the precision of the pronted value proportionate to the gridsize */
  
        if (grid < 0.01f)               conv_float= "%.6g";
        if(v3d->zbuf) bglPolygonOffset(rv3d->dist, 5.0f);
        
        if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
 +              BMEdge *eed;
 +
                UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
  
 -              for(eed= em->edges.first; eed; eed= eed->next) {
 -                      /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
 -                      if((eed->h != EM_FGON) && ((eed->f & SELECT) || (do_moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
 +              eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
 +              for(; eed; eed=BMIter_Step(&iter)) {
 +                      /* draw selected edges, or edges next to selected verts while draging */
 +                      if(BM_TestHFlag(eed, BM_SELECT) ||
 +                              (do_moving && (BM_TestHFlag(eed->v1, BM_SELECT) || BM_TestHFlag(eed->v2, BM_SELECT) ))) {
 +
                                copy_v3_v3(v1, eed->v1->co);
                                copy_v3_v3(v2, eed->v2->co);
  
-                               interp_v3_v3v3(vmid, v1, v2, 0.5f);
+                               mid_v3_v3v3(vmid, v1, v2);
  
                                if(do_global) {
                                        mul_mat3_m4_v3(ob->obmat, v1);
        }
  
        if(me->drawflag & ME_DRAWEXTRA_FACEAREA) {
 -// XXX                extern int faceselectedOR(EditFace *efa, int flag);             // editmesh.h shouldn't be in this file... ok for now?
 +              /* would be nice to use BM_face_area, but that is for 2d faces
 +              so instead add up tessalation triangle areas */
 +              BMFace *f;
 +              int n;
 +
 +#define DRAW_EM_MEASURE_STATS_FACEAREA()\
 +              if (BM_TestHFlag(f, BM_SELECT)) {\
 +                      mul_v3_fl(vmid, 1.0/n);\
 +                      if(unit->system)\
 +                              bUnit_AsString(val, sizeof(val), area*unit->scale_length,\
 +                                      3, unit->system, B_UNIT_LENGTH, do_split, FALSE);\
 +                      else\
 +                              sprintf(val, conv_float, area);\
 +                      view3d_cached_text_draw_add(vmid, val, 0, V3D_CACHE_TEXT_ASCII, col);\
 +              }
 +
                UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
                
 -              for(efa= em->faces.first; efa; efa= efa->next) {
 -                      if((efa->f & SELECT)) { // XXX || (do_moving && faceselectedOR(efa, SELECT)) ) {
 -                              copy_v3_v3(v1, efa->v1->co);
 -                              copy_v3_v3(v2, efa->v2->co);
 -                              copy_v3_v3(v3, efa->v3->co);
 -                              if (efa->v4) {
 -                                      copy_v3_v3(v4, efa->v4->co);
 -                              }
 -                              if(do_global) {
 -                                      mul_mat3_m4_v3(ob->obmat, v1);
 -                                      mul_mat3_m4_v3(ob->obmat, v2);
 -                                      mul_mat3_m4_v3(ob->obmat, v3);
 -                                      if (efa->v4) mul_mat3_m4_v3(ob->obmat, v4);
 -                              }
 -                              
 -                              if (efa->v4)
 -                                      area=  area_quad_v3(v1, v2, v3, v4);
 -                              else
 -                                      area = area_tri_v3(v1, v2, v3);
 -
 -                              if(unit->system)
 -                                      bUnit_AsString(val, sizeof(val), area*unit->scale_length, 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); // XXX should be B_UNIT_AREA
 -                              else
 -                                      sprintf(val, conv_float, area);
 -
 -                              view3d_cached_text_draw_add(efa->cent, val, 0, V3D_CACHE_TEXT_ASCII, col);
 +              f = NULL;
 +              area = 0.0;
 +              zero_v3(vmid);
 +              n = 0;
 +              for(i = 0; i < em->tottri; i++) {
 +                      BMLoop **l = em->looptris[i];
 +                      if(f && l[0]->f != f) {
 +                              DRAW_EM_MEASURE_STATS_FACEAREA();
 +                              zero_v3(vmid);
 +                              area = 0.0;
 +                              n = 0;
                        }
 -              }
 -      }
  
 -      if(me->drawflag & ME_DRAWEXTRA_FACEANG) {
 -              EditEdge *e1, *e2, *e3, *e4;
 -              UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
 -              for(efa= em->faces.first; efa; efa= efa->next) {
 -                      copy_v3_v3(v1, efa->v1->co);
 -                      copy_v3_v3(v2, efa->v2->co);
 -                      copy_v3_v3(v3, efa->v3->co);
 -                      if(efa->v4) {
 -                              copy_v3_v3(v4, efa->v4->co); 
 -                      }
 -                      else {
 -                              copy_v3_v3(v4, v3);
 -                      }
 +                      f = l[0]->f;
 +                      copy_v3_v3(v1, l[0]->v->co);
 +                      copy_v3_v3(v2, l[1]->v->co);
 +                      copy_v3_v3(v3, l[2]->v->co);
                        if(do_global) {
                                mul_mat3_m4_v3(ob->obmat, v1);
                                mul_mat3_m4_v3(ob->obmat, v2);
                                mul_mat3_m4_v3(ob->obmat, v3);
 -                              mul_mat3_m4_v3(ob->obmat, v4); /* intentionally executed even for tri's */
                        }
 -                      
 -                      e1= efa->e1;
 -                      e2= efa->e2;
 -                      e3= efa->e3;
 -                      if(efa->e4) e4= efa->e4; else e4= e3;
 -                      
 -                      /* Calculate the angles */
 -                              
 -                      if( (e4->f & e1->f & SELECT) || (do_moving && (efa->v1->f & SELECT)) ) {
 -                              /* Vec 1 */
 -                              sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v4, v1, v2)));
 -                              interp_v3_v3v3(fvec, efa->cent, efa->v1->co, 0.8f);
 -                              view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
 -                      }
 -                      if( (e1->f & e2->f & SELECT) || (do_moving && (efa->v2->f & SELECT)) ) {
 -                              /* Vec 2 */
 -                              sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
 -                              interp_v3_v3v3(fvec, efa->cent, efa->v2->co, 0.8f);
 -                              view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
 -                      }
 -                      if( (e2->f & e3->f & SELECT) || (do_moving && (efa->v3->f & SELECT)) ) {
 -                              /* Vec 3 */
 -                              if(efa->v4) 
 -                                      sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v4)));
 -                              else
 -                                      sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v2, v3, v1)));
 -                              interp_v3_v3v3(fvec, efa->cent, efa->v3->co, 0.8f);
 -                              view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
 -                      }
 -                              /* Vec 4 */
 -                      if(efa->v4) {
 -                              if( (e3->f & e4->f & SELECT) || (do_moving && (efa->v4->f & SELECT)) ) {
 -                                      sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v3, v4, v1)));
 -                                      interp_v3_v3v3(fvec, efa->cent, efa->v4->co, 0.8f);
 +                      area += area_tri_v3(v1, v2, v3);
 +                      add_v3_v3(vmid, v1);
 +                      add_v3_v3(vmid, v2);
 +                      add_v3_v3(vmid, v3);
 +                      n += 3;
 +              }
 +
 +              if(f){
 +                      DRAW_EM_MEASURE_STATS_FACEAREA();
 +              }
 +#undef DRAW_EM_MEASURE_STATS_FACEAREA
 +      }
 +
 +      if(me->drawflag & ME_DRAWEXTRA_FACEANG) {
 +              BMFace *efa;
 +
 +              UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
 +
 +
 +              for(efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
 +                  efa; efa=BMIter_Step(&iter)) {
 +                      BMIter liter;
 +                      BMLoop *loop;
 +
 +                      BM_Compute_Face_Center(em->bm, efa, vmid);
 +
 +                      for(loop = BMIter_New(&liter, em->bm, BM_LOOPS_OF_FACE, efa);
 +                          loop; loop = BMIter_Step(&liter)) {
 +
 +                              float v1[3], v2[3], v3[3];
 +
 +                              copy_v3_v3(v1, loop->prev->v->co);
 +                              copy_v3_v3(v2, loop->v->co);
 +                              copy_v3_v3(v3, loop->next->v->co);
 +
 +                              if(do_global){
 +                                      mul_mat3_m4_v3(ob->obmat, v1);
 +                                      mul_mat3_m4_v3(ob->obmat, v2);
 +                                      mul_mat3_m4_v3(ob->obmat, v3);
 +                              }
 +
 +                              if(BM_TestHFlag(efa, BM_SELECT) ||
 +                                      (do_moving && BM_TestHFlag(loop->v, BM_SELECT))){
 +                                      sprintf(val,"%.3g", RAD2DEGF(angle_v3v3v3(v1, v2, v3)));
 +                                      interp_v3_v3v3(fvec, vmid, v2, 0.8f);
                                        view3d_cached_text_draw_add(fvec, val, 0, V3D_CACHE_TEXT_ASCII, col);
                                }
                        }
        /* useful for debugging index vs shape key index */
  #if 0
        {
 -              EditVert *eve;
 -              int j;
 +              BMIter iter;
 +              BMVert *eve;
 +              int j=0;
 +
                UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
 -              for(eve= em->verts.first, j= 0; eve; eve= eve->next, j++) {
 -                      sprintf(val, "%d:%d", j, eve->keyindex);
 -                      view3d_cached_text_draw_add(eve->co, val, 0, V3D_CACHE_TEXT_ASCII, col);
 +
 +              if(CustomData_has_layer(&em->bm->vdata, CD_SHAPE_KEYINDEX)) {
 +                      int *keyi;
 +                      BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
 +                              keyi = CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_SHAPE_KEYINDEX);
 +                              if(keyi && *keyi != ORIGINDEX_NONE) {
 +                                      sprintf(val, "%d:%d", j, *keyi);
 +                              }
 +                              else {
 +                                      sprintf(val, "%d", j);
 +                              }
 +                              view3d_cached_text_draw_add(eve->co, val, 0, V3D_CACHE_TEXT_ASCII, col);
 +                              i++;
 +                      }
 +              }
 +              else {
 +                      BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
 +                              sprintf(val, "%d", j);
 +                              view3d_cached_text_draw_add(eve->co, val, 0, V3D_CACHE_TEXT_ASCII, col);
 +                              j++;
 +                      }
                }
        }
  #endif
        }
  }
  
 -static int draw_em_fancy__setFaceOpts(void *UNUSED(userData), int index, int *UNUSED(drawSmooth_r))
 +static int draw_em_fancy__setFaceOpts(void *userData, int index, int *UNUSED(drawSmooth_r))
  {
 -      EditFace *efa = EM_get_face_for_index(index);
 +      BMFace *efa = EDBM_get_face_for_index(userData, index);
  
 -      if (efa->h==0) {
 +      if (efa && !BM_TestHFlag(efa, BM_HIDDEN)) {
                GPU_enable_material(efa->mat_nr+1, NULL);
                return 1;
        }
                return 0;
  }
  
 -static int draw_em_fancy__setGLSLFaceOpts(void *UNUSED(userData), int index)
 +static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
  {
 -      EditFace *efa = EM_get_face_for_index(index);
 +      BMFace *efa = EDBM_get_face_for_index(userData, index);
  
 -      return (efa->h==0);
 +      return !BM_TestHFlag(efa, BM_HIDDEN);
  }
  
 -static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
 +static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob,
 +                        BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
 +
  {
        Mesh *me = ob->data;
 -      EditFace *efa_act = EM_get_actFace(em, 0); /* annoying but active faces is stored differently */
 -      EditEdge *eed_act = NULL;
 -      EditVert *eve_act = NULL;
 +      BMFace *efa_act = BM_get_actFace(em->bm, 0); /* annoying but active faces is stored differently */
 +      BMEdge *eed_act = NULL;
 +      BMVert *eve_act = NULL;
        
 -      if (em->selected.last) {
 -              EditSelection *ese = em->selected.last;
 +      if (em->bm->selected.last) {
 +              BMEditSelection *ese= em->bm->selected.last;
                /* face is handeled above */
 -              /*if (ese->type == EDITFACE ) {
 -                      efa_act = (EditFace *)ese->data;
 -              } else */ if ( ese->type == EDITEDGE ) {
 -                      eed_act = (EditEdge *)ese->data;
 -              } else if ( ese->type == EDITVERT ) {
 -                      eve_act = (EditVert *)ese->data;
 +              /*if (ese->type == BM_FACE ) {
 +                      efa_act = (BMFace *)ese->data;
 +              } else */ if ( ese->htype == BM_EDGE ) {
 +                      eed_act = (BMEdge *)ese->data;
 +              } else if ( ese->htype == BM_VERT ) {
 +                      eve_act = (BMVert *)ese->data;
                }
        }
        
 -      EM_init_index_arrays(em, 1, 1, 1);
 +      EDBM_init_index_arrays(em, 1, 1, 1);
  
        if(dt>OB_WIRE) {
                if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
                                glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
  
                                finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
 -                                      draw_em_fancy__setGLSLFaceOpts, NULL);
 +                                      draw_em_fancy__setGLSLFaceOpts, em);
                                GPU_disable_material();
  
                                glFrontFace(GL_CCW);
  
                        glEnable(GL_LIGHTING);
                        glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
 -
 -                      finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, NULL, 0, GPU_enable_material, NULL);
 +                      finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, me->edit_btmesh, 0, GPU_enable_material, NULL);
  
                        glFrontFace(GL_CCW);
                        glDisable(GL_LIGHTING);
                if CHECK_OB_DRAWTEXTURE(v3d, dt)
                        col1[3] = 0;
                
 -              draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
 +              draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act, me);
  
                glDisable(GL_BLEND);
                glDepthMask(1);         // restore write in zbuffer
                glEnable(GL_BLEND);
                glDepthMask(0);         // disable write in zbuffer, needed for nice transp
                
 -              draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
 +              draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act, me);
  
                glDisable(GL_BLEND);
                glDepthMask(1);         // restore write in zbuffer
                /* we are drawing textures and 'ME_DRAWEDGES' is disabled, dont draw any edges */
                
                /* only draw selected edges otherwise there is no way of telling if a face is selected */
 -              draw_em_fancy_edges(scene, v3d, me, cageDM, 1, eed_act);
 +              draw_em_fancy_edges(em, scene, v3d, me, cageDM, 1, eed_act);
                
        } else {
                if(me->drawflag & ME_DRAWSEAMS) {
                        UI_ThemeColor(TH_EDGE_SEAM);
                        glLineWidth(2);
        
 -                      draw_dm_edges_seams(cageDM);
 +                      draw_dm_edges_seams(em, cageDM);
        
                        glColor3ub(0,0,0);
                        glLineWidth(1);
                        UI_ThemeColor(TH_EDGE_SHARP);
                        glLineWidth(2);
        
 -                      draw_dm_edges_sharp(cageDM);
 +                      draw_dm_edges_sharp(em, cageDM);
        
                        glColor3ub(0,0,0);
                        glLineWidth(1);
                }
        
 -              if(me->drawflag & ME_DRAWCREASES) {
 -                      draw_dm_creases(cageDM);
 +              if(me->drawflag & ME_DRAWCREASES && CustomData_has_layer(&em->bm->edata, CD_CREASE)) {
 +                      draw_dm_creases(em, cageDM);
                }
                if(me->drawflag & ME_DRAWBWEIGHTS) {
 -                      draw_dm_bweights(scene, cageDM);
 +                      draw_dm_bweights(em, scene, cageDM);
                }
 -      
 -              draw_em_fancy_edges(scene, v3d, me, cageDM, 0, eed_act);
 +
 +              draw_em_fancy_edges(em, scene, v3d, me, cageDM, 0, eed_act);
        }
        if(em) {
  // XXX                retopo_matrix_update(v3d);
  
 -              draw_em_fancy_verts(scene, v3d, ob, cageDM, eve_act);
 +              draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act);
  
                if(me->drawflag & ME_DRAWNORMALS) {
                        UI_ThemeColor(TH_NORMAL);
 -                      draw_dm_face_normals(scene, cageDM);
 +                      draw_dm_face_normals(em, scene, cageDM);
                }
                if(me->drawflag & ME_DRAW_VNORMALS) {
                        UI_ThemeColor(TH_VNORMAL);
 -                      draw_dm_vert_normals(scene, cageDM);
 +                      draw_dm_vert_normals(em, scene, cageDM);
                }
  
                if(me->drawflag & (ME_DRAWEXTRA_EDGELEN|ME_DRAWEXTRA_FACEAREA|ME_DRAWEXTRA_FACEANG) && !((v3d->flag2 & V3D_RENDER_OVERRIDE)))
                GPU_disable_material();
        }
  
 -      EM_free_index_arrays();
 +      EDBM_free_index_arrays(em);
  }
  
  /* Mesh drawing routines */
@@@ -3006,7 -2923,7 +3006,7 @@@ static void draw_mesh_fancy(Scene *scen
        
        /* totvert = dm->getNumVerts(dm); */ /*UNUSED*/
        totedge = dm->getNumEdges(dm);
 -      totface = dm->getNumFaces(dm);
 +      totface = dm->getNumTessFaces(dm);
        
        /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
        glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
@@@ -3236,7 -3153,7 +3236,7 @@@ static int draw_mesh_object(Scene *scen
        Object *ob= base->object;
        Object *obedit= scene->obedit;
        Mesh *me= ob->data;
 -      EditMesh *em= me->edit_mesh;
 +      BMEditMesh *em= me->edit_btmesh;
        int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha, i;
  
        /* If we are drawing shadows and any of the materials don't cast a shadow,
                DerivedMesh *finalDM, *cageDM;
                
                if (obedit!=ob)
 -                      finalDM = cageDM = editmesh_get_derived_base(ob, em);
 +                      finalDM = cageDM = editbmesh_get_derived_base(ob, em);
                else
 -                      cageDM = editmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
 +                      cageDM = editbmesh_get_derived_cage_and_final(scene, ob, em, &finalDM,
                                                                                        scene->customdata_mask);
  
                if(dt>OB_WIRE) {
@@@ -6798,51 -6715,44 +6798,51 @@@ static void bbs_obmode_mesh_verts(Objec
  
  static void bbs_mesh_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
  {
 -      int offset = (intptr_t) userData;
 -      EditVert *eve = EM_get_vert_for_index(index);
 +      void **ptrs = userData;
 +      int offset = (intptr_t) ptrs[0];
 +      BMVert *eve = EDBM_get_vert_for_index(ptrs[1], index);
  
 -      if (eve->h==0) {
 +      if (!BM_TestHFlag(eve, BM_HIDDEN)) {
                WM_set_framebuffer_index_color(offset+index);
                bglVertex3fv(co);
        }
  }
 -static void bbs_mesh_verts(DerivedMesh *dm, int offset)
 +static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *dm, int offset)
  {
 +      void *ptrs[2] = {(void*)(intptr_t) offset, em};
 +
        glPointSize( UI_GetThemeValuef(TH_VERTEX_SIZE) );
        bglBegin(GL_POINTS);
 -      dm->foreachMappedVert(dm, bbs_mesh_verts__mapFunc, (void*)(intptr_t) offset);
 +      dm->foreachMappedVert(dm, bbs_mesh_verts__mapFunc, ptrs);
        bglEnd();
        glPointSize(1.0);
  }             
  
  static int bbs_mesh_wire__setDrawOptions(void *userData, int index)
  {
 -      int offset = (intptr_t) userData;
 -      EditEdge *eed = EM_get_edge_for_index(index);
 +      void **ptrs = userData;
 +      int offset = (intptr_t) ptrs[0];
 +      BMEdge *eed = EDBM_get_edge_for_index(ptrs[1], index);
  
 -      if (eed->h==0) {
 +      if (!BM_TestHFlag(eed, BM_HIDDEN)) {
                WM_set_framebuffer_index_color(offset+index);
                return 1;
        } else {
                return 0;
        }
  }
 -static void bbs_mesh_wire(DerivedMesh *dm, int offset)
 +static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *dm, int offset)
  {
 -      dm->drawMappedEdges(dm, bbs_mesh_wire__setDrawOptions, (void*)(intptr_t) offset);
 +      void *ptrs[2] = {(void*)(intptr_t) offset, em};
 +      dm->drawMappedEdges(dm, bbs_mesh_wire__setDrawOptions, ptrs);
  }             
  
  static int bbs_mesh_solid__setSolidDrawOptions(void *userData, int index, int *UNUSED(drawSmooth_r))
  {
 -      if (EM_get_face_for_index(index)->h==0) {
 -              if (userData) {
 +      BMFace *efa = EDBM_get_face_for_index(((void**)userData)[0], index);
 +      
 +      if (efa && !BM_TestHFlag(efa, BM_HIDDEN)) {
 +              if (((void**)userData)[1]) {
                        WM_set_framebuffer_index_color(index+1);
                }
                return 1;
        }
  }
  
 -static void bbs_mesh_solid__drawCenter(void *UNUSED(userData), int index, float *cent, float *UNUSED(no))
 +static void bbs_mesh_solid__drawCenter(void *userData, int index, float *cent, float *UNUSED(no))
  {
 -      EditFace *efa = EM_get_face_for_index(index);
 +      BMFace *efa = EDBM_get_face_for_index(((void**)userData)[0], index);
  
 -      if (efa->h==0 && efa->fgonf!=EM_FGON) {
 +      if (!BM_TestHFlag(efa, BM_HIDDEN)) {
                WM_set_framebuffer_index_color(index+1);
  
                bglVertex3fv(cent);
  }
  
  /* two options, facecolors or black */
 -static void bbs_mesh_solid_EM(Scene *scene, View3D *v3d, Object *ob, DerivedMesh *dm, int facecol)
 +static void bbs_mesh_solid_EM(BMEditMesh *em, Scene *scene, View3D *v3d,
 +                            Object *ob, DerivedMesh *dm, int facecol)
  {
 +      void *ptrs[2] = {em, NULL}; //second one being null means to draw black
        cpack(0);
  
        if (facecol) {
 -              dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*)(intptr_t) 1, 0, GPU_enable_material, NULL);
 +              ptrs[1] = (void*)(intptr_t) 1;
 +              dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, ptrs, 0, GPU_enable_material, NULL);
  
                if(check_ob_drawface_dot(scene, v3d, ob->dt)) {
                        glPointSize(UI_GetThemeValuef(TH_FACEDOT_SIZE));
                
                        bglBegin(GL_POINTS);
 -                      dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, NULL);
 +                      dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, ptrs);
                        bglEnd();
                }
  
        } else {
 -              dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*) 0, 0, GPU_enable_material, NULL);
 +              dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, ptrs, 0, GPU_enable_material, NULL);
        }
  }
  
@@@ -6941,36 -6848,36 +6941,36 @@@ void draw_object_backbufsel(Scene *scen
        case OB_MESH:
                if(ob->mode & OB_MODE_EDIT) {
                        Mesh *me= ob->data;
 -                      EditMesh *em= me->edit_mesh;
 +                      BMEditMesh *em= me->edit_btmesh;
  
 -                      DerivedMesh *dm = editmesh_get_derived_cage(scene, ob, em, CD_MASK_BAREMESH);
 +                      DerivedMesh *dm = editbmesh_get_derived_cage(scene, ob, em, CD_MASK_BAREMESH);
  
 -                      EM_init_index_arrays(em, 1, 1, 1);
 +                      EDBM_init_index_arrays(em, 1, 1, 1);
  
 -                      bbs_mesh_solid_EM(scene, v3d, ob, dm, ts->selectmode & SCE_SELECT_FACE);
 +                      bbs_mesh_solid_EM(em, scene, v3d, ob, dm, ts->selectmode & SCE_SELECT_FACE);
                        if(ts->selectmode & SCE_SELECT_FACE)
 -                              em_solidoffs = 1+em->totface;
 +                              bm_solidoffs = 1+em->bm->totface;
                        else
 -                              em_solidoffs= 1;
 +                              bm_solidoffs= 1;
                        
                        bglPolygonOffset(rv3d->dist, 1.0);
                        
                        // we draw edges always, for loop (select) tools
 -                      bbs_mesh_wire(dm, em_solidoffs);
 -                      em_wireoffs= em_solidoffs + em->totedge;
 +                      bbs_mesh_wire(em, dm, bm_solidoffs);
 +                      bm_wireoffs= bm_solidoffs + em->bm->totedge;
                        
                        // we draw verts if vert select mode or if in transform (for snap).
                        if(ts->selectmode & SCE_SELECT_VERTEX || G.moving & G_TRANSFORM_EDIT) {
 -                              bbs_mesh_verts(dm, em_wireoffs);
 -                              em_vertoffs= em_wireoffs + em->totvert;
 +                              bbs_mesh_verts(em, dm, bm_wireoffs);
 +                              bm_vertoffs= bm_wireoffs + em->bm->totvert;
                        }
 -                      else em_vertoffs= em_wireoffs;
 +                      else bm_vertoffs= bm_wireoffs;
                        
                        bglPolygonOffset(rv3d->dist, 0.0);
  
                        dm->release(dm);
  
 -                      EM_free_index_arrays();
 +                      EDBM_free_index_arrays(em);
                }
                else {
                        Mesh *me= ob->data;
  
                                
                                bbs_obmode_mesh_verts(ob, dm, 1);
 -                              em_vertoffs = me->totvert+1;
 +                              bm_vertoffs = me->totvert+1;
                                dm->release(dm);
                        }
                        else {
@@@ -7014,7 -6921,7 +7014,7 @@@ static void draw_object_mesh_instance(S
        int glsl;
        
        if(ob->mode & OB_MODE_EDIT)
 -              edm= editmesh_get_derived_base(ob, me->edit_mesh);
 +              edm= editbmesh_get_derived_base(ob, me->edit_btmesh);
        else 
                dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
  
index 582ee56961ae41fac5bbb717f5f46f2289637382,7cd9c07c00ca68cb82ec1a5ebe3b823aca04f6c7..fd46112e7764bea00280f007f25eb41ed53f4cd0
@@@ -55,8 -55,6 +55,8 @@@
  #include "BKE_lattice.h"
  #include "BKE_main.h"
  #include "BKE_object.h"
 +#include "BKE_tessmesh.h"
 +#include "BKE_DerivedMesh.h"
  #include "BKE_tracking.h"
  
  #include "WM_api.h"
@@@ -81,11 -79,10 +81,11 @@@ extern float originmat[3][3];      /* XXX ob
  
  typedef struct TransVert {
        float *loc;
 -      float oldloc[3], fac;
 +      float oldloc[3], maploc[3], fac;
        float *val, oldval;
        int flag;
        float *nor;
 +      int f1;
  } TransVert;
  
  static TransVert *transvmain=NULL;
@@@ -101,7 -98,7 +101,7 @@@ static void special_transvert_update(Ob
                
                if(obedit->type==OB_MESH) {
                        Mesh *me= obedit->data;
 -                      recalc_editnormals(me->edit_mesh);      // does face centers too
 +                      BM_Compute_Normals(me->edit_btmesh->bm);        // does face centers too
                }
                else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
                        Curve *cu= obedit->data;
        }
  }
  
 +static void set_mapped_co(void *vuserdata, int index, float *co, float *UNUSED(no), short *UNUSED(no_s))
 +{
 +      void ** userdata = vuserdata;
 +      BMEditMesh *em = userdata[0];
 +      TransVert *tv = userdata[1];
 +      BMVert *eve = EDBM_get_vert_for_index(em, index);
 +      
 +      if (BM_GetIndex(eve) != -1 && !tv[BM_GetIndex(eve)].f1) {
 +              copy_v3_v3(tv[BM_GetIndex(eve)].maploc, co);
 +              tv[BM_GetIndex(eve)].f1 = 1;
 +      }
 +}
 +
  /* copied from editobject.c, needs to be replaced with new transform code still */
  /* mode flags: */
  #define TM_ALL_JOINTS         1 /* all joints (for bones only) */
@@@ -216,7 -200,7 +216,7 @@@ static void make_trans_verts(Object *ob
        BPoint *bp;
        TransVert *tv=NULL;
        MetaElem *ml;
 -      EditVert *eve;
 +      BMVert *eve;
        EditBone        *ebo;
        float total, center[3], centroid[3];
        int a;
        
        if(obedit->type==OB_MESH) {
                Mesh *me= obedit->data;
 -              EditMesh *em= me->edit_mesh;
 +              BMEditMesh *em= me->edit_btmesh;
 +              BMesh *bm = em->bm;
 +              BMIter iter;
 +              void *userdata[2] = {em, NULL};
 +              /*int proptrans= 0; */ /*UNUSED*/
                
                // transform now requires awareness for select mode, so we tag the f1 flags in verts
                tottrans= 0;
                if(em->selectmode & SCE_SELECT_VERTEX) {
 -                      for(eve= em->verts.first; eve; eve= eve->next) {
 -                              if(eve->h==0 && (eve->f & SELECT)) {
 -                                      eve->f1= SELECT;
 +                      BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
 +                              if(!BM_TestHFlag(eve, BM_HIDDEN) && BM_TestHFlag(eve, BM_SELECT)) {
 +                                      BM_SetIndex(eve, 1);
                                        tottrans++;
                                }
 -                              else eve->f1= 0;
 +                              else BM_SetIndex(eve, 0);
                        }
                }
                else if(em->selectmode & SCE_SELECT_EDGE) {
 -                      EditEdge *eed;
 -                      for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
 -                      for(eed= em->edges.first; eed; eed= eed->next) {
 -                              if(eed->h==0 && (eed->f & SELECT)) eed->v1->f1= eed->v2->f1= SELECT;
 +                      BMEdge *eed;
 +
 +                      BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
 +                              BM_SetIndex(eve, 0);
 +
 +                      BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
 +                              if(!BM_TestHFlag(eed, BM_HIDDEN) && BM_TestHFlag(eed, BM_SELECT))
 +                                      BM_SetIndex(eed->v1, 1), BM_SetIndex(eed->v2, 1);
                        }
 -                      for(eve= em->verts.first; eve; eve= eve->next) if(eve->f1) tottrans++;
 +
 +                      BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
 +                              if(BM_GetIndex(eve)) tottrans++;
                }
                else {
 -                      EditFace *efa;
 -                      for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
 -                      for(efa= em->faces.first; efa; efa= efa->next) {
 -                              if(efa->h==0 && (efa->f & SELECT)) {
 -                                      efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
 -                                      if(efa->v4) efa->v4->f1= SELECT;
 +                      BMFace *efa;
 +
 +                      BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
 +                              BM_SetIndex(eve, 0);
 +
 +                      BM_ITER(efa, &iter, bm, BM_FACES_OF_MESH, NULL) {
 +                              if(!BM_TestHFlag(efa, BM_HIDDEN) && BM_TestHFlag(efa, BM_SELECT)) {
 +                                      BMIter liter;
 +                                      BMLoop *l;
 +                                      
 +                                      BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, efa) {
 +                                              BM_SetIndex(l->v, 1);
 +                                      }
                                }
                        }
 -                      for(eve= em->verts.first; eve; eve= eve->next) if(eve->f1) tottrans++;
 +
 +                      BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
 +                              if(BM_GetIndex(eve)) tottrans++;
                }
                
                /* and now make transverts */
                if(tottrans) {
                        tv=transvmain= MEM_callocN(tottrans*sizeof(TransVert), "maketransverts");
 -
 -                      for(eve= em->verts.first; eve; eve= eve->next) {
 -                              if(eve->f1) {
 +              
 +                      a = 0;
 +                      BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
 +                              if(BM_GetIndex(eve)) {
 +                                      BM_SetIndex(eve, a);
                                        copy_v3_v3(tv->oldloc, eve->co);
                                        tv->loc= eve->co;
                                        if(eve->no[0] != 0.0f || eve->no[1] != 0.0f ||eve->no[2] != 0.0f)
                                                tv->nor= eve->no; // note this is a hackish signal (ton)
 -                                      tv->flag= eve->f1 & SELECT;
 +                                      tv->flag= BM_GetIndex(eve) & SELECT;
                                        tv++;
 -                              }
 +                                      a++;
 +                              } else BM_SetIndex(eve, -1);
 +                      }
 +                      
 +                      userdata[1] = transvmain;
 +              }
 +              
 +              if (transvmain && em->derivedCage) {
 +                      EDBM_init_index_arrays(em, 1, 0, 0);
 +                      em->derivedCage->foreachMappedVert(em->derivedCage, set_mapped_co, userdata);
 +                      EDBM_free_index_arrays(em);
 +              } else if (transvmain) {
 +                      tv = transvmain;
 +                      for (a=0; a<tottrans; a++, tv++) {
 +                              copy_v3_v3(tv->maploc, tv->loc);
                        }
                }
        }
@@@ -832,7 -781,7 +832,7 @@@ static void bundle_midpoint(Scene *scen
        }
  
        if(ok) {
-               interp_v3_v3v3(vec, min, max, 0.5);
+               mid_v3_v3v3(vec, min, max);
        }
  }
  
@@@ -962,10 -911,10 +962,10 @@@ static int snap_curs_to_active(bContex
                if (obedit->type == OB_MESH) {
                        /* check active */
                        Mesh *me= obedit->data;
 -                      EditSelection ese;
 +                      BMEditSelection ese;
                        
 -                      if (EM_get_actSelection(me->edit_mesh, &ese)) {
 -                              EM_editselection_center(curs, &ese);
 +                      if (EDBM_get_actSelection(me->edit_btmesh, &ese)) {
 +                              EDBM_editselection_center(me->edit_btmesh, curs, &ese);
                        }
                        
                        mul_m4_v3(obedit->obmat, curs);
@@@ -1050,7 -999,7 +1050,7 @@@ int minmax_verts(Object *obedit, float 
        
        tv= transvmain;
        for(a=0; a<tottrans; a++, tv++) {               
 -              copy_v3_v3(vec, tv->loc);
 +              copy_v3_v3(vec, tv->maploc);
                mul_m3_v3(bmat, vec);
                add_v3_v3(vec, obedit->obmat[3]);
                add_v3_v3(centroid, vec);
        
        return 1;
  }
 -
index e5ae4aa56b3294f9d52dfedd8e4358380fa57859,95daa11d97ff40126fb785babdd8d4211609a16a..5ef74c0af20d00b7a1854a7a084b698599aee967
@@@ -84,8 -84,6 +84,8 @@@
  #include "BLI_editVert.h"
  #include "BLI_ghash.h"
  #include "BLI_linklist.h"
 +#include "BLI_smallhash.h"
 +#include "BLI_array.h"
  
  #include "UI_resources.h"
  
@@@ -95,8 -93,6 +95,8 @@@
  
  #include "transform.h"
  
 +#include <stdio.h>
 +
  void drawTransformApply(const struct bContext *C, struct ARegion *ar, void *arg);
  int doEdgeSlide(TransInfo *t, float perc);
  
@@@ -517,7 -513,7 +517,7 @@@ wmKeyMap* transform_modal_keymap(wmKeyC
        {NUM_MODAL_INCREMENT_UP, "INCREMENT_UP", 0, "Numinput Increment Up", ""},
        {NUM_MODAL_INCREMENT_DOWN, "INCREMENT_DOWN", 0, "Numinput Increment Down", ""},
        {TFM_MODAL_PROPSIZE_UP, "PROPORTIONAL_SIZE_UP", 0, "Increase Proportional Influence", ""},
-       {TFM_MODAL_PROPSIZE_DOWN, "PROPORTIONAL_SIZE_DOWN", 0, "Decrease Poportional Influence", ""},
+       {TFM_MODAL_PROPSIZE_DOWN, "PROPORTIONAL_SIZE_DOWN", 0, "Decrease Proportional Influence", ""},
        {TFM_MODAL_AUTOIK_LEN_INC, "AUTOIK_CHAIN_LEN_UP", 0, "Increase Max AutoIK Chain Length", ""},
        {TFM_MODAL_AUTOIK_LEN_DEC, "AUTOIK_CHAIN_LEN_DOWN", 0, "Decrease Max AutoIK Chain Length", ""},
        {0, NULL, 0, NULL, NULL}};
@@@ -3477,8 -3473,7 +3477,8 @@@ static void applyTranslation(TransInfo 
                
                protectedTransBits(td->protectflag, tvec);
                
 -              add_v3_v3v3(td->loc, td->iloc, tvec);
 +              if (td->loc)
 +                      add_v3_v3v3(td->loc, td->iloc, tvec);
                
                constraintTransLim(t, td);
        }
@@@ -4271,467 -4266,506 +4271,467 @@@ int BoneEnvelope(TransInfo *t, const in
  }
  
  /* ********************  Edge Slide   *************** */
 +static BMEdge *get_other_edge(BMesh *bm, BMVert *v, BMEdge *e)
 +{
 +      BMIter iter;
 +      BMEdge *e2;
 +
 +      BM_ITER(e2, &iter, bm, BM_EDGES_OF_VERT, v) {
 +              if (BM_TestHFlag(e2, BM_SELECT) && e2 != e)
 +                      return e2;
 +      }
 +
 +      return NULL;
 +}
 +
 +static BMLoop *get_next_loop(BMesh *UNUSED(bm), BMVert *v, BMLoop *l, 
 +                             BMEdge *olde, BMEdge *nexte, float vec[3])
 +{
 +      BMLoop *firstl;
 +      float a[3] = {0.0f, 0.0f, 0.0f}, n[3] = {0.0f, 0.0f, 0.0f};
 +      int i=0;
 +
 +      firstl = l;
 +      do {
 +              l = BM_OtherFaceLoop(l->e, l->f, v);
 +              if (l->radial_next == l)
 +                      return NULL;
 +              
 +              if (l->e == nexte) {
 +                      if (i) {
 +                              mul_v3_fl(a, 1.0f / (float)i);
 +                      } else {
 +                              float f1[3], f2[3], f3[3];
 +
 +                              sub_v3_v3v3(f1, BM_OtherEdgeVert(olde, v)->co, v->co);
 +                              sub_v3_v3v3(f2, BM_OtherEdgeVert(nexte, v)->co, v->co);
 +
 +                              cross_v3_v3v3(f3, f1, l->f->no);
 +                              cross_v3_v3v3(a, f2, l->f->no);
 +                              mul_v3_fl(a, -1.0f);
 +
 +                              add_v3_v3(a, f3);
 +                              mul_v3_fl(a, 0.5f);
 +                      }
 +                      
 +                      copy_v3_v3(vec, a);
 +                      return l;
 +              } else {
 +                      sub_v3_v3v3(n, BM_OtherEdgeVert(l->e, v)->co, v->co);
 +                      add_v3_v3v3(a, a, n);
 +                      i += 1;
 +              }
 +
 +              if (BM_OtherFaceLoop(l->e, l->f, v)->e == nexte) {
 +                      if (i)
 +                              mul_v3_fl(a, 1.0f / (float)i);
 +                      
 +                      copy_v3_v3(vec, a);
 +                      return BM_OtherFaceLoop(l->e, l->f, v);
 +              }
 +              
 +              l = l->radial_next;
 +      } while (l != firstl); 
 +
 +      if (i)
 +              mul_v3_fl(a, 1.0f / (float)i);
 +      
 +      copy_v3_v3(vec, a);
 +      
 +      return NULL;
 +}
  
  static int createSlideVerts(TransInfo *t)
  {
        Mesh *me = t->obedit->data;
 -      EditMesh *em = me->edit_mesh;
 -      EditFace *efa;
 -      EditEdge *eed,*first=NULL,*last=NULL, *temp = NULL;
 -      EditVert *ev, *nearest = NULL;
 -      LinkNode *edgelist = NULL, *vertlist=NULL, *look;
 -      GHash *vertgh;
 +      BMEditMesh *em = me->edit_btmesh;
 +      BMesh *bm = em->bm;
 +      BMIter iter, iter2;
 +      BMEdge *e, *e1, *ee, *le;
 +      BMVert *v, *v2, *first;
 +      BMLoop *l, *l1, *l2;
        TransDataSlideVert *tempsv;
 -      int i, j, numsel, numadded=0, timesthrough = 0, vertsel=0;
 -      /* UV correction vars */
 -      GHash **uvarray= NULL;
 +      BMBVHTree *btree = BMBVH_NewBVH(em, 0, NULL, NULL);
 +      SmallHash table;
        SlideData *sld = MEM_callocN(sizeof(*sld), "sld");
 -      const int  uvlay_tot=  (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) ? CustomData_number_of_layers(&em->fdata, CD_MTFACE) : 0;
 -      int uvlay_idx;
 -      TransDataSlideUv *slideuvs=NULL, *suv=NULL, *suv_last=NULL;
 -      RegionView3D *v3d = t->ar ? t->ar->regiondata : NULL; /* background mode support */
 +      View3D *v3d = t->sa ? t->sa->spacedata.first : NULL;
 +      RegionView3D *rv3d = t->ar ? t->ar->regiondata : NULL; /* background mode support */
 +      ARegion *ar = t->ar;
        float projectMat[4][4];
 -      float start[3] = {0.0f, 0.0f, 0.0f}, end[3] = {0.0f, 0.0f, 0.0f};
 -      float vec[3];
 -      float totvec=0.0;
 +      float start[3] = {0.0f, 0.0f, 0.0f}, dir[3], end[3] = {0.0f, 0.0f, 0.0f};
 +      float vec[3], vec2[3], lastvec[3], size, dis=0.0, z;
 +      int numsel, i, j;
  
        if (!v3d) {
                /*ok, let's try to survive this*/
                unit_m4(projectMat);
        } else {
 -              ED_view3d_ob_project_mat_get(v3d, t->obedit, projectMat);
 +              ED_view3d_ob_project_mat_get(rv3d, t->obedit, projectMat);
        }
        
 -      numsel =0;
 -
 -      // Get number of selected edges and clear some flags
 -      for(eed=em->edges.first;eed;eed=eed->next) {
 -              eed->f1 = 0;
 -              eed->f2 = 0;
 -              if(eed->f & SELECT) numsel++;
 -      }
 -
 -      for(ev=em->verts.first;ev;ev=ev->next) {
 -              ev->f1 = 0;
 -      }
 +      BLI_smallhash_init(&sld->vhash);
 +      BLI_smallhash_init(&sld->origfaces);
 +      BLI_smallhash_init(&table);
 +      
 +      /*ensure valid selection*/
 +      BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
 +              if (BM_TestHFlag(v, BM_SELECT)) {
 +                      numsel = 0;
 +                      BM_ITER(e, &iter2, em->bm, BM_EDGES_OF_VERT, v) {
 +                              if (BM_TestHFlag(e, BM_SELECT)) {
 +                                      /*BMESH_TODO: this is probably very evil,
 +                                        set v->e to a selected edge*/
 +                                      v->e = e;
  
 -      //Make sure each edge only has 2 faces
 -      // make sure loop doesn't cross face
 -      for(efa=em->faces.first;efa;efa=efa->next) {
 -              int ct = 0;
 -              if(efa->e1->f & SELECT) {
 -                      ct++;
 -                      efa->e1->f1++;
 -                      if(efa->e1->f1 > 2) {
 -                              //BKE_report(op->reports, RPT_ERROR, "3+ face edge");
 -                              MEM_freeN(sld);
 -                              return 0;
 -                      }
 -              }
 -              if(efa->e2->f & SELECT) {
 -                      ct++;
 -                      efa->e2->f1++;
 -                      if(efa->e2->f1 > 2) {
 -                              //BKE_report(op->reports, RPT_ERROR, "3+ face edge");
 -                              MEM_freeN(sld);
 -                              return 0;
 -                      }
 -              }
 -              if(efa->e3->f & SELECT) {
 -                      ct++;
 -                      efa->e3->f1++;
 -                      if(efa->e3->f1 > 2) {
 -                              //BKE_report(op->reports, RPT_ERROR, "3+ face edge");
 -                              MEM_freeN(sld);
 -                              return 0;
 +                                      numsel++;
 +                              }
                        }
 -              }
 -              if(efa->e4 && efa->e4->f & SELECT) {
 -                      ct++;
 -                      efa->e4->f1++;
 -                      if(efa->e4->f1 > 2) {
 -                              //BKE_report(op->reports, RPT_ERROR, "3+ face edge");
 -                              MEM_freeN(sld);
 -                              return 0;
 +
 +                      if (numsel == 0 || numsel > 2) {
 +                              return 0; //invalid edge selection
                        }
                }
 -              // Make sure loop is not 2 edges of same face
 -              if(ct > 1) {
 -                 //BKE_report(op->reports, RPT_ERROR, "Loop crosses itself");
 -                      MEM_freeN(sld);
 -                      return 0;
 +      }
 +
 +      BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
 +              if (BM_TestHFlag(e, BM_SELECT)) {
 +                      if (BM_Edge_FaceCount(e) != 2)
 +                              return 0; //can only handle exactly 2 faces around each edge
                }
        }
  
 -      // Get # of selected verts
 -      for(ev=em->verts.first;ev;ev=ev->next) {
 -              if(ev->f & SELECT) vertsel++;
 +      j = 0;
 +      BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
 +              if (BM_TestHFlag(v, BM_SELECT)) {
 +                      BM_SetHFlag(v, BM_TMP_TAG);
 +                      BLI_smallhash_insert(&table, (uintptr_t)v, SET_INT_IN_POINTER(j));
 +                      j += 1;
 +              }
 +              else {
 +                      BM_ClearHFlag(v, BM_TMP_TAG);
 +              }
        }
  
 -      // Test for multiple segments
 -      if(vertsel > numsel+1) {
 -              //BKE_report(op->reports, RPT_ERROR, "Please choose a single edge loop");
 -              MEM_freeN(sld);
 +      if (!j)
                return 0;
 -      }
  
 -      // Get the edgeloop in order - mark f1 with SELECT once added
 -      for(eed=em->edges.first;eed;eed=eed->next) {
 -              if((eed->f & SELECT) && !(eed->f1 & SELECT)) {
 -                      // If this is the first edge added, just put it in
 -                      if(!edgelist) {
 -                              BLI_linklist_prepend(&edgelist,eed);
 -                              numadded++;
 -                              first = eed;
 -                              last  = eed;
 -                              eed->f1 = SELECT;
 -                      } else {
 -                              if(editedge_getSharedVert(eed, last)) {
 -                                      BLI_linklist_append(&edgelist,eed);
 -                                      eed->f1 = SELECT;
 -                                      numadded++;
 -                                      last = eed;
 -                              }  else if(editedge_getSharedVert(eed, first)) {
 -                                      BLI_linklist_prepend(&edgelist,eed);
 -                                      eed->f1 = SELECT;
 -                                      numadded++;
 -                                      first = eed;
 -                              }
 -                      }
 -              }
 -              if(eed->next == NULL && numadded != numsel) {
 -                      eed=em->edges.first;
 -                      timesthrough++;
 -              }
 +      tempsv = MEM_callocN(sizeof(TransDataSlideVert)*j, "tempsv");
 +
 +      j = 0;
 +      while (1) {
 +              v = NULL;
 +              BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
 +                      if (BM_TestHFlag(v, BM_TMP_TAG))
 +                              break;
  
 -              // It looks like there was an unexpected case - Hopefully should not happen
 -              if(timesthrough >= numsel*2) {
 -                      BLI_linklist_free(edgelist,NULL);
 -                      //BKE_report(op->reports, RPT_ERROR, "Could not order loop");
 -                      MEM_freeN(sld);
 -                      return 0;
                }
 -      }
  
 -      // Put the verts in order in a linklist
 -      look = edgelist;
 -      while(look) {
 -              eed = look->link;
 -              if(!vertlist) {
 -                      if(look->next) {
 -                              temp = look->next->link;
 +              if (!v)
 +                      break;
  
 -                              //This is the first entry takes care of extra vert
 -                              if(eed->v1 != temp->v1 && eed->v1 != temp->v2) {
 -                                      BLI_linklist_append(&vertlist,eed->v1);
 -                                      eed->v1->f1 = 1;
 -                              } else {
 -                                      BLI_linklist_append(&vertlist,eed->v2);
 -                                      eed->v2->f1 = 1;
 -                              }
 -                      } else {
 -                              //This is the case that we only have 1 edge
 -                              BLI_linklist_append(&vertlist,eed->v1);
 -                              eed->v1->f1 = 1;
 -                      }
 -              }
 -              // for all the entries
 -              if(eed->v1->f1 != 1) {
 -                      BLI_linklist_append(&vertlist,eed->v1);
 -                      eed->v1->f1 = 1;
 -              } else  if(eed->v2->f1 != 1) {
 -                      BLI_linklist_append(&vertlist,eed->v2);
 -                      eed->v2->f1 = 1;
 -              }
 -              look = look->next;
 -      }
 -
 -      // populate the SlideVerts
 -
 -      vertgh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "createSlideVerts gh");
 -      look = vertlist;
 -      while(look) {
 -              i=0;
 -              j=0;
 -              ev = look->link;
 -              tempsv = (struct TransDataSlideVert*)MEM_mallocN(sizeof(struct TransDataSlideVert),"SlideVert");
 -              tempsv->up = NULL;
 -              tempsv->down = NULL;
 -              tempsv->origvert.co[0] = ev->co[0];
 -              tempsv->origvert.co[1] = ev->co[1];
 -              tempsv->origvert.co[2] = ev->co[2];
 -              tempsv->origvert.no[0] = ev->no[0];
 -              tempsv->origvert.no[1] = ev->no[1];
 -              tempsv->origvert.no[2] = ev->no[2];
 -              // i is total edges that vert is on
 -              // j is total selected edges that vert is on
 -
 -              for(eed=em->edges.first;eed;eed=eed->next) {
 -                      if(eed->v1 == ev || eed->v2 == ev) {
 -                              i++;
 -                              if(eed->f & SELECT) {
 -                                       j++;
 -                              }
 -                      }
 -              }
 -              // If the vert is in the middle of an edge loop, it touches 2 selected edges and 2 unselected edges
 -              if(i == 4 && j == 2) {
 -                      for(eed=em->edges.first;eed;eed=eed->next) {
 -                              if(editedge_containsVert(eed, ev)) {
 -                                      if(!(eed->f & SELECT)) {
 -                                              if(!tempsv->up) {
 -                                                      tempsv->up = eed;
 -                                              } else if (!(tempsv->down)) {
 -                                                      tempsv->down = eed;
 -                                              }
 -                                      }
 -                              }
 -                      }
 -              }
 -              // If it is on the end of the loop, it touches 1 selected and as least 2 more unselected
 -              if(i >= 3 && j == 1) {
 -                      for(eed=em->edges.first;eed;eed=eed->next) {
 -                              if(editedge_containsVert(eed, ev) && eed->f & SELECT) {
 -                                      for(efa = em->faces.first;efa;efa=efa->next) {
 -                                              if(editface_containsEdge(efa, eed)) {
 -                                                      if(editedge_containsVert(efa->e1, ev) && efa->e1 != eed) {
 -                                                              if(!tempsv->up) {
 -                                                                      tempsv->up = efa->e1;
 -                                                              } else if (!(tempsv->down)) {
 -                                                                      tempsv->down = efa->e1;
 -                                                              }
 -                                                      }
 -                                                      if(editedge_containsVert(efa->e2, ev) && efa->e2 != eed) {
 -                                                              if(!tempsv->up) {
 -                                                                      tempsv->up = efa->e2;
 -                                                              } else if (!(tempsv->down)) {
 -                                                                      tempsv->down = efa->e2;
 -                                                              }
 -                                                      }
 -                                                      if(editedge_containsVert(efa->e3, ev) && efa->e3 != eed) {
 -                                                              if(!tempsv->up) {
 -                                                                      tempsv->up = efa->e3;
 -                                                              } else if (!(tempsv->down)) {
 -                                                                      tempsv->down = efa->e3;
 -                                                              }
 -                                                      }
 -                                                      if(efa->e4) {
 -                                                              if(editedge_containsVert(efa->e4, ev) && efa->e4 != eed) {
 -                                                                      if(!tempsv->up) {
 -                                                                              tempsv->up = efa->e4;
 -                                                                      } else if (!(tempsv->down)) {
 -                                                                              tempsv->down = efa->e4;
 -                                                                      }
 -                                                              }
 -                                                      }
 +              if (!v->e)
 +                      continue;
 +              
 +              first = v;
  
 -                                              }
 -                                      }
 -                              }
 +              /*walk along the edge loop*/
 +              e = v->e;
 +
 +              /*first, rewind*/
 +              numsel = 0;
 +              do {
 +                      e = get_other_edge(bm, v, e);
 +                      if (!e) {
 +                              e = v->e;
 +                              break;
                        }
 -              }
 -              if(i > 4 && j == 2) {
 -                      BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN);
 -                      BLI_linklist_free(vertlist,NULL);
 -                      BLI_linklist_free(edgelist,NULL);
 -                      return 0;
 -              }
 -              BLI_ghash_insert(vertgh,ev,tempsv);
  
 -              look = look->next;
 -      }
 +                      numsel += 1;
 +
 +                      if (!BM_TestHFlag(BM_OtherEdgeVert(e, v), BM_TMP_TAG))
 +                              break;
  
 -      // make sure the UPs and DOWNs are 'faceloops'
 -      // Also find the nearest slidevert to the cursor
 +                      v = BM_OtherEdgeVert(e, v);
 +              } while (e != first->e);
  
 -      look = vertlist;
 -      nearest = NULL;
 -      while(look) {
 -              tempsv  = BLI_ghash_lookup(vertgh,(EditVert*)look->link);
 +              BM_ClearHFlag(v, BM_TMP_TAG);
  
 -              if(!tempsv->up || !tempsv->down) {
 -                      //BKE_report(op->reports, RPT_ERROR, "Missing rails");
 -                      BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN);
 -                      BLI_linklist_free(vertlist,NULL);
 -                      BLI_linklist_free(edgelist,NULL);
 -                      return 0;
 -              }
 +              l1 = l2 = l = NULL;
 +              l1 = e->l;
 +              l2 = e->l->radial_next;
  
 -              if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
 -                      if(!(tempsv->up->f & SELECT)) {
 -                              tempsv->up->f |= SELECT;
 -                              tempsv->up->f2 |= 16;
 -                      } else {
 -                              tempsv->up->f2 |= ~16;
 -                      }
 -                      if(!(tempsv->down->f & SELECT)) {
 -                              tempsv->down->f |= SELECT;
 -                              tempsv->down->f2 |= 16;
 -                      } else {
 -                              tempsv->down->f2 |= ~16;
 -                      }
 -              }
 +              l = BM_OtherFaceLoop(l1->e, l1->f, v);
 +              sub_v3_v3v3(vec, BM_OtherEdgeVert(l->e, v)->co, v->co);
  
 -              if(look->next != NULL) {
 -                      TransDataSlideVert *sv;
 -                      
 -                      ev = (EditVert*)look->next->link;
 -                      sv = BLI_ghash_lookup(vertgh, ev);
 +              if (l2 != l1) {
 +                      l = BM_OtherFaceLoop(l2->e, l2->f, v);
 +                      sub_v3_v3v3(vec2, BM_OtherEdgeVert(l->e, v)->co, v->co);
 +              } else {
 +                      l2 = NULL;
 +              }
  
 -                      if(sv) {
 -                              float co[3], co2[3], tvec[3];
 +              /*iterate over the loop*/
 +              first = v;
 +              do {
 +                      TransDataSlideVert *sv = tempsv + j;
  
 -                              ev = (EditVert*)look->link;
 +                      sv->v = v;
 +                      sv->origvert = *v;
 +                      copy_v3_v3(sv->upvec, vec);
 +                      if (l2)
 +                              copy_v3_v3(sv->downvec, vec2);
  
 -                              if(!sharesFace(em, tempsv->up,sv->up)) {
 -                                      EditEdge *swap;
 -                                      swap = sv->up;
 -                                      sv->up = sv->down;
 -                                      sv->down = swap;
 -                              }
 -                              
 -                              if (v3d) {
 -                                      ED_view3d_project_float(t->ar, tempsv->up->v1->co, co, projectMat);
 -                                      ED_view3d_project_float(t->ar, tempsv->up->v2->co, co2, projectMat);
 -                              }
 +                      l = BM_OtherFaceLoop(l1->e, l1->f, v);
 +                      sv->up = BM_OtherEdgeVert(l->e, v);
  
 -                              if (ev == tempsv->up->v1) {
 -                                      sub_v3_v3v3(tvec, co, co2);
 -                              } else {
 -                                      sub_v3_v3v3(tvec, co2, co);
 -                              }
 +                      if (l2) {
 +                              l = BM_OtherFaceLoop(l2->e, l2->f, v);
 +                              sv->down = BM_OtherEdgeVert(l->e, v);
 +                      }
  
 -                              add_v3_v3(start, tvec);
 +                      v2=v, v = BM_OtherEdgeVert(e, v);
  
 -                              if (v3d) {
 -                                      ED_view3d_project_float(t->ar, tempsv->down->v1->co, co, projectMat);
 -                                      ED_view3d_project_float(t->ar, tempsv->down->v2->co, co2, projectMat);
 -                              }
 +                      e1 = e;
 +                      e = get_other_edge(bm, v, e);
 +                      if (!e) {
 +                              //v2=v, v = BM_OtherEdgeVert(l1->e, v);
  
 -                              if (ev == tempsv->down->v1) {
 -                                      sub_v3_v3v3(tvec, co2, co);
 -                              } else {
 -                                      sub_v3_v3v3(tvec, co, co2);
 +                              sv = tempsv + j + 1;
 +                              sv->v = v;
 +                              sv->origvert = *v;
 +                              
 +                              l = BM_OtherFaceLoop(l1->e, l1->f, v);
 +                              sv->up = BM_OtherEdgeVert(l->e, v);
 +                              sub_v3_v3v3(sv->upvec, BM_OtherEdgeVert(l->e, v)->co, v->co);
 +
 +                              if (l2) {
 +                                      l = BM_OtherFaceLoop(l2->e, l2->f, v);
 +                                      sv->down = BM_OtherEdgeVert(l->e, v);
 +                                      sub_v3_v3v3(sv->downvec, BM_OtherEdgeVert(l->e, v)->co, v->co);
                                }
  
 -                              add_v3_v3(end, tvec);
 -
 -                              totvec += 1.0f;
 -                              nearest = (EditVert*)look->link;
 +                              BM_ClearHFlag(v, BM_TMP_TAG);
 +                              BM_ClearHFlag(v2, BM_TMP_TAG);
 +                              
 +                              j += 2;
 +                              break;
                        }
 -              }
  
 +                      l1 = get_next_loop(bm, v, l1, e1, e, vec);
 +                      l2 = l2 ? get_next_loop(bm, v, l2, e1, e, vec2) : NULL;
  
 +                      j += 1;
  
 -              look = look->next;
 +                      BM_ClearHFlag(v, BM_TMP_TAG);
 +                      BM_ClearHFlag(v2, BM_TMP_TAG);
 +              } while (e != first->e && l1);
        }
  
 -      add_v3_v3(start, end);
 -      mul_v3_fl(start, 0.5f*(1.0f/totvec));
 -      copy_v3_v3(vec, start);
 -      start[0] = t->mval[0];
 -      start[1] = t->mval[1];
 -      add_v3_v3v3(end, start, vec);
 +      //EDBM_clear_flag_all(em, BM_SELECT);
  
 +      sld->sv = tempsv;
 +      sld->totsv = j;
 +      
 +      /*find mouse vector*/
 +      dis = z = -1.0f;
 +      size = 50.0;
 +      zero_v3(lastvec); zero_v3(dir);
 +      ee = le = NULL;
 +      BM_ITER(e, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
 +              if (BM_TestHFlag(e, BM_SELECT)) {
 +                      BMIter iter2;
 +                      BMEdge *e2;
 +                      float vec1[3], dis2, mval[2] = {t->mval[0], t->mval[1]}, d;
 +                                              
 +                      /*search cross edges for visible edge to the mouse cursor,
 +              then use the shared vertex to calculate screen vector*/
 +                      dis2 = -1.0f;
 +                      for (i=0; i<2; i++) {
 +                              v = i?e->v1:e->v2;
 +                              BM_ITER(e2, &iter2, em->bm, BM_EDGES_OF_VERT, v) {
 +                                      if (BM_TestHFlag(e2, BM_SELECT))
 +                                              continue;
 +                                      
 +                                      if (!BMBVH_EdgeVisible(btree, e2, ar, v3d, t->obedit))
 +                                              continue;
 +                                      
 +                                      j = GET_INT_FROM_POINTER(BLI_smallhash_lookup(&table, (uintptr_t)v));
 +
 +                                      if (tempsv[j].down) {
 +                                              ED_view3d_project_float_v3(ar, tempsv[j].down->co, vec1, projectMat);
 +                                      } else {
 +                                              add_v3_v3v3(vec1, v->co, tempsv[j].downvec);
 +                                              ED_view3d_project_float_v3(ar, vec1, vec1, projectMat);
 +                                      }
 +                                      
 +                                      if (tempsv[j].up) {
 +                                              ED_view3d_project_float_v3(ar, tempsv[j].up->co, vec2, projectMat);
 +                                      } else {
 +                                              add_v3_v3v3(vec1, v->co, tempsv[j].upvec);
 +                                              ED_view3d_project_float_v3(ar, vec2, vec2, projectMat);
 +                                      }
  
 -      /* Ensure minimum screen distance, when looking top down on edge loops */
 -#define EDGE_SLIDE_MIN 30
 -      if (len_squared_v2v2(start, end) < (EDGE_SLIDE_MIN * EDGE_SLIDE_MIN)) {
 -              if(ABS(start[0]-end[0]) + ABS(start[1]-end[1]) < 4.0f) {
 -                      /* even more exceptional case, points are ontop of each other */
 -                      end[0]= start[0];
 -                      end[1]= start[1] + EDGE_SLIDE_MIN;
 -              }
 -              else {
 -                      sub_v2_v2(end, start);
 -                      normalize_v2(end);
 -                      mul_v2_fl(end, EDGE_SLIDE_MIN);
 -                      add_v2_v2(end, start);
 +                                      d = dist_to_line_segment_v2(mval, vec1, vec2);
 +                                      if (dis2 == -1.0f || d < dis2) {
 +                                              dis2 = d;
 +                                              ee = e2;
 +                                              size = len_v3v3(vec1, vec2);
 +                                              sub_v3_v3v3(dir, vec1, vec2);
 +                                      }
 +                              }
 +                      }
                }
        }
 -#undef EDGE_SLIDE_MIN
 +      
 +      em->bm->ob = t->obedit;
 +      bmesh_begin_edit(em->bm, BMOP_UNTAN_MULTIRES);
  
 +      /*create copies of faces for customdata projection*/
 +      tempsv = sld->sv;
 +      for (i=0; i<sld->totsv; i++, tempsv++) {
 +              BMIter fiter, liter;
 +              BMFace *f;
 +              BMLoop *l;
 +              
 +              BM_ITER(f, &fiter, em->bm, BM_FACES_OF_VERT, tempsv->v) {
 +                      
 +                      if (!BLI_smallhash_haskey(&sld->origfaces, (uintptr_t)f)) {
 +                              BMFace *copyf = BM_Copy_Face(em->bm, f, 1, 1);
 +                              
 +                              BM_Select(em->bm, copyf, 0);
 +                              BM_SetHFlag(copyf, BM_HIDDEN);
 +                              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, copyf) {
 +                                      BM_Select(em->bm, l->v, 0);
 +                                      BM_SetHFlag(l->v, BM_HIDDEN);
 +                                      BM_Select(em->bm, l->e, 0);
 +                                      BM_SetHFlag(l->e, BM_HIDDEN);
 +                              }
  
 -      sld->start[0] = (int) start[0];
 -      sld->start[1] = (int) start[1];
 -      sld->end[0] = (int) end[0];
 -      sld->end[1] = (int) end[1];
 +                              BLI_smallhash_insert(&sld->origfaces, (uintptr_t)f, copyf);
 +                      }
 +              }
 +
 +              BLI_smallhash_insert(&sld->vhash, (uintptr_t)tempsv->v, tempsv);
 +      }
 +      
 +      sld->em = em;
        
 -      if (uvlay_tot) {
 -              int maxnum = 0;
 +      /*zero out start*/
 +      zero_v3(start);
 +      
 +      /*dir holds a vector along edge loop*/
 +      copy_v3_v3(end, dir);
 +      mul_v3_fl(end, 0.5);
 +      
 +      sld->start[0] = t->mval[0] + start[0];
 +      sld->start[1] = t->mval[1] + start[1];
  
 -              uvarray = MEM_callocN( uvlay_tot * sizeof(GHash *), "SlideUVs Array");
 -              sld->totuv = uvlay_tot;
 -              suv_last = slideuvs = MEM_callocN( uvlay_tot * (numadded+1) * sizeof(TransDataSlideUv), "SlideUVs"); /* uvLayers * verts */
 -              suv = NULL;
 +      sld->end[0] = t->mval[0] + end[0];
 +      sld->end[1] = t->mval[1] + end[1];
 +      
 +      sld->perc = 0.0f;
 +      
 +      t->customData = sld;
 +      
 +      BLI_smallhash_release(&table);
 +      BMBVH_FreeBVH(btree);
 +      
 +      return 1;
 +}
  
 -              for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
 +void projectSVData(TransInfo *t, int final)
 +{
 +      SlideData *sld = t->customData;
 +      TransDataSlideVert *tempsv;
 +      BMEditMesh *em = sld->em;
 +      SmallHash visit;
 +      int i;
 +      
 +      if (!em)
 +              return;
 +      
 +      /* BMESH_TODO, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)
 +       * currently all vertex data is interpolated which is nice mostly
 +       * except for shape keys where you dont want to modify UVs for eg.
 +       * current BMesh code doesnt make it easy to pick which data we interpolate
 +       * - campbell */
  
 -                      uvarray[uvlay_idx] = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "createSlideVerts2 gh");
 +      BLI_smallhash_init(&visit);
 +      
 +              for (i=0, tempsv=sld->sv; i<sld->totsv; i++, tempsv++) {
 +              BMIter fiter;
 +              BMFace *f;
 +              
 +              BM_ITER(f, &fiter, em->bm, BM_FACES_OF_VERT, tempsv->v) {
 +                      BMIter liter2;
 +                      BMFace *copyf, *copyf2;
 +                      BMLoop *l2;
 +                      int sel, hide, do_vdata;
 +                      
 +                      if (BLI_smallhash_haskey(&visit, (uintptr_t)f))
 +                              continue;
 +                      
 +                      BLI_smallhash_insert(&visit, (uintptr_t)f, NULL);
 +                      
 +                      /*the face attributes of the copied face will get
 +                        copied over, so its necessary to save the selection
 +                        and hidden state*/
 +                      sel = BM_TestHFlag(f, BM_SELECT);
 +                      hide = BM_TestHFlag(f, BM_HIDDEN);
 +                      
 +                      copyf2 = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)f);
 +                      
 +                      /*project onto copied projection face*/
 +                      BM_ITER(l2, &liter2, em->bm, BM_LOOPS_OF_FACE, f) {
 +                              copyf = copyf2;
 +                              do_vdata = l2->v==tempsv->v;
 +                              
 +                              if (BM_TestHFlag(l2->e, BM_SELECT) || BM_TestHFlag(l2->prev->e, BM_SELECT)) {
 +                                      BMLoop *l3 = l2;
 +                                      
 +                                      do_vdata = 1;
 +                                      
 +                                      if (!BM_TestHFlag(l2->e, BM_SELECT))
 +                                              l3 = l3->prev;
 +                                      
 +                                      if (sld->perc < 0.0 && BM_Vert_In_Face(l3->radial_next->f, tempsv->down)) {
 +                                              copyf = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)l3->radial_next->f);
 +                                      } else if (sld->perc > 0.0 && BM_Vert_In_Face(l3->radial_next->f, tempsv->up)) {
 +                                              copyf = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)l3->radial_next->f);
 +                                      }
 +                                      if (!copyf)
 +                                              continue;  /* shouldn't happen, but protection */
 +                              }
 +                              
 +                              BM_loop_interp_from_face(em->bm, l2, copyf, do_vdata, 0);
  
 -                      for(ev=em->verts.first;ev;ev=ev->next) {
 -                              ev->tmp.l = 0;
 -                      }
 -                      look = vertlist;
 -                      while(look) {
 -                              float *uv_new;
 -                              tempsv  = BLI_ghash_lookup(vertgh,(EditVert*)look->link);
 -
 -                              ev = look->link;
 -                              suv = NULL;
 -                              for(efa = em->faces.first;efa;efa=efa->next) {
 -                                      if (ev->tmp.l != -1) { /* test for self, in this case its invalid */
 -                                              int k=-1; /* face corner */
 -
 -                                              /* Is this vert in the faces corner? */
 -                                              if              (efa->v1==ev)                           k=0;
 -                                              else if (efa->v2==ev)                           k=1;
 -                                              else if (efa->v3==ev)                           k=2;
 -                                              else if (efa->v4 && efa->v4==ev)        k=3;
 -
 -                                              if (k != -1) {
 -                                                      MTFace *tf = CustomData_em_get_n(&em->fdata, efa->data, CD_MTFACE, uvlay_idx);
 -                                                      EditVert *ev_up, *ev_down;
 -
 -                                                      uv_new = tf->uv[k];
 -
 -                                                      if (ev->tmp.l) {
 -                                                              if (fabsf(suv->origuv[0]-uv_new[0]) > 0.0001f || fabs(suv->origuv[1]-uv_new[1]) > 0.0001f) {
 -                                                                      ev->tmp.l = -1; /* Tag as invalid */
 -                                                                      BLI_linklist_free(suv->fuv_list,NULL);
 -                                                                      suv->fuv_list = NULL;
 -                                                                      BLI_ghash_remove(uvarray[uvlay_idx],ev, NULL, NULL);
 -                                                                      suv = NULL;
 -                                                                      break;
 -                                                              }
 -                                                      } else {
 -                                                              ev->tmp.l = 1;
 -                                                              suv = suv_last;
 -
 -                                                              suv->fuv_list = NULL;
 -                                                              suv->uv_up = suv->uv_down = NULL;
 -                                                              suv->origuv[0] = uv_new[0];
 -                                                              suv->origuv[1] = uv_new[1];
 -
 -                                                              BLI_linklist_prepend(&suv->fuv_list, uv_new);
 -                                                              BLI_ghash_insert(uvarray[uvlay_idx],ev,suv);
 -
 -                                                              suv_last++; /* advance to next slide UV */
 -                                                              maxnum++;
 -                                                      }
 -
 -                                                      /* Now get the uvs along the up or down edge if we can */
 -                                                      if (suv) {
 -                                                              if (!suv->uv_up) {
 -                                                                      ev_up = editedge_getOtherVert(tempsv->up,ev);
 -                                                                      if              (efa->v1==ev_up)                                suv->uv_up = tf->uv[0];
 -                                                                      else if (efa->v2==ev_up)                                suv->uv_up = tf->uv[1];
 -                                                                      else if (efa->v3==ev_up)                                suv->uv_up = tf->uv[2];
 -                                                                      else if (efa->v4 && efa->v4==ev_up)             suv->uv_up = tf->uv[3];
 -                                                              }
 -                                                              if (!suv->uv_down) { /* if the first face was apart of the up edge, it cant be apart of the down edge */
 -                                                                      ev_down = editedge_getOtherVert(tempsv->down,ev);
 -                                                                      if              (efa->v1==ev_down)                              suv->uv_down = tf->uv[0];
 -                                                                      else if (efa->v2==ev_down)                              suv->uv_down = tf->uv[1];
 -                                                                      else if (efa->v3==ev_down)                              suv->uv_down = tf->uv[2];
 -                                                                      else if (efa->v4 && efa->v4==ev_down)   suv->uv_down = tf->uv[3];
 -                                                              }
 -
 -                                                              /* Copy the pointers to the face UV's */
 -                                                              BLI_linklist_prepend(&suv->fuv_list, uv_new);
 -                                                      }
 -                                              }
 +                              if (final) {
 +                                      BM_loop_interp_multires(em->bm, l2, copyf);     
 +                                      if (copyf2 != copyf) {
 +                                              BM_loop_interp_multires(em->bm, l2, copyf2);
                                        }
                                }
 -                              look = look->next;
                        }
 -              } /* end uv layer loop */
 -      } /* end uvlay_tot */
 -
 -      sld->uvhash = uvarray;
 -      sld->slideuv = slideuvs;
 -      sld->vhash = vertgh;
 -      sld->nearest = nearest;
 -      sld->vertlist = vertlist;
 -      sld->edgelist = edgelist;
 -      sld->suv_last = suv_last;
 -      sld->uvlay_tot = uvlay_tot;
 -
 -      // we should have enough info now to slide
 -
 -      t->customData = sld;
 -
 -      return 1;
 +                      
 +                      /*make sure face-attributes are correct (e.g. MTexPoly)*/
 +                      BM_Copy_Attributes(em->bm, em->bm, copyf2, f);
 +                      
 +                      /*restore selection and hidden flags*/
 +                      BM_Select(em->bm, f, sel);
 +                      BM_Hide(em->bm, f, hide);
 +              }
 +      }
 +      
 +      BLI_smallhash_release(&visit);
  }
  
  void freeSlideVerts(TransInfo *t)
  {
 -      TransDataSlideUv *suv;
        SlideData *sld = t->customData;
 -      Mesh *me = t->obedit->data;
 -      int uvlay_idx;
 -
 +      SmallHashIter hiter;
 +      BMFace *copyf;
 +      
 +#if 0 /*BMESH_TODO*/
        if(me->drawflag & ME_DRAWEXTRA_EDGELEN) {
                TransDataSlideVert *tempsv;
                LinkNode *look = sld->vertlist;
                        look = look->next;
                }
        }
 -
 -      //BLI_ghash_free(edgesgh, freeGHash, NULL);
 -      BLI_ghash_free(sld->vhash, NULL, (GHashValFreeFP)MEM_freeN);
 -      BLI_linklist_free(sld->vertlist, NULL);
 -      BLI_linklist_free(sld->edgelist, NULL);
 -
 -      if (sld->uvlay_tot) {
 -              for (uvlay_idx=0; uvlay_idx<sld->uvlay_tot; uvlay_idx++) {
 -                      BLI_ghash_free(sld->uvhash[uvlay_idx], NULL, NULL);
 -              }
 -
 -              suv = sld->suv_last-1;
 -              while (suv >= sld->slideuv) {
 -                      if (suv->fuv_list) {
 -                              BLI_linklist_free(suv->fuv_list,NULL);
 -                      }
 -                      suv--;
 -              }
 -
 -              MEM_freeN(sld->slideuv);
 -              MEM_freeN(sld->uvhash);
 +#endif
 +      
 +      if (!sld)
 +              return;
 +      
 +      /*handle multires reprojection, done
 +      on transform completion since it's
 +      really slow -joeedh*/
 +      if (t->state != TRANS_CANCEL) {
 +              projectSVData(t, 1);
 +      } else {
 +              sld->perc = 0.0;
 +              projectSVData(t, 0);
        }
 +      
 +      copyf = BLI_smallhash_iternew(&sld->origfaces, &hiter, NULL);
 +      for (; copyf; copyf=BLI_smallhash_iternext(&hiter, NULL)) {
 +              BM_Kill_Face_Verts(sld->em->bm, copyf);
 +      }
 +      
 +      sld->em->bm->ob = t->obedit;
 +      bmesh_end_edit(sld->em->bm, BMOP_UNTAN_MULTIRES);
  
 +      BLI_smallhash_release(&sld->vhash);
 +      BLI_smallhash_release(&sld->origfaces);
 +      
 +      MEM_freeN(sld->sv);
        MEM_freeN(sld);
 +      
        t->customData = NULL;
 +      
 +      recalcData(t);
  }
  
  void initEdgeSlide(TransInfo *t)
  int doEdgeSlide(TransInfo *t, float perc)
  {
        SlideData *sld = t->customData;
 -      EditVert *ev, *nearest = sld->nearest;
 -      EditVert *centerVert, *upVert, *downVert;
 -      LinkNode *vertlist=sld->vertlist, *look;
 -      GHash *vertgh = sld->vhash;
 -      TransDataSlideVert *tempsv;
 -      float len;
 -      int prop=1, flip=0;
 -      /* UV correction vars */
 -      GHash **uvarray= sld->uvhash;
 -      const int  uvlay_tot= sld->uvlay_tot;
 -      int uvlay_idx;
 -      TransDataSlideUv *suv;
 -      float uv_tmp[2];
 -      LinkNode *fuv_link;
 -
 -      tempsv = BLI_ghash_lookup(vertgh,nearest);
 -
 -      centerVert = editedge_getSharedVert(tempsv->up, tempsv->down);
 -      upVert = editedge_getOtherVert(tempsv->up, centerVert);
 -      downVert = editedge_getOtherVert(tempsv->down, centerVert);
 -
 -      len = MIN2(perc, len_v3v3(upVert->co,downVert->co));
 -      len = MAX2(len, 0);
 -
 -      //Adjust Edgeloop
 -      if(prop) {
 -              look = vertlist;
 -              while(look) {
 -                      EditVert *tempev;
 -                      ev = look->link;
 -                      tempsv = BLI_ghash_lookup(vertgh,ev);
 -
 -                      tempev = editedge_getOtherVert((perc>=0)?tempsv->up:tempsv->down, ev);
 -                      interp_v3_v3v3(ev->co, tempsv->origvert.co, tempev->co, fabs(perc));
 -
 -                      if (uvlay_tot) {
 -                              for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
 -                                      suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev );
 -                                      if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) {
 -                                              interp_v2_v2v2(uv_tmp, suv->origuv,  (perc>=0)?suv->uv_up:suv->uv_down, fabs(perc));
 -                                              fuv_link = suv->fuv_list;
 -                                              while (fuv_link) {
 -                                                      copy_v2_v2(((float *)fuv_link->link), uv_tmp);
 -                                                      fuv_link = fuv_link->next;
 -                                              }
 -                                      }
 -                              }
 -                      }
 +      TransDataSlideVert *svlist = sld->sv, *sv;
 +      float vec[3];
 +      int i;
  
 -                      look = look->next;
 -              }
 -      }
 -      else {
 -              //Non prop code
 -              look = vertlist;
 -              while(look) {
 -                      float newlen, edgelen;
 -                      ev = look->link;
 -                      tempsv = BLI_ghash_lookup(vertgh,ev);
 -                      edgelen = len_v3v3(editedge_getOtherVert(tempsv->up,ev)->co,editedge_getOtherVert(tempsv->down,ev)->co);
 -                      newlen = (edgelen != 0.0f)? (len / edgelen): 0.0f;
 -                      if(newlen > 1.0f) {newlen = 1.0;}
 -                      if(newlen < 0.0f) {newlen = 0.0;}
 -                      if(flip == 0) {
 -                              interp_v3_v3v3(ev->co, editedge_getOtherVert(tempsv->down,ev)->co, editedge_getOtherVert(tempsv->up,ev)->co, fabs(newlen));
 -                              if (uvlay_tot) {
 -                                      /* dont do anything if no UVs */
 -                                      for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
 -                                              suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev );
 -                                              if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) {
 -                                                      interp_v2_v2v2(uv_tmp, suv->uv_down, suv->uv_up, fabs(newlen));
 -                                                      fuv_link = suv->fuv_list;
 -                                                      while (fuv_link) {
 -                                                              copy_v2_v2(((float *)fuv_link->link), uv_tmp);
 -                                                              fuv_link = fuv_link->next;
 -                                                      }
 -                                              }
 -                                      }
 -                              }
 -                      } else{
 -                              interp_v3_v3v3(ev->co, editedge_getOtherVert(tempsv->up,ev)->co, editedge_getOtherVert(tempsv->down,ev)->co, fabs(newlen));
 -
 -                              if (uvlay_tot) {
 -                                      /* dont do anything if no UVs */
 -                                      for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) {
 -                                              suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev );
 -                                              if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) {
 -                                                      interp_v2_v2v2(uv_tmp, suv->uv_up, suv->uv_down, fabs(newlen));
 -                                                      fuv_link = suv->fuv_list;
 -                                                      while (fuv_link) {
 -                                                              copy_v2_v2(((float *)fuv_link->link), uv_tmp);
 -                                                              fuv_link = fuv_link->next;
 -                                                      }
 -                                              }
 -                                      }
 -                              }
 -                      }
 -                      look = look->next;
 -              }
 +      sld->perc = perc;
  
 +      sv = svlist;
 +      for (i=0; i<sld->totsv; i++, sv++) {
 +              if (perc > 0.0f) {
 +                      copy_v3_v3(vec, sv->upvec);
 +                      mul_v3_fl(vec, perc);
 +                      add_v3_v3v3(sv->v->co, sv->origvert.co, vec);
 +              } else {
 +                      copy_v3_v3(vec, sv->downvec);
 +                      mul_v3_fl(vec, -perc);
 +                      add_v3_v3v3(sv->v->co, sv->origvert.co, vec);
 +              }
        }
 -
 +      
 +      projectSVData(t, 0);
 +      
        return 1;
  }
  
index 409dbdf33afd38e62c2bce325b3f0c888976d104,0e053e6849628329cd51b385da0292d94688162f..82920ca51ffe3bca70e1be1888451faf10a76d5a
@@@ -71,7 -71,6 +71,7 @@@
  #include "BKE_mesh.h"
  #include "BKE_nla.h"
  #include "BKE_context.h"
 +#include "BKE_tessmesh.h"
  #include "BKE_tracking.h"
  
  #include "ED_anim_api.h"
@@@ -234,10 -233,10 +234,10 @@@ static void clipMirrorModifier(TransInf
  }
  
  /* assumes obedit set to mesh object */
 -static void editmesh_apply_to_mirror(TransInfo *t)
 +static void editbmesh_apply_to_mirror(TransInfo *t)
  {
        TransData *td = t->data;
 -      EditVert *eve;
 +      BMVert *eve;
        int i;
        
        for(i = 0 ; i < t->total; i++, td++) {
@@@ -372,6 -371,7 +372,6 @@@ static void recalcData_actedit(TransInf
                BLI_freelistN(&anim_data);
        }
  }
 -
  /* helper for recalcData() - for Graph Editor transforms */
  static void recalcData_graphedit(TransInfo *t)
  {
@@@ -619,6 -619,65 +619,65 @@@ static void recalcData_nla(TransInfo *t
        }
  }
  
+ /* helper for recalcData() - for Image Editor transforms */
+ static void recalcData_image(TransInfo *t)
+ {
+       if (t->obedit && t->obedit->type == OB_MESH) {
+               SpaceImage *sima= t->sa->spacedata.first;
+               
+               flushTransUVs(t);
+               if(sima->flag & SI_LIVE_UNWRAP)
+                       ED_uvedit_live_unwrap_re_solve();
+               
+               DAG_id_tag_update(t->obedit->data, 0);
+       }
+ }
+ /* helper for recalcData() - for Movie Clip transforms */
+ static void recalcData_clip(TransInfo *t)
+ {
+       SpaceClip *sc= t->sa->spacedata.first;
+       MovieClip *clip= ED_space_clip(sc);
+       MovieTrackingTrack *track;
+       
+       if(t->state == TRANS_CANCEL) {
+               track= clip->tracking.tracks.first;
+               while(track) {
+                       if(TRACK_VIEW_SELECTED(sc, track)) {
+                               MovieTrackingMarker *marker= BKE_tracking_ensure_marker(track, sc->user.framenr);
+                               
+                               marker->flag= track->transflag;
+                       }
+                       
+                       track= track->next;
+               }
+       }
+       
+       flushTransTracking(t);
+       
+       track= clip->tracking.tracks.first;
+       while(track) {
+               if(TRACK_VIEW_SELECTED(sc, track)) {
+                       if (t->mode == TFM_TRANSLATION) {
+                               if(TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
+                                       BKE_tracking_clamp_track(track, CLAMP_PAT_POS);
+                               if(TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH))
+                                       BKE_tracking_clamp_track(track, CLAMP_SEARCH_POS);
+                       }
+                       else if (t->mode == TFM_RESIZE) {
+                               if(TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
+                                       BKE_tracking_clamp_track(track, CLAMP_PAT_DIM);
+                               if(TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH))
+                                       BKE_tracking_clamp_track(track, CLAMP_SEARCH_DIM);
+                       }
+               }
+               
+               track= track->next;
+       }
+       
+       DAG_id_tag_update(&clip->id, 0);
+ }
  /* helper for recalcData() - for 3d-view transforms */
  static void recalcData_view3d(TransInfo *t)
  {
                                        calchandlesNurb(nu); /* Cant do testhandlesNurb here, it messes up the h1 and h2 flags */
                                        nu= nu->next;
                                }
 +
                        } 
                        else {
                                /* Normal updating */
                        if(la->editlatt->latt->flag & LT_OUTSIDE) outside_lattice(la->editlatt->latt);
                }
                else if (t->obedit->type == OB_MESH) {
 -                      EditMesh *em = ((Mesh*)t->obedit->data)->edit_mesh;
 +                      BMEditMesh *em = ((Mesh*)t->obedit->data)->edit_btmesh;
                        /* mirror modifier clipping? */
                        if(t->state != TRANS_CANCEL) {
                                /* apply clipping after so we never project past the clip plane [#25423] */
                                clipMirrorModifier(t, t->obedit);
                        }
                        if((t->options & CTX_NO_MIRROR) == 0 && (t->flag & T_MIRROR))
 -                              editmesh_apply_to_mirror(t);
 +                              editbmesh_apply_to_mirror(t);
                                
                        DAG_id_tag_update(t->obedit->data, 0);  /* sets recalc flags */
                        
 -                      recalc_editnormals(em);
 +                      EDBM_RecalcNormals(em);
 +                      BMEdit_RecalcTesselation(em);
                }
                else if(t->obedit->type==OB_ARMATURE) { /* no recalc flag, does pose */
                        bArmature *arm= t->obedit->data;
@@@ -855,60 -912,13 +914,13 @@@ void recalcData(TransInfo *t
                recalcData_nla(t);
        }
        else if (t->spacetype == SPACE_IMAGE) {
-               if (t->obedit && t->obedit->type == OB_MESH) {
-                       SpaceImage *sima= t->sa->spacedata.first;
-                       
-                       flushTransUVs(t);
-                       if(sima->flag & SI_LIVE_UNWRAP)
-                               ED_uvedit_live_unwrap_re_solve();
-                       
-                       DAG_id_tag_update(t->obedit->data, 0);
-               }
+               recalcData_image(t);
        }
        else if (t->spacetype == SPACE_VIEW3D) {
                recalcData_view3d(t);
        }
        else if (t->spacetype == SPACE_CLIP) {
-               SpaceClip *sc= t->sa->spacedata.first;
-               MovieClip *clip= ED_space_clip(sc);
-               MovieTrackingTrack *track;
-               if(t->state == TRANS_CANCEL) {
-                       track= clip->tracking.tracks.first;
-                       while(track) {
-                               if(TRACK_VIEW_SELECTED(sc, track)) {
-                                       MovieTrackingMarker *marker= BKE_tracking_ensure_marker(track, sc->user.framenr);
-                                       marker->flag= track->transflag;
-                               }
-                               track= track->next;
-                       }
-               }
-               flushTransTracking(t);
-               track= clip->tracking.tracks.first;
-               while(track) {
-                       if(TRACK_VIEW_SELECTED(sc, track)) {
-                               if (t->mode == TFM_TRANSLATION) {
-                                       if(TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
-                                               BKE_tracking_clamp_track(track, CLAMP_PAT_POS);
-                                       if(TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH))
-                                               BKE_tracking_clamp_track(track, CLAMP_SEARCH_POS);
-                               }
-                               else if (t->mode == TFM_RESIZE) {
-                                       if(TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
-                                               BKE_tracking_clamp_track(track, CLAMP_PAT_DIM);
-                                       if(TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH))
-                                               BKE_tracking_clamp_track(track, CLAMP_SEARCH_DIM);
-                               }
-                       }
-                       track= track->next;
-               }
-               DAG_id_tag_update(&clip->id, 0);
+               recalcData_clip(t);
        }
  }
  
@@@ -1536,13 -1546,13 +1548,13 @@@ void calculateCenter(TransInfo *t
                /* EDIT MODE ACTIVE EDITMODE ELEMENT */
  
                if (t->obedit && t->obedit->type == OB_MESH) {
 -                      EditSelection ese;
 -                      EditMesh *em = BKE_mesh_get_editmesh(t->obedit->data);
 +                      BMEditSelection ese;
 +                      BMEditMesh *em = ((Mesh*)t->obedit->data)->edit_btmesh;
                        
 -                      if (EM_get_actSelection(em, &ese)) {
 -                              EM_editselection_center(t->center, &ese);
 -                              calculateCenter2D(t);
 -                              break;
 +                      if (EDBM_get_actSelection(em, &ese)) {
 +                      EDBM_editselection_center(em, t->center, &ese);
 +                      calculateCenter2D(t);
 +                      break;
                        }
                } /* END EDIT MODE ACTIVE ELEMENT */