=bmesh= merge from trunk at r36529
[blender.git] / source / blender / editors / mesh / editface.c
index 0042ad9483b63ee1497f7ca5202081336478c9f5..06eb1f1ead406e86e028bb486c87150f5fa7d4a9 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/** \file blender/editors/mesh/editface.c
+ *  \ingroup edmesh
+ */
+
+
 
 #include <math.h>
 #include <string.h>
 #include "MEM_guardedalloc.h"
 
 #include "BLI_blenlib.h"
-#include "BLI_arithb.h"
+#include "BLI_math.h"
 #include "BLI_heap.h"
 #include "BLI_edgehash.h"
 #include "BLI_editVert.h"
+#include "BLI_utildefines.h"
 
 #include "IMB_imbuf_types.h"
 #include "IMB_imbuf.h"
 
-#include "DNA_image_types.h"
-#include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
 #include "DNA_object_types.h"
-#include "DNA_space_types.h"
-#include "DNA_screen_types.h"
 #include "DNA_scene_types.h"
-#include "DNA_view3d_types.h"
 
-#include "BKE_brush.h"
-#include "BKE_customdata.h"
-#include "BKE_depsgraph.h"
 #include "BKE_DerivedMesh.h"
-#include "BKE_displist.h"
 #include "BKE_global.h"
 #include "BKE_mesh.h"
-#include "BKE_object.h"
-#include "BKE_texture.h"
-#include "BKE_utildefines.h"
-#include "BKE_customdata.h"
 #include "BKE_context.h"
+#include "BKE_tessmesh.h"
 
 #include "BIF_gl.h"
-#include "BIF_glutil.h"
-
-#include "GPU_draw.h"
-
-#ifndef DISABLE_PYTHON
-//#include "BPY_extern.h"
-//#include "BPY_menus.h"
-#endif
 
 #include "ED_mesh.h"
 #include "ED_screen.h"
-#include "ED_object.h"
 #include "ED_view3d.h"
 
 #include "WM_api.h"
 /* own include */
 #include "mesh_intern.h"
 
-/* ***************** XXX **************** */
-static int pupmenu() {return 0;}
-/* ***************** XXX **************** */
-
-
 /* copy the face flags, most importantly selection from the mesh to the final derived mesh,
  * use in object mode when selecting faces (while painting) */
-void object_facesel_flush_dm(Object *ob)
+void paintface_flush_flags(Object *ob)
 {
        Mesh *me= get_mesh(ob);
        DerivedMesh *dm= ob->derivedFinal;
-       MFace *faces, *mf, *mf_orig;
-       int *index_array = NULL;
+       MPoly *mf_orig;
+       DMFaceIter *fiter;
+       int *index = NULL;
        int totface;
        int i;
        
-       
-       if(me==NULL || dm==NULL || !CustomData_has_layer( &dm->faceData, CD_ORIGINDEX))
+       if(me==NULL || dm==NULL)
                return;
-       
-       faces = dm->getFaceArray(dm);
+
+       fiter = dm->newFaceIter(dm);
        totface = dm->getNumFaces(dm);
-       
-       index_array = dm->getFaceDataArray(dm, CD_ORIGINDEX);
-       
-       mf= faces;
-       
-       for (i= 0; i<totface; i++, mf++) { /* loop over derived mesh faces */
-               mf_orig= me->mface + index_array[i];
-               mf->flag= mf_orig->flag;;
+
+       for (i=0; !fiter->done; fiter->step(fiter), i++) {
+               index = fiter->getCDData(fiter, CD_ORIGINDEX, -1);
+               if (!index) {
+                       fiter->free(fiter);
+                       return;
+               }
+               
+               mf_orig = me->mpoly + *index;
+               fiter->flags = mf_orig->flag; 
        }
+
+       fiter->free(fiter);
 }
 
 /* returns 0 if not found, otherwise 1 */
-int facesel_face_pick(struct bContext *C, Mesh *me, short *mval, unsigned int *index, short rect)
+static int facesel_face_pick(struct bContext *C, Mesh *me, Object *ob, const short mval[2], unsigned int *index, short rect)
 {
+       Scene *scene = CTX_data_scene(C);
        ViewContext vc;
        view3d_set_viewcontext(C, &vc);
 
-       if (!me || me->totface==0)
+       if (!me || me->totpoly==0)
                return 0;
 
-// XXX         if (v3d->flag & V3D_NEEDBACKBUFDRAW) {
+       /*we can't assume mfaces have a correct origindex layer that indices to mpolys.
+         so instead we have to regenerate the tesselation faces altogether.
+         
+         the final 0, 0 paramters causes it to use the index of each mpoly, instead
+         of reading from the origindex layer.*/
+       me->totface = mesh_recalcTesselation(&me->fdata, &me->ldata, &me->pdata, 
+               me->mvert, me->totface, me->totloop, me->totpoly, 0, 0);
+       mesh_update_customdata_pointers(me);
+       makeDerivedMesh(scene, ob, NULL, CD_MASK_BAREMESH, 0);
+
+       // XXX  if (v3d->flag & V3D_INVALID_BACKBUF) {
 // XXX drawview.c!             check_backbuf();
 // XXX         persp(PERSP_VIEW);
 // XXX         }
@@ -142,7 +137,7 @@ int facesel_face_pick(struct bContext *C, Mesh *me, short *mval, unsigned int *i
                *index = view3d_sample_backbuf(&vc, mval[0], mval[1]);
        }
 
-       if ((*index)<=0 || (*index)>(unsigned int)me->totface)
+       if ((*index)<=0 || (*index)>(unsigned int)me->totpoly)
                return 0;
 
        (*index)--;
@@ -152,74 +147,38 @@ int facesel_face_pick(struct bContext *C, Mesh *me, short *mval, unsigned int *i
 
 /* last_sel, use em->act_face otherwise get the last selected face in the editselections
  * at the moment, last_sel is mainly useful for gaking sure the space image dosnt flicker */
-MTFace *EM_get_active_mtface(EditMesh *em, EditFace **act_efa, MCol **mcol, int sloppy)
+MTexPoly *EDBM_get_active_mtface(BMEditMesh *em, BMFace **act_efa, int sloppy)
 {
-       EditFace *efa = NULL;
+       BMFace *efa = NULL;
        
-       if(!EM_texFaceCheck(em))
+       if(!EDBM_texFaceCheck(em))
                return NULL;
        
-       efa = EM_get_actFace(em, sloppy);
+       efa = EDBM_get_actFace(em, sloppy);
        
        if (efa) {
-               if (mcol) {
-                       if (CustomData_has_layer(&em->fdata, CD_MCOL))
-                               *mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
-                       else
-                               *mcol = NULL;
-               }
                if (act_efa) *act_efa = efa; 
-               return CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+               return CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
        }
+
        if (act_efa) *act_efa= NULL;
-       if(mcol) *mcol = NULL;
        return NULL;
 }
 
-void reveal_tface(Scene *scene)
+void paintface_hide(Object *ob, const int unselected)
 {
        Mesh *me;
-       MFace *mface;
+       MPoly *mface;
        int a;
        
-       me= get_mesh(OBACT);
-       if(me==0 || me->totface==0) return;
-       
-       mface= me->mface;
-       a= me->totface;
-       while(a--) {
-               if(mface->flag & ME_HIDE) {
-                       mface->flag |= ME_FACE_SEL;
-                       mface->flag -= ME_HIDE;
-               }
-               mface++;
-       }
-
-       object_facesel_flush_dm(OBACT);
-// XXX notifier!       object_tface_flags_changed(OBACT, 0);
-}
+       me= get_mesh(ob);
+       if(me==NULL || me->totpoly==0) return;
 
-void hide_tface(Scene *scene)
-{
-       Mesh *me;
-       MFace *mface;
-       int a;
-       int shift=0, alt= 0; // XXX
-       
-       me= get_mesh(OBACT);
-       if(me==0 || me->totface==0) return;
-       
-       if(alt) {
-               reveal_tface(scene);
-               return;
-       }
-       
-       mface= me->mface;
-       a= me->totface;
+       mface= me->mpoly;
+       a= me->totpoly;
        while(a--) {
-               if(mface->flag & ME_HIDE);
-               else {
-                       if(shift) {
+               if((mface->flag & ME_HIDE) == 0) {
+                       if(unselected) {
                                if( (mface->flag & ME_FACE_SEL)==0) mface->flag |= ME_HIDE;
                        }
                        else {
@@ -231,36 +190,58 @@ void hide_tface(Scene *scene)
                mface++;
        }
        
-       object_facesel_flush_dm(OBACT);
-// XXX notifier!               object_tface_flags_changed(OBACT, 0);
+       paintface_flush_flags(ob);
+}
+
+
+void paintface_reveal(Object *ob)
+{
+       Mesh *me;
+       MPoly *mface;
+       int a;
+
+       me= get_mesh(ob);
+       if(me==NULL || me->totpoly==0) return;
+
+       mface= me->mpoly;
+       a= me->totpoly;
+       while(a--) {
+               if(mface->flag & ME_HIDE) {
+                       mface->flag |= ME_FACE_SEL;
+                       mface->flag -= ME_HIDE;
+               }
+               mface++;
+       }
+
+       paintface_flush_flags(ob);
 }
 
 /* Set tface seams based on edge data, uses hash table to find seam edges. */
 
-static void hash_add_face(EdgeHash *ehash, MFace *mf)
+static void hash_add_face(EdgeHash *ehash, MPoly *mf, MLoop *mloop)
 {
-       BLI_edgehash_insert(ehash, mf->v1, mf->v2, NULL);
-       BLI_edgehash_insert(ehash, mf->v2, mf->v3, NULL);
-       if(mf->v4) {
-               BLI_edgehash_insert(ehash, mf->v3, mf->v4, NULL);
-               BLI_edgehash_insert(ehash, mf->v4, mf->v1, NULL);
-       }
-       else
-               BLI_edgehash_insert(ehash, mf->v3, mf->v1, NULL);
+       MLoop *ml, *ml2;
+       int i;
+
+       for (i=0, ml=mloop; i<mf->totloop; i++, ml++) {
+               ml2 = mloop + (i+1) % mf->totloop;
+               BLI_edgehash_insert(ehash, ml->v, ml2->v, NULL);
+       }
 }
 
 
-void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index)
+static void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index)
 {
-       MFace *mf;
-       int a, doit=1, mark=0;
-       char *linkflag;
        EdgeHash *ehash, *seamhash;
+       MPoly *mf;
+       MLoop *ml;
        MEdge *med;
+       char *linkflag;
+       int a, b, doit=1, mark=0;
 
        ehash= BLI_edgehash_new();
        seamhash = BLI_edgehash_new();
-       linkflag= MEM_callocN(sizeof(char)*me->totface, "linkflaguv");
+       linkflag= MEM_callocN(sizeof(char)*me->totpoly, "linkflaguv");
 
        for(med=me->medge, a=0; a < me->totedge; a++, med++)
                if(med->flag & ME_SEAM)
@@ -268,17 +249,17 @@ void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index)
 
        if (mode==0 || mode==1) {
                /* only put face under cursor in array */
-               mf= ((MFace*)me->mface) + index;
-               hash_add_face(ehash, mf);
+               mf= ((MPoly*)me->mpoly) + index;
+               hash_add_face(ehash, mf, me->mloop + mf->loopstart);
                linkflag[index]= 1;
        }
        else {
                /* fill array by selection */
-               mf= me->mface;
-               for(a=0; a<me->totface; a++, mf++) {
+               mf= me->mpoly;
+               for(a=0; a<me->totpoly; a++, mf++) {
                        if(mf->flag & ME_HIDE);
                        else if(mf->flag & ME_FACE_SEL) {
-                               hash_add_face(ehash, mf);
+                               hash_add_face(ehash, mf, me->mloop + mf->loopstart);
                                linkflag[a]= 1;
                        }
                }
@@ -288,35 +269,26 @@ void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index)
                doit= 0;
 
                /* expand selection */
-               mf= me->mface;
-               for(a=0; a<me->totface; a++, mf++) {
+               mf= me->mpoly;
+               for(a=0; a<me->totpoly; a++, mf++) {
                        if(mf->flag & ME_HIDE)
                                continue;
 
                        if(!linkflag[a]) {
+                               MLoop *mnextl;
                                mark= 0;
 
-                               if(!BLI_edgehash_haskey(seamhash, mf->v1, mf->v2))
-                                       if(BLI_edgehash_haskey(ehash, mf->v1, mf->v2))
-                                               mark= 1;
-                               if(!BLI_edgehash_haskey(seamhash, mf->v2, mf->v3))
-                                       if(BLI_edgehash_haskey(ehash, mf->v2, mf->v3))
-                                               mark= 1;
-                               if(mf->v4) {
-                                       if(!BLI_edgehash_haskey(seamhash, mf->v3, mf->v4))
-                                               if(BLI_edgehash_haskey(ehash, mf->v3, mf->v4))
-                                                       mark= 1;
-                                       if(!BLI_edgehash_haskey(seamhash, mf->v4, mf->v1))
-                                               if(BLI_edgehash_haskey(ehash, mf->v4, mf->v1))
-                                                       mark= 1;
+                               ml = me->mloop + mf->loopstart;
+                               for (b=0; b<mf->totloop; b++, ml++) {
+                                       mnextl = b < mf->totloop-1 ? ml - 1 : me->mloop + mf->loopstart;
+                                       if (!BLI_edgehash_haskey(seamhash, ml->v, mnextl->v))
+                                               if (!BLI_edgehash_haskey(ehash, ml->v, mnextl->v))
+                                                       mark = 1;
                                }
-                               else if(!BLI_edgehash_haskey(seamhash, mf->v3, mf->v1))
-                                       if(BLI_edgehash_haskey(ehash, mf->v3, mf->v1))
-                                               mark = 1;
 
                                if(mark) {
                                        linkflag[a]= 1;
-                                       hash_add_face(ehash, mf);
+                                       hash_add_face(ehash, mf, me->mloop + mf->loopstart);
                                        doit= 1;
                                }
                        }
@@ -328,42 +300,39 @@ void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index)
        BLI_edgehash_free(seamhash, NULL);
 
        if(mode==0 || mode==2) {
-               for(a=0, mf=me->mface; a<me->totface; a++, mf++)
+               for(a=0, mf=me->mpoly; a<me->totpoly; a++, mf++)
                        if(linkflag[a])
                                mf->flag |= ME_FACE_SEL;
                        else
                                mf->flag &= ~ME_FACE_SEL;
        }
        else if(mode==1) {
-               for(a=0, mf=me->mface; a<me->totface; a++, mf++)
+               for(a=0, mf=me->mpoly; a<me->totpoly; a++, mf++)
                        if(linkflag[a] && (mf->flag & ME_FACE_SEL))
                                break;
 
-               if (a<me->totface) {
-                       for(a=0, mf=me->mface; a<me->totface; a++, mf++)
+               if (a<me->totpoly) {
+                       for(a=0, mf=me->mpoly; a<me->totpoly; a++, mf++)
                                if(linkflag[a])
                                        mf->flag &= ~ME_FACE_SEL;
                }
                else {
-                       for(a=0, mf=me->mface; a<me->totface; a++, mf++)
+                       for(a=0, mf=me->mpoly; a<me->totpoly; a++, mf++)
                                if(linkflag[a])
                                        mf->flag |= ME_FACE_SEL;
                }
        }
 
        MEM_freeN(linkflag);
-
-       // BIF_undo_push("Select linked UV face");
-       // object_tface_flags_changed(OBACT, 0);
 }
 
-void select_linked_tfaces(bContext *C, Object *ob, short mval[2], int mode)
+void paintface_select_linked(bContext *UNUSED(C), Object *ob, short UNUSED(mval[2]), int mode)
 {
        Mesh *me;
        unsigned int index=0;
 
        me = get_mesh(ob);
-       if(me==0 || me->totface==0) return;
+       if(me==NULL || me->totpoly==0) return;
 
        if (mode==0 || mode==1) {
                // XXX - Causes glitches, not sure why
@@ -375,116 +344,101 @@ void select_linked_tfaces(bContext *C, Object *ob, short mval[2], int mode)
 
        select_linked_tfaces_with_seams(mode, me, index);
 
-       object_facesel_flush_dm(ob);
+       paintface_flush_flags(ob);
 }
 
-void deselectall_tface(Object *ob)
+/* note: caller needs to run paintface_flush_flags(ob) after this */
+void paintface_deselect_all_visible(Object *ob, int action, short flush_flags)
 {
        Mesh *me;
-       MFace *mface;
-       int a, sel;
+       MPoly *mface;
+       int a;
 
        me= get_mesh(ob);
-       if(me==0) return;
-       
-       mface= me->mface;
-       a= me->totface;
-       sel= 0;
-       while(a--) {
-               if(mface->flag & ME_HIDE);
-               else if(mface->flag & ME_FACE_SEL) {
-                       sel= 1;
-                       break;
+       if(me==NULL) return;
+       
+       if(action == SEL_INVERT) {
+               mface= me->mpoly;
+               a= me->totpoly;
+               while(a--) {
+                       if((mface->flag & ME_HIDE) == 0) {
+                               mface->flag ^= ME_FACE_SEL;
+                       }
+                       mface++;
                }
-               mface++;
-       }
-       
-       mface= me->mface;
-       a= me->totface;
-       while(a--) {
-               if(mface->flag & ME_HIDE);
-               else {
-                       if(sel) mface->flag &= ~ME_FACE_SEL;
-                       else mface->flag |= ME_FACE_SEL;
+       } else {
+               if (action == SEL_TOGGLE) {
+                       action = SEL_SELECT;
+
+                       mface= me->mpoly;
+                       a= me->totpoly;
+                       while(a--) {
+                               if((mface->flag & ME_HIDE) == 0 && mface->flag & ME_FACE_SEL) {
+                                       action = SEL_DESELECT;
+                                       break;
+                               }
+                               mface++;
+                       }
                }
-               mface++;
        }
 
-       object_facesel_flush_dm(ob);
+       //BMESH_TODO object_facesel_flush_dm(ob);
 // XXX notifier!               object_tface_flags_changed(OBACT, 0);
 }
 
 void selectswap_tface(Scene *scene)
 {
        Mesh *me;
-       MFace *mface;
+       MPoly *mface;
        int a;
                
        me= get_mesh(OBACT);
        if(me==0) return;
        
-       mface= me->mface;
-       a= me->totface;
+       mface= me->mpoly;
+       a= me->totpoly;
        while(a--) {
                if(mface->flag & ME_HIDE);
                else {
                        if(mface->flag & ME_FACE_SEL) mface->flag &= ~ME_FACE_SEL;
                        else mface->flag |= ME_FACE_SEL;
                }
-               mface++;
        }
-       
-       object_facesel_flush_dm(OBACT);
-// XXX notifier!               object_tface_flags_changed(OBACT, 0);
 }
 
-int minmax_tface(Scene *scene, float *min, float *max)
+int paintface_minmax(Object *ob, float *min, float *max)
 {
-       Object *ob;
        Mesh *me;
-       MFace *mf;
-       MTFace *tf;
+       MPoly *mf;
+       MTexPoly *tf;
+       MLoop *ml;
        MVert *mv;
-       int a, ok=0;
+       int a, b, ok=0;
        float vec[3], bmat[3][3];
-       
-       ob = OBACT;
-       if (ob==0) return ok;
+
        me= get_mesh(ob);
-       if(me==0 || me->mtface==0) return ok;
+       if(!me || !me->mtpoly) return ok;
        
-       Mat3CpyMat4(bmat, ob->obmat);
+       copy_m3_m4(bmat, ob->obmat);
 
        mv= me->mvert;
-       mf= me->mface;
-       tf= me->mtface;
-       for (a=me->totface; a>0; a--, mf++, tf++) {
+       mf= me->mpoly;
+       tf= me->mtpoly;
+       for (a=me->totpoly; a>0; a--, mf++, tf++) {
                if (mf->flag & ME_HIDE || !(mf->flag & ME_FACE_SEL))
                        continue;
 
-               VECCOPY(vec, (mv+mf->v1)->co);
-               Mat3MulVecfl(bmat, vec);
-               VecAddf(vec, vec, ob->obmat[3]);
-               DO_MINMAX(vec, min, max);               
-
-               VECCOPY(vec, (mv+mf->v2)->co);
-               Mat3MulVecfl(bmat, vec);
-               VecAddf(vec, vec, ob->obmat[3]);
-               DO_MINMAX(vec, min, max);               
-
-               VECCOPY(vec, (mv+mf->v3)->co);
-               Mat3MulVecfl(bmat, vec);
-               VecAddf(vec, vec, ob->obmat[3]);
-               DO_MINMAX(vec, min, max);               
-
-               if (mf->v4) {
-                       VECCOPY(vec, (mv+mf->v4)->co);
-                       Mat3MulVecfl(bmat, vec);
-                       VecAddf(vec, vec, ob->obmat[3]);
-                       DO_MINMAX(vec, min, max);
+               ml = me->mloop + mf->totloop;
+               for (b=0; b<mf->totloop; b++, ml++) {
+                       VECCOPY(vec, (mv+ml->v)->co);
+                       mul_m3_v3(bmat, vec);
+                       add_v3_v3v3(vec, vec, ob->obmat[3]);
+                       DO_MINMAX(vec, min, max);               
                }
+
                ok= 1;
        }
+
        return ok;
 }
 
@@ -492,35 +446,36 @@ int minmax_tface(Scene *scene, float *min, float *max)
 
 #define ME_SEAM_DONE 2         /* reuse this flag */
 
-static float edgetag_cut_cost(EditMesh *em, int e1, int e2, int vert)
+static float edgetag_cut_cost(BMEditMesh *em, int e1, int e2, int vert)
 {
-       EditVert *v = EM_get_vert_for_index(vert);
-       EditEdge *eed1 = EM_get_edge_for_index(e1), *eed2 = EM_get_edge_for_index(e2);
-       EditVert *v1 = EM_get_vert_for_index( (eed1->v1->tmp.l == vert)? eed1->v2->tmp.l: eed1->v1->tmp.l );
-       EditVert *v2 = EM_get_vert_for_index( (eed2->v1->tmp.l == vert)? eed2->v2->tmp.l: eed2->v1->tmp.l );
+       BMVert *v = EDBM_get_vert_for_index(em, vert);
+       BMEdge *eed1 = EDBM_get_edge_for_index(em, e1), *eed2 = EDBM_get_edge_for_index(em, e2);
+       BMVert *v1 = EDBM_get_vert_for_index(em, (BMINDEX_GET(eed1->v1) == vert)? BMINDEX_GET(eed1->v2): BMINDEX_GET(eed1->v1) );
+       BMVert *v2 = EDBM_get_vert_for_index(em, (BMINDEX_GET(eed2->v1) == vert)? BMINDEX_GET(eed2->v2): BMINDEX_GET(eed2->v1) );
        float cost, d1[3], d2[3];
 
-       cost = VecLenf(v1->co, v->co);
-       cost += VecLenf(v->co, v2->co);
+       cost = len_v3v3(v1->co, v->co);
+       cost += len_v3v3(v->co, v2->co);
 
-       VecSubf(d1, v->co, v1->co);
-       VecSubf(d2, v2->co, v->co);
+       sub_v3_v3v3(d1, v->co, v1->co);
+       sub_v3_v3v3(d2, v2->co, v->co);
 
-       cost = cost + 0.5f*cost*(2.0f - fabs(d1[0]*d2[0] + d1[1]*d2[1] + d1[2]*d2[2]));
+       cost = cost + 0.5f*cost*(2.0f - fabsf(d1[0]*d2[0] + d1[1]*d2[1] + d1[2]*d2[2]));
 
        return cost;
 }
 
-static void edgetag_add_adjacent(EditMesh *em, Heap *heap, int mednum, int vertnum, int *nedges, int *edges, int *prevedge, float *cost)
+static void edgetag_add_adjacent(BMEditMesh *em, Heap *heap, int mednum, int vertnum, 
+                                                                int *nedges, int *edges, int *prevedge, float *cost)
 {
        int startadj, endadj = nedges[vertnum+1];
 
        for (startadj = nedges[vertnum]; startadj < endadj; startadj++) {
                int adjnum = edges[startadj];
-               EditEdge *eedadj = EM_get_edge_for_index(adjnum);
+               BMEdge *eedadj = EDBM_get_edge_for_index(em, adjnum);
                float newcost;
 
-               if (eedadj->f2 & ME_SEAM_DONE)
+               if (eedadj->head.flags[0].f & ME_SEAM_DONE)
                        continue;
 
                newcost = cost[mednum] + edgetag_cut_cost(em, mednum, adjnum, vertnum);
@@ -533,72 +488,94 @@ static void edgetag_add_adjacent(EditMesh *em, Heap *heap, int mednum, int vertn
        }
 }
 
-void edgetag_context_set(Scene *scene, EditEdge *eed, int val)
+void edgetag_context_set(BMEditMesh *em, Scene *scene, BMEdge *eed, int val)
 {
        
        switch (scene->toolsettings->edge_mode) {
        case EDGE_MODE_SELECT:
-               EM_select_edge(eed, val);
+               BM_Select(em->bm, eed, val);
                break;
        case EDGE_MODE_TAG_SEAM:
-               if (val)                {eed->seam = 255;}
-               else                    {eed->seam = 0;}
+               if (val)                {BM_SetHFlag(eed, BM_SEAM);}
+               else                    {BM_ClearHFlag(eed, BM_SEAM);}
                break;
        case EDGE_MODE_TAG_SHARP:
-               if (val)                {eed->sharp = 1;}
-               else                    {eed->sharp = 0;}
+               if (val)                {BM_SetHFlag(eed, BM_SEAM);}
+               else                    {BM_ClearHFlag(eed, BM_SEAM);}
                break;                          
-       case EDGE_MODE_TAG_CREASE:      
-               if (val)                {eed->crease = 1.0f;}
-               else                    {eed->crease = 0.0f;}
+       case EDGE_MODE_TAG_CREASE:
+        {
+               float *crease = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_CREASE);
+               
+               if (val)                {*crease = 1.0f;}
+               else                    {*crease = 0.0f;}
                break;
+        }
        case EDGE_MODE_TAG_BEVEL:
-               if (val)                {eed->bweight = 1.0f;}
-               else                    {eed->bweight = 0.0f;}
+        {
+               float *bweight = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_BWEIGHT);
+
+               if (val)                {*bweight = 1.0f;}
+               else                    {*bweight = 0.0f;}
                break;
+        }
        }
 }
 
-int edgetag_context_check(Scene *scene, EditEdge *eed)
+static float bm_cdata_get_single_float(BMesh *UNUSED(bm), CustomData *cdata, void *element, int type)
+{
+       BMHeader *ele = element;
+       float *f;
+       
+       if (!CustomData_has_layer(cdata, type))
+               return 0.0f;
+       
+       f = CustomData_bmesh_get(cdata, ele->data, type);
+       
+       return *f;
+}
+
+int edgetag_context_check(Scene *scene, BMEditMesh *em, BMEdge *eed)
 {
        switch (scene->toolsettings->edge_mode) {
        case EDGE_MODE_SELECT:
-               return (eed->f & SELECT) ? 1 : 0;
+               return BM_TestHFlag(eed, BM_SELECT) ? 1 : 0;
        case EDGE_MODE_TAG_SEAM:
-               return eed->seam ? 1 : 0;
+               return BM_TestHFlag(eed, BM_SEAM);
        case EDGE_MODE_TAG_SHARP:
-               return eed->sharp ? 1 : 0;
+               return BM_TestHFlag(eed, BM_SHARP);
        case EDGE_MODE_TAG_CREASE:      
-               return eed->crease ? 1 : 0;
+               return bm_cdata_get_single_float(em->bm, &em->bm->edata, eed, CD_CREASE) ? 1 : 0;
        case EDGE_MODE_TAG_BEVEL:
-               return eed->bweight ? 1 : 0;
+               return bm_cdata_get_single_float(em->bm, &em->bm->edata, eed, CD_BWEIGHT) ? 1 : 0;
        }
        return 0;
 }
 
 
-int edgetag_shortest_path(Scene *scene, EditMesh *em, EditEdge *source, EditEdge *target)
+int edgetag_shortest_path(Scene *scene, BMEditMesh *em, BMEdge *source, BMEdge *target)
 {
-       EditEdge *eed;
-       EditVert *ev;
-       
+       BMEdge *eed;
+       BMVert *ev;
+       BMIter iter;
        Heap *heap;
        float *cost;
        int a, totvert=0, totedge=0, *nedges, *edges, *prevedge, mednum = -1, nedgeswap = 0;
 
 
        /* we need the vert */
-       for (ev= em->verts.first, totvert=0; ev; ev= ev->next) {
-               ev->tmp.l = totvert;
+       BM_ITER(ev, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+               BMINDEX_SET(ev, totvert);
                totvert++;
        }
 
-       for (eed= em->edges.first; eed; eed = eed->next) {
-               eed->f2 = 0;
-               if (eed->h) {
-                       eed->f2 |= ME_SEAM_DONE;
+       BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+               eed->head.flags[0].f = 0;
+               if (BM_TestHFlag(eed, BM_SELECT)) {
+                       eed->head.flags[0].f |= ME_SEAM_DONE;
                }
-               eed->tmp.l = totedge;
+
+               BMINDEX_SET(eed, totedge);
                totedge++;
        }
 
@@ -609,9 +586,9 @@ int edgetag_shortest_path(Scene *scene, EditMesh *em, EditEdge *source, EditEdge
        cost = MEM_mallocN(sizeof(*cost)*totedge, "SeamPathCost");
 
        /* count edges, compute adjacent edges offsets and fill adjacent edges */
-       for (eed= em->edges.first; eed; eed = eed->next) {
-               nedges[eed->v1->tmp.l+1]++;
-               nedges[eed->v2->tmp.l+1]++;
+       BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+               nedges[BMINDEX_GET(eed->v1)+1]++;
+               nedges[BMINDEX_GET(eed->v2)+1]++;
        }
 
        for (a=1; a<totvert; a++) {
@@ -621,107 +598,108 @@ int edgetag_shortest_path(Scene *scene, EditMesh *em, EditEdge *source, EditEdge
        }
        nedges[0] = nedges[1] = 0;
 
-       for (a=0, eed= em->edges.first; eed; a++, eed = eed->next) {
-               edges[nedges[eed->v1->tmp.l+1]++] = a;
-               edges[nedges[eed->v2->tmp.l+1]++] = a;
+       BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+               edges[nedges[BMINDEX_GET(eed->v1)+1]++] = a;
+               edges[nedges[BMINDEX_GET(eed->v2)+1]++] = a;
 
                cost[a] = 1e20f;
                prevedge[a] = -1;
+               a++;
        }
 
        /* regular dijkstra shortest path, but over edges instead of vertices */
        heap = BLI_heap_new();
-       BLI_heap_insert(heap, 0.0f, SET_INT_IN_POINTER(source->tmp.l));
-       cost[source->tmp.l] = 0.0f;
-
-       EM_init_index_arrays(em, 1, 1, 0);
+       BLI_heap_insert(heap, 0.0f, SET_INT_IN_POINTER(BMINDEX_GET(source)));
+       cost[BMINDEX_GET(source)] = 0.0f;
 
+       EDBM_init_index_arrays(em, 1, 1, 0);
 
        while (!BLI_heap_empty(heap)) {
                mednum = GET_INT_FROM_POINTER(BLI_heap_popmin(heap));
-               eed = EM_get_edge_for_index( mednum );
+               eed = EDBM_get_edge_for_index(em, mednum);
 
-               if (mednum == target->tmp.l)
+               if (mednum == BMINDEX_GET(target))
                        break;
 
-               if (eed->f2 & ME_SEAM_DONE)
+               if (eed->head.flags[0].f & ME_SEAM_DONE)
                        continue;
 
-               eed->f2 |= ME_SEAM_DONE;
+               eed->head.flags[0].f |= ME_SEAM_DONE;
 
-               edgetag_add_adjacent(em, heap, mednum, eed->v1->tmp.l, nedges, edges, prevedge, cost);
-               edgetag_add_adjacent(em, heap, mednum, eed->v2->tmp.l, nedges, edges, prevedge, cost);
+               edgetag_add_adjacent(em, heap, mednum, BMINDEX_GET(eed->v1), nedges, edges, prevedge, cost);
+               edgetag_add_adjacent(em, heap, mednum, BMINDEX_GET(eed->v2), nedges, edges, prevedge, cost);
        }
        
-       
        MEM_freeN(nedges);
        MEM_freeN(edges);
        MEM_freeN(cost);
        BLI_heap_free(heap, NULL);
 
-       for (eed= em->edges.first; eed; eed = eed->next) {
-               eed->f2 &= ~ME_SEAM_DONE;
+       BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+               eed->head.flags[0].f &= ~ME_SEAM_DONE;
        }
 
-       if (mednum != target->tmp.l) {
+       if (mednum != BMINDEX_GET(target)) {
                MEM_freeN(prevedge);
-               EM_free_index_arrays();
+               EDBM_free_index_arrays(em);
                return 0;
        }
 
        /* follow path back to source and mark as seam */
-       if (mednum == target->tmp.l) {
+       if (mednum == BMINDEX_GET(target)) {
                short allseams = 1;
 
-               mednum = target->tmp.l;
+               mednum = BMINDEX_GET(target);
                do {
-                       eed = EM_get_edge_for_index( mednum );
-                       if (!edgetag_context_check(scene, eed)) {
+                       eed = EDBM_get_edge_for_index(em, mednum);
+                       if (!edgetag_context_check(scene, em, eed)) {
                                allseams = 0;
                                break;
                        }
                        mednum = prevedge[mednum];
-               } while (mednum != source->tmp.l);
+               } while (mednum != BMINDEX_GET(source));
 
-               mednum = target->tmp.l;
+               mednum = BMINDEX_GET(target);
                do {
-                       eed = EM_get_edge_for_index( mednum );
+                       eed = EDBM_get_edge_for_index(em, mednum);
                        if (allseams)
-                               edgetag_context_set(scene, eed, 0);
+                               edgetag_context_set(em, scene, eed, 0);
                        else
-                               edgetag_context_set(scene, eed, 1);
+                               edgetag_context_set(em, scene, eed, 1);
                        mednum = prevedge[mednum];
                } while (mednum != -1);
        }
 
        MEM_freeN(prevedge);
-       EM_free_index_arrays();
+       EDBM_free_index_arrays(em);
        return 1;
 }
 
 /* *************************************** */
-
-static void seam_edgehash_insert_face(EdgeHash *ehash, MFace *mf)
+#if 0
+static void seam_edgehash_insert_face(EdgeHash *ehash, MPoly *mf, MLoop *loopstart)
 {
-       BLI_edgehash_insert(ehash, mf->v1, mf->v2, NULL);
-       BLI_edgehash_insert(ehash, mf->v2, mf->v3, NULL);
-       if (mf->v4) {
-               BLI_edgehash_insert(ehash, mf->v3, mf->v4, NULL);
-               BLI_edgehash_insert(ehash, mf->v4, mf->v1, NULL);
-       }
-       else
-               BLI_edgehash_insert(ehash, mf->v3, mf->v1, NULL);
+       MLoop *ml1, *ml2;
+       int a;
+
+       for (a=0; a<mf->totloop; a++) {
+               ml1 = loopstart + a;
+               ml2 = loopstart + (a+1) % mf->totloop;
+
+               BLI_edgehash_insert(ehash, ml1->v, ml2->v, NULL);
+       }
 }
 
 void seam_mark_clear_tface(Scene *scene, short mode)
 {
        Mesh *me;
-       MFace *mf;
+       MPoly *mf;
+       MLoop *ml1, *ml2;
        MEdge *med;
-       int a;
+       int a, b;
        
        me= get_mesh(OBACT);
-       if(me==0 ||  me->totface==0) return;
+       if(me==0 ||  me->totpoly==0) return;
 
        if (mode == 0)
                mode = pupmenu("Seams%t|Mark Border Seam %x1|Clear Seam %x2");
@@ -732,9 +710,9 @@ void seam_mark_clear_tface(Scene *scene, short mode)
        if (mode == 2) {
                EdgeHash *ehash = BLI_edgehash_new();
 
-               for (a=0, mf=me->mface; a<me->totface; a++, mf++)
+               for (a=0, mf=me->mpoly; a<me->totpoly; a++, mf++)
                        if (!(mf->flag & ME_HIDE) && (mf->flag & ME_FACE_SEL))
-                               seam_edgehash_insert_face(ehash, mf);
+                               seam_edgehash_insert_face(ehash, mf, me->mloop + mf->loopstart);
 
                for (a=0, med=me->medge; a<me->totedge; a++, med++)
                        if (BLI_edgehash_haskey(ehash, med->v1, med->v2))
@@ -747,16 +725,16 @@ void seam_mark_clear_tface(Scene *scene, short mode)
                EdgeHash *ehash1 = BLI_edgehash_new();
                EdgeHash *ehash2 = BLI_edgehash_new();
 
-               for (a=0, mf=me->mface; a<me->totface; a++, mf++) {
+               for (a=0, mf=me->mpoly; a<me->totpoly; a++, mf++) {
                        if ((mf->flag & ME_HIDE) || !(mf->flag & ME_FACE_SEL))
-                               seam_edgehash_insert_face(ehash1, mf);
+                               seam_edgehash_insert_face(ehash1, mf, me->mloop + mf->loopstart);
                        else
-                               seam_edgehash_insert_face(ehash2, mf);
+                               seam_edgehash_insert_face(ehash2, mf, me->mloop + mf->loopstart);
                }
 
                for (a=0, med=me->medge; a<me->totedge; a++, med++)
                        if (BLI_edgehash_haskey(ehash1, med->v1, med->v2) &&
-                           BLI_edgehash_haskey(ehash2, med->v1, med->v2))
+                               BLI_edgehash_haskey(ehash2, med->v1, med->v2))
                                med->flag |= ME_SEAM;
 
                BLI_edgehash_free(ehash1, NULL);
@@ -767,28 +745,30 @@ void seam_mark_clear_tface(Scene *scene, short mode)
 //             unwrap_lscm(1);
 
        me->drawflag |= ME_DRAWSEAMS;
-
-// XXX notifier!               object_tface_flags_changed(OBACT, 1);
 }
+#endif
 
-int face_select(struct bContext *C, Object *ob, short mval[2], int extend)
+int paintface_mouse_select(struct bContext *C, Object *ob, const short mval[2], int extend)
 {
        Mesh *me;
-       MFace *mface, *msel;
+       MPoly *mface, *msel;
        unsigned int a, index;
        
        /* Get the face under the cursor */
        me = get_mesh(ob);
 
-       if (!facesel_face_pick(C, me, mval, &index, 1))
+       if (!facesel_face_pick(C, me, ob, mval, &index, 1))
                return 0;
        
-       msel= (((MFace*)me->mface)+index);
+       if (index >= me->totpoly || index < 0)
+               return 0;
+
+       msel= me->mpoly + index;
        if (msel->flag & ME_HIDE) return 0;
        
        /* clear flags */
-       mface = me->mface;
-       a = me->totface;
+       mface = me->mpoly;
+       a = me->totpoly;
        if (!extend) {
                while (a--) {
                        mface->flag &= ~ME_FACE_SEL;
@@ -808,40 +788,49 @@ int face_select(struct bContext *C, Object *ob, short mval[2], int extend)
        
        /* image window redraw */
        
-       object_facesel_flush_dm(ob);
-// XXX notifier!               object_tface_flags_changed(OBACT, 1);
+       paintface_flush_flags(ob);
        WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
        ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views
        return 1;
 }
 
-void face_borderselect(struct bContext *C, Object *ob, rcti *rect, int select)
+int do_paintface_box_select(ViewContext *vc, rcti *rect, int select, int extend)
 {
+       Object *ob = vc->obact;
        Mesh *me;
-       MFace *mface;
+       MPoly *mface;
        struct ImBuf *ibuf;
        unsigned int *rt;
-       int a, sx, sy, index;
        char *selar;
+       int a, index;
+       int sx= rect->xmax-rect->xmin+1;
+       int sy= rect->ymax-rect->ymin+1;
        
-       ViewContext vc;
-       view3d_set_viewcontext(C, &vc);
-
        me= get_mesh(ob);
-       if(me==0) return;
-       if(me->totface==0) return;
+       if(me==0) return 0;
+       if(me->totpoly==0) return 0;
 
-       selar= MEM_callocN(me->totface+1, "selar");
+       if(me==NULL || me->totface==0 || sx*sy <= 0)
+               return OPERATOR_CANCELLED;
 
-       sx= (rect->xmax-rect->xmin+1);
-       sy= (rect->ymax-rect->ymin+1);
-       if(sx*sy<=0) return;
+       selar= MEM_callocN(me->totpoly+1, "selar");
 
-       view3d_validate_backbuf(&vc);
+       if (extend == 0 && select)
+               paintface_deselect_all_visible(vc->obact, SEL_DESELECT, FALSE);
 
-       ibuf = IMB_allocImBuf(sx,sy,32,IB_rect,0);
+       if (extend == 0 && select) {
+               mface= me->mpoly;
+               for(a=1; a<=me->totpoly; a++, mface++) {
+                       if((mface->flag & ME_HIDE) == 0)
+                               mface->flag &= ~ME_FACE_SEL;
+               }
+       }
+
+       view3d_validate_backbuf(vc);
+
+       ibuf = IMB_allocImBuf(sx,sy,32,IB_rect);
        rt = ibuf->rect;
-       glReadPixels(rect->xmin+vc.ar->winrct.xmin,  rect->ymin+vc.ar->winrct.ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE,  ibuf->rect);
+       glReadPixels(rect->xmin+vc->ar->winrct.xmin,  rect->ymin+vc->ar->winrct.ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE,  ibuf->rect);
        if(ENDIAN_ORDER==B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
 
        a= sx*sy;
@@ -853,8 +842,8 @@ void face_borderselect(struct bContext *C, Object *ob, rcti *rect, int select)
                rt++;
        }
 
-       mface= me->mface;
-       for(a=1; a<=me->totface; a++, mface++) {
+       mface= me->mpoly;
+       for(a=1; a<=me->totpoly; a++, mface++) {
                if(selar[a]) {
                        if(mface->flag & ME_HIDE);
                        else {
@@ -867,11 +856,11 @@ void face_borderselect(struct bContext *C, Object *ob, rcti *rect, int select)
        IMB_freeImBuf(ibuf);
        MEM_freeN(selar);
 
-
-// XXX notifier!                       object_tface_flags_changed(OBACT, 0);
 #ifdef __APPLE__       
        glReadBuffer(GL_BACK);
 #endif
-       
-       object_facesel_flush_dm(ob);
+
+       paintface_flush_flags(vc->obact);
+
+       return OPERATOR_FINISHED;
 }