svn merge ^/trunk/blender -r42009:42053
authorCampbell Barton <ideasman42@gmail.com>
Tue, 22 Nov 2011 11:51:42 +0000 (11:51 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 22 Nov 2011 11:51:42 +0000 (11:51 +0000)
18 files changed:
1  2 
release/scripts/startup/bl_ui/space_view3d.py
source/blender/blenkernel/intern/dynamicpaint.c
source/blender/blenkernel/intern/subsurf_ccg.c
source/blender/blenlib/intern/path_util.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/mesh/loopcut.c
source/blender/editors/object/object_bake.c
source/blender/editors/object/object_edit.c
source/blender/editors/render/render_shading.c
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/space_view3d/drawobject.c
source/blender/makesrna/RNA_access.h
source/blender/makesrna/intern/rna_scene.c
source/blender/makesrna/intern/rna_ui_api.c
source/blender/modifiers/intern/MOD_fluidsim_util.c
source/blender/modifiers/intern/MOD_ocean.c
source/blenderplayer/bad_level_call_stubs/stubs.c
source/creator/creator.c

@@@ -522,10 -522,11 +522,10 @@@ class VIEW3D_MT_select_edit_mesh(Menu)
  
          layout.separator()
  
 -        layout.operator("mesh.select_by_number_vertices", text="Triangles").type = 'TRIANGLES'
 -        layout.operator("mesh.select_by_number_vertices", text="Quads").type = 'QUADS'
 +        layout.operator("mesh.select_by_number_vertices", text = "By Number of Verts")
          if context.scene.tool_settings.mesh_select_mode[2] == False:
              layout.operator("mesh.select_non_manifold", text="Non Manifold")
 -        layout.operator("mesh.select_by_number_vertices", text="Loose Verts/Edges").type = 'OTHER'
 +        layout.operator("mesh.select_loose_verts", text = "Loose Verts/Edges")
          layout.operator("mesh.select_similar", text="Similar")
  
          layout.separator()
@@@ -1496,9 -1497,7 +1496,9 @@@ class VIEW3D_MT_edit_mesh_specials(Menu
          layout.operator_context = 'INVOKE_REGION_WIN'
  
          layout.operator("mesh.subdivide", text="Subdivide")
 +        """
          layout.operator("mesh.subdivide", text="Subdivide Smooth").smoothness = 1.0
 +        """
          layout.operator("mesh.merge", text="Merge...")
          layout.operator("mesh.remove_doubles")
          layout.operator("mesh.hide", text="Hide")
          layout.operator("mesh.select_inverse")
          layout.operator("mesh.flip_normals")
          layout.operator("mesh.vertices_smooth", text="Smooth")
 -        layout.operator("mesh.bevel", text="Bevel")
 +        layout.operator("mesh.bevel", text="Bevel")
          layout.operator("mesh.faces_shade_smooth")
          layout.operator("mesh.faces_shade_flat")
          layout.operator("mesh.blend_from_shape")
@@@ -1628,10 -1627,6 +1628,10 @@@ class VIEW3D_MT_edit_mesh_edges(Menu)
  
          layout.separator()
  
 +        layout.operator("mesh.bridge_edge_loops", text="Bridge Two Edge Loops")
 +
 +        layout.separator()
 +
          layout.operator("TRANSFORM_OT_edge_slide")
          layout.operator("TRANSFORM_OT_edge_crease")
          layout.operator("mesh.loop_multi_select", text="Edge Loop")
@@@ -2208,7 -2203,7 +2208,7 @@@ class VIEW3D_PT_view3d_motion_tracking(
  
          col = layout.column()
          col.active = view.show_reconstruction
-         col.prop(view, "show_tracks_name")
+         col.prop(view, "show_bundle_names")
          col.prop(view, "show_camera_path")
          col.label(text="Tracks:")
          col.prop(view, "tracks_draw_type", text="")
@@@ -976,7 -976,7 +976,7 @@@ struct DynamicPaintSurface *dynamicPain
        surface->wave_timescale = 1.0f;
        surface->wave_spring = 0.20f;
  
-       modifier_path_init(surface->image_output_path, sizeof(surface->image_output_path), "dynamicpaint");
+       modifier_path_init(surface->image_output_path, sizeof(surface->image_output_path), "cache_dynamicpaint");
  
        dynamicPaintSurface_setUniqueName(surface, "Surface");
  
@@@ -1213,9 -1213,9 +1213,9 @@@ static void dynamicPaint_initAdjacencyD
  
                /* For vertex format, count every vertex that is connected by an edge */
                int numOfEdges = surface->canvas->dm->getNumEdges(surface->canvas->dm);
 -              int numOfFaces = surface->canvas->dm->getNumFaces(surface->canvas->dm);
 +              int numOfFaces = surface->canvas->dm->getNumTessFaces(surface->canvas->dm);
                struct MEdge *edge =  surface->canvas->dm->getEdgeArray(surface->canvas->dm);
 -              struct MFace *face =  surface->canvas->dm->getFaceArray(surface->canvas->dm);
 +              struct MFace *face =  surface->canvas->dm->getTessFaceArray(surface->canvas->dm);
  
                /* count number of edges per vertex */
                for (i=0; i<numOfEdges; i++) {
@@@ -1301,8 -1301,8 +1301,8 @@@ void dynamicPaint_setInitialColor(Dynam
        else if (surface->init_color_type == MOD_DPAINT_INITIAL_TEXTURE) {
                Tex *tex = surface->init_texture;
                MTFace *tface;
 -              MFace *mface = dm->getFaceArray(dm);
 -              int numOfFaces = dm->getNumFaces(dm);
 +              MFace *mface = dm->getTessFaceArray(dm);
 +              int numOfFaces = dm->getNumTessFaces(dm);
                char uvname[40];
  
                if (!tex) return;
  
                /* for vertex surface, just copy colors from mcol */
                if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
 -                      MFace *mface = dm->getFaceArray(dm);
 -                      int numOfFaces = dm->getNumFaces(dm);
 +                      MFace *mface = dm->getTessFaceArray(dm);
 +                      int numOfFaces = dm->getNumTessFaces(dm);
  
                        #pragma omp parallel for schedule(static)
                        for (i=0; i<numOfFaces; i++) {
@@@ -1524,7 -1524,7 +1524,7 @@@ static struct DerivedMesh *dynamicPaint
                                                         Object *ob,
                                                         DerivedMesh *dm)
  {     
 -      DerivedMesh *result = CDDM_copy(dm);
 +      DerivedMesh *result = CDDM_copy(dm, 0); /* BMESH_TODO second argument untested, may be incorrect - campbell */
  
        if(pmd->canvas && !(pmd->canvas->flags & MOD_DPAINT_BAKING)) {
  
                                        /* vertex color paint */
                                        if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
  
 -                                              MFace *mface = result->getFaceArray(result);
 -                                              int numOfFaces = result->getNumFaces(result);
 +                                              MFace *mface = result->getTessFaceArray(result);
 +                                              int numOfFaces = result->getNumTessFaces(result);
                                                int i;
                                                PaintPoint* pPoint = (PaintPoint*)sData->type_data;
                                                MCol *col;
                                                if (surface->flags & MOD_DPAINT_PREVIEW) {
                                                        /* Save preview results to weight layer, to be
                                                        *   able to share same drawing methods */
 -                                                      col = result->getFaceDataArray(result, CD_WEIGHT_MCOL);
 +                                                      col = result->getTessFaceDataArray(result, CD_WEIGHT_MCOL);
                                                        if (!col) col = CustomData_add_layer(&result->faceData, CD_WEIGHT_MCOL, CD_CALLOC, NULL, numOfFaces);
  
                                                        if (col) {
                                                if (surface->flags & MOD_DPAINT_PREVIEW) {
                                                        /* Save preview results to weight layer, to be
                                                        *   able to share same drawing methods */
 -                                                      MFace *mface = result->getFaceArray(result);
 +                                                      MFace *mface = result->getTessFaceArray(result);
                                                        int numOfFaces = result->getNumFaces(result);
                                                        int i;
 -                                                      MCol *col = result->getFaceDataArray(result, CD_WEIGHT_MCOL);
 +                                                      MCol *col = result->getTessFaceDataArray(result, CD_WEIGHT_MCOL);
                                                        if (!col) col = CustomData_add_layer(&result->faceData, CD_WEIGHT_MCOL, CD_CALLOC, NULL, numOfFaces);
  
                                                        if (col) {
        /* make a copy of dm to use as brush data */
        if (pmd->brush) {
                if (pmd->brush->dm) pmd->brush->dm->release(pmd->brush->dm);
 -              pmd->brush->dm = CDDM_copy(result);
 +              pmd->brush->dm = CDDM_copy(result, 0); /* BMESH_TODO untested second argument - campbell */
        }
  
        return result;
@@@ -1771,7 -1771,7 +1771,7 @@@ void dynamicPaint_cacheUpdateFrames(Dyn
  void canvas_copyDerivedMesh(DynamicPaintCanvasSettings *canvas, DerivedMesh *dm)
  {
        if (canvas->dm) canvas->dm->release(canvas->dm);
 -      canvas->dm = CDDM_copy(dm);
 +      canvas->dm = CDDM_copy(dm, 0); /* BMESH_TODO second argument untested, may be incorrect - campbell */
  }
  
  /*
@@@ -1924,9 -1924,9 +1924,9 @@@ static int dynamicPaint_findNeighbourPi
        *       TODO: Implement something more accurate / optimized?
        */
        {
 -              int numOfFaces = dm->getNumFaces(dm);
 -              MFace *mface = dm->getFaceArray(dm);
 -              MTFace *tface =  CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
 +              int numOfFaces = dm->getNumTessFaces(dm);
 +              MFace *mface = dm->getTessFaceArray(dm);
 +              MTFace *tface =  CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname); /* BMESH_TODO, is this data valid?, possibly need loop uv's */
  
                /* Get closest edge to that subpixel on UV map  */
                {
@@@ -2092,7 -2092,7 +2092,7 @@@ int dynamicPaint_createUVSurface(Dynami
        if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ) return setError(canvas, "Can't bake non-\"image sequence\" formats.");
  
        numOfFaces = dm->getNumFaces(dm);
 -      mface = dm->getFaceArray(dm);
 +      mface = dm->getTessFaceArray(dm);
  
        /* get uv layer */
        CustomData_validate_layer_name(&dm->faceData, CD_MTFACE, surface->uvlayer_name, uvname);
@@@ -2527,13 -2527,13 +2527,13 @@@ void dynamicPaint_outputSurfaceImage(Dy
        PaintSurfaceData *sData = surface->data;
        ImgSeqFormatData *f_data = (ImgSeqFormatData*)sData->format_data;
        /* OpenEXR or PNG       */
-       int format = (surface->image_fileformat & MOD_DPAINT_IMGFORMAT_OPENEXR) ? R_OPENEXR : R_PNG;
+       int format = (surface->image_fileformat & MOD_DPAINT_IMGFORMAT_OPENEXR) ? R_IMF_IMTYPE_OPENEXR : R_IMF_IMTYPE_PNG;
        char output_file[FILE_MAX];
  
        if (!sData || !sData->type_data) {setError(surface->canvas, "Image save failed: Invalid surface.");return;}
        /* if selected format is openexr, but current build doesnt support one */
        #ifndef WITH_OPENEXR
-       if (format == R_OPENEXR) format = R_PNG;
+       if (format == R_IMF_IMTYPE_OPENEXR) format = R_IMF_IMTYPE_PNG;
        #endif
        BLI_strncpy(output_file, filename, sizeof(output_file));
        BKE_add_image_extension(output_file, format);
        /* Set output format, png in case exr isnt supported */
        ibuf->ftype= PNG|95;
  #ifdef WITH_OPENEXR
-       if (format == R_OPENEXR) {      /* OpenEXR 32-bit float */
+       if (format == R_IMF_IMTYPE_OPENEXR) {   /* OpenEXR 32-bit float */
                ibuf->ftype = OPENEXR | OPENEXR_COMPRESS;
        }
  #endif
@@@ -2693,7 -2693,7 +2693,7 @@@ static void dynamicPaint_freeBrushMater
  void dynamicPaint_doMaterialTex(BrushMaterials *bMats, float color[3], float *alpha, Object *brushOb, const float volume_co[3], const float surface_co[3], int faceIndex, short isQuad, DerivedMesh *orcoDm)
  {
        Material *mat = bMats->mat;
 -      MFace *mface = orcoDm->getFaceArray(orcoDm);
 +      MFace *mface = orcoDm->getTessFaceArray(orcoDm);
  
        /* If no material defined, use the one assigned to the mesh face */
        if (mat == NULL) {
@@@ -3019,7 -3019,7 +3019,7 @@@ static void dynamicPaint_brushMeshCalcu
        scene->r.subframe = prev_sfra;
  
        subframe_updateObject(scene, ob, UPDATE_EVERYTHING, BKE_curframe(scene));
 -      dm_p = CDDM_copy(brush->dm);
 +      dm_p = CDDM_copy(brush->dm, 0); /* BMESH_TODO second argument untested, may be incorrect - campbell */
        numOfVerts_p = dm_p->getNumVerts(dm_p);
        mvert_p = dm_p->getVertArray(dm_p);
        copy_m4_m4(prev_obmat, ob->obmat);
@@@ -3123,9 -3123,9 +3123,9 @@@ static int dynamicPaint_paintMesh(Dynam
                Bounds3D mesh_bb = {0};
                VolumeGrid *grid = bData->grid;
  
 -              dm = CDDM_copy(brush->dm);
 +              dm = CDDM_copy(brush->dm, 0); /* BMESH_TODO second argument untested, may be incorrect - campbell */
                mvert = dm->getVertArray(dm);
 -              mface = dm->getFaceArray(dm);
 +              mface = dm->getTessFaceArray(dm);
                numOfVerts = dm->getNumVerts(dm);
  
                /*      Transform collider vertices to global space
  #include "DNA_object_types.h"
  #include "DNA_scene_types.h"
  
 +#include "BLI_utildefines.h"
  #include "BLI_blenlib.h"
  #include "BLI_edgehash.h"
  #include "BLI_math.h"
  #include "BLI_memarena.h"
  #include "BLI_pbvh.h"
 -#include "BLI_utildefines.h"
  
  #include "BKE_cdderivedmesh.h"
  #include "BKE_global.h"
  #include "BKE_paint.h"
  #include "BKE_scene.h"
  #include "BKE_subsurf.h"
 +#include "BKE_tessmesh.h"
 +
 +#include "PIL_time.h"
 +#include "BLI_array.h"
  
  #include "GL/glew.h"
  
  
  extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */
  
 -static int ccgDM_getVertMapIndex(CCGSubSurf *ss, CCGVert *v);
 -static int ccgDM_getEdgeMapIndex(CCGSubSurf *ss, CCGEdge *e);
 -static int ccgDM_getFaceMapIndex(CCGSubSurf *ss, CCGFace *f);
 +static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
 +                                         int drawInteriorEdges,
 +                                         int useSubsurfUv,
 +                                         DerivedMesh *dm);
  static int ccgDM_use_grid_pbvh(CCGDerivedMesh *ccgdm);
  
  ///
@@@ -164,8 -159,7 +164,8 @@@ static int getEdgeIndex(CCGSubSurf *ss
                return edgeBase + x-1;
        }
  }
 -static int getFaceIndex(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edgeSize, int gridSize) {
 +
 +BM_INLINE int getFaceIndex(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edgeSize, int gridSize) {
        int faceBase = *((int*) ccgSubSurf_getFaceUserData(ss, f));
        int numVerts = ccgSubSurf_getFaceNumVerts(f);
  
        }
  }
  
 -static void get_face_uv_map_vert(UvVertMap *vmap, struct MFace *mf, int fi, CCGVertHDL *fverts) {
 -      unsigned int *fv = &mf->v1;
 +static void get_face_uv_map_vert(UvVertMap *vmap, struct MPoly *mp, struct MLoop *ml, int fi, CCGVertHDL *fverts) {
        UvMapVert *v, *nv;
 -      int j, nverts= mf->v4? 4: 3;
 +      int j, nverts= mp->totloop;
  
 -      for (j=0; j<nverts; j++, fv++) {
 -              for (nv=v=get_uv_map_vert(vmap, *fv); v; v=v->next) {
 +      for (j=0; j<nverts; j++) {
 +              for (nv=v=get_uv_map_vert(vmap, ml[j].v); v; v=v->next) {
                        if (v->separate)
                                nv= v;
                        if (v->f == fi)
        }
  }
  
 -static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, MTFace *tface) {
 -      MFace *mface = dm->getFaceArray(dm);
 +static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, MLoopUV *mloopuv) {
 +      MPoly *mpoly = dm->getPolyArray(dm);
 +      MLoop *mloop = dm->getLoopArray(dm);
        MVert *mvert = dm->getVertArray(dm);
        int totvert = dm->getNumVerts(dm);
        int totface = dm->getNumFaces(dm);
        UvMapVert *v;
        UvVertMap *vmap;
        float limit[2];
 -      CCGVertHDL fverts[4];
 +      CCGVertHDL *fverts= NULL;
 +      BLI_array_declare(fverts);
        EdgeHash *ehash;
        float creaseFactor = (float)ccgSubSurf_getSubdivisionLevels(ss);
  
        limit[0]= limit[1]= STD_UV_CONNECT_LIMIT;
 -      vmap= make_uv_vert_map(mface, tface, totface, totvert, 0, limit);
 +      vmap= make_uv_vert_map(mpoly, mloop, mloopuv, totface, totvert, 0, limit);
        if (!vmap)
                return 0;
        
                                CCGVertHDL vhdl = SET_INT_IN_POINTER(v->f*4 + v->tfindex);
                                float uv[3];
  
 -                              uv[0]= (tface+v->f)->uv[v->tfindex][0];
 -                              uv[1]= (tface+v->f)->uv[v->tfindex][1];
 +                              uv[0]= mloopuv[mpoly[v->f].loopstart + v->tfindex].uv[0];
 +                              uv[1]= mloopuv[mpoly[v->f].loopstart + v->tfindex].uv[1];
                                uv[2]= 0.0f;
  
                                ccgSubSurf_syncVert(ss, vhdl, uv, seam, &ssv);
        ehash = BLI_edgehash_new();
  
        for (i=0; i<totface; i++) {
 -              MFace *mf = &((MFace*) mface)[i];
 -              int nverts= mf->v4? 4: 3;
 +              MPoly *mp = &((MPoly*) mpoly)[i];
 +              int nverts= mp->totloop;
                CCGFace *origf= ccgSubSurf_getFace(origss, SET_INT_IN_POINTER(i));
 -              unsigned int *fv = &mf->v1;
 +              /* unsigned int *fv = &mp->v1; */
 +              MLoop *ml= mloop + mp->loopstart;
  
 -              get_face_uv_map_vert(vmap, mf, i, fverts);
 +              BLI_array_empty(fverts);
 +              BLI_array_growitems(fverts, nverts);
 +
 +              get_face_uv_map_vert(vmap, mp, ml, i, fverts);
  
                for (j=0; j<nverts; j++) {
                        int v0 = GET_INT_FROM_POINTER(fverts[j]);
                        int v1 = GET_INT_FROM_POINTER(fverts[(j+1)%nverts]);
 -                      MVert *mv0 = mvert + *(fv+j);
 -                      MVert *mv1 = mvert + *(fv+((j+1)%nverts));
 +                      MVert *mv0 = mvert + (ml[ j ]. v);
 +                      MVert *mv1 = mvert + (ml[ ((j+1)%nverts) ].v);
  
                        if (!BLI_edgehash_haskey(ehash, v0, v1)) {
                                CCGEdge *e, *orige= ccgSubSurf_getFaceEdge(origss, origf, j);
  
        /* create faces */
        for (i=0; i<totface; i++) {
 -              MFace *mf = &((MFace*) mface)[i];
 -              int nverts= mf->v4? 4: 3;
 +              MPoly *mp = &((MPoly*) mpoly)[i];
 +              MLoop *ml= mloop + mp->loopstart;
 +              int nverts= mp->totloop;
                CCGFace *f;
  
 -              get_face_uv_map_vert(vmap, mf, i, fverts);
 +              BLI_array_empty(fverts);
 +              BLI_array_growitems(fverts, nverts);
 +
 +              get_face_uv_map_vert(vmap, mp, ml, i, fverts);
                ccgSubSurf_syncFace(ss, SET_INT_IN_POINTER(i), nverts, fverts, &f);
        }
  
 +      BLI_array_free(fverts);
 +
        free_uv_vert_map(vmap);
        ccgSubSurf_processSync(ss);
  
@@@ -332,22 -315,18 +332,22 @@@ static void set_subsurf_uv(CCGSubSurf *
        CCGSubSurf *uvss;
        CCGFace **faceMap;
        MTFace *tf;
 +      MLoopUV *mluv;
        CCGFaceIterator *fi;
        int index, gridSize, gridFaces, /*edgeSize,*/ totface, x, y, S;
 -      MTFace *dmtface = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, n);
 +      MLoopUV *dmloopuv = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, n);
 +      /* need to update both CD_MTFACE & CD_MLOOPUV, hrmf, we could get away with
 +       * just tface except applying the modifier then looses subsurf UV */
        MTFace *tface = CustomData_get_layer_n(&result->faceData, CD_MTFACE, n);
 +      MLoopUV *mloopuv = CustomData_get_layer_n(&result->loopData, CD_MLOOPUV, n);
  
 -      if(!dmtface || !tface)
 +      if(!dmloopuv || (!tface && !mloopuv))
                return;
  
        /* create a CCGSubSurf from uv's */
        uvss = _getSubSurf(NULL, ccgSubSurf_getSubdivisionLevels(ss), 0, 1, 0);
  
 -      if(!ss_sync_from_uv(uvss, ss, dm, dmtface)) {
 +      if(!ss_sync_from_uv(uvss, ss, dm, dmloopuv)) {
                ccgSubSurf_free(uvss);
                return;
        }
  
        /* load coordinates from uvss into tface */
        tf= tface;
 +      mluv= mloopuv;
  
        for(index = 0; index < totface; index++) {
                CCGFace *f = faceMap[index];
                                        float *c = faceGridData[(y + 1)*gridSize + x + 1].co;
                                        float *d = faceGridData[(y + 1)*gridSize + x + 0].co;
  
 -                                      tf->uv[0][0] = a[0]; tf->uv[0][1] = a[1];
 -                                      tf->uv[1][0] = d[0]; tf->uv[1][1] = d[1];
 -                                      tf->uv[2][0] = c[0]; tf->uv[2][1] = c[1];
 -                                      tf->uv[3][0] = b[0]; tf->uv[3][1] = b[1];
 +                                      if (tface) {
 +                                              tf->uv[0][0] = a[0]; tf->uv[0][1] = a[1];
 +                                              tf->uv[1][0] = d[0]; tf->uv[1][1] = d[1];
 +                                              tf->uv[2][0] = c[0]; tf->uv[2][1] = c[1];
 +                                              tf->uv[3][0] = b[0]; tf->uv[3][1] = b[1];
 +                                      }
 +
 +                                      if (mloopuv) {
 +                                              mluv[0].uv[0] = a[0]; mluv[0].uv[1] = a[1];
 +                                              mluv[1].uv[0] = d[0]; mluv[1].uv[1] = d[1];
 +                                              mluv[2].uv[0] = c[0]; mluv[2].uv[1] = c[1];
 +                                              mluv[3].uv[0] = b[0]; mluv[3].uv[1] = b[1];
 +                                      }
  
                                        tf++;
 +                                      mluv+=4;
                                }
                        }
                }
  }
  
  /* face weighting */
 -static void calc_ss_weights(int gridFaces,
 -                                                      FaceVertWeight **qweight, FaceVertWeight **tweight)
 +typedef struct FaceVertWeightEntry {
 +      FaceVertWeight *weight;
 +      float *w;
 +      int valid;
 +} FaceVertWeightEntry;
 +
 +typedef struct WeightTable {
 +      FaceVertWeightEntry *weight_table;
 +      int len;
 +} WeightTable;
 +
 +static float *get_ss_weights(WeightTable *wtable, int gridCuts, int faceLen)
  {
 -      FaceVertWeight *qw, *tw;
 -      int x, y, j;
 -      int numWeights = gridFaces * gridFaces;
 -
 -      *tweight = MEM_mallocN(sizeof(**tweight) * numWeights, "ssTriWeight");
 -      *qweight = MEM_mallocN(sizeof(**qweight) * numWeights, "ssQuadWeight");
 -
 -      qw = *qweight;
 -      tw = *tweight;
 -
 -      for (y = 0; y < gridFaces; y++) {
 -              for (x = 0; x < gridFaces; x++) {
 -                      for (j = 0; j < 4; j++) {
 -                              int fx = x + (j == 2 || j == 3);
 -                              int fy = y + (j == 1 || j == 2);
 -                              float x_v = (float) fx / gridFaces;
 -                              float y_v = (float) fy / gridFaces;
 -                              float tx_v = (1.0f - x_v), ty_v = (1.0f - y_v);
 -                              float center = (1.0f / 3.0f) * tx_v * ty_v;
 -
 -                              (*tw)[j][0] = center + 0.5f * tx_v * y_v;
 -                              (*tw)[j][2] = center + 0.5f * x_v * ty_v;
 -                              (*tw)[j][1] = 1.0f - (*tw)[j][0] - (*tw)[j][2];
 -                              (*tw)[j][3] = 0.0f;
 -
 -                              tx_v *= 0.5f;
 -                              ty_v *= 0.5f;
 -
 -                              (*qw)[j][3] = tx_v * ty_v;
 -                              (*qw)[j][0] = (*qw)[j][3] + tx_v * y_v;
 -                              (*qw)[j][2] = (*qw)[j][3] + x_v * ty_v;
 -                              (*qw)[j][1] = 1.0f - (*qw)[j][0] - (*qw)[j][2] - (*qw)[j][3];
 +      int x, y, i, j;
 +      float *w, w1, w2, w4, fac, fac2, fx, fy;
  
 +      if (wtable->len <= faceLen) {
 +              void *tmp = MEM_callocN(sizeof(FaceVertWeightEntry)*(faceLen+1), "weight table alloc 2");
 +              
 +              if (wtable->len) {
 +                      memcpy(tmp, wtable->weight_table, sizeof(FaceVertWeightEntry)*wtable->len);
 +                      MEM_freeN(wtable->weight_table);
 +              }
 +              
 +              wtable->weight_table = tmp;
 +              wtable->len = faceLen+1;
 +      }
 +
 +      if (!wtable->weight_table[faceLen].valid) {
 +              wtable->weight_table[faceLen].valid = 1;
 +              wtable->weight_table[faceLen].w = w = MEM_callocN(sizeof(float)*faceLen*faceLen*(gridCuts+2)*(gridCuts+2), "weight table alloc");
 +              fac = 1.0f / (float)faceLen;
 +
 +              for (i=0; i<faceLen; i++) {
 +                      for (x=0; x<gridCuts+2; x++) {
 +                              for (y=0; y<gridCuts+2; y++) {
 +                                      fx = 0.5f - (float)x / (float)(gridCuts+1) / 2.0f;
 +                                      fy = 0.5f - (float)y / (float)(gridCuts+1) / 2.0f;
 +                              
 +                                      fac2 = faceLen - 4;
 +                                      w1 = (1.0f - fx) * (1.0f - fy) + (-fac2*fx*fy*fac);
 +                                      w2 = (1.0f - fx + fac2*fx*-fac) * (fy);
 +                                      w4 = (fx) * (1.0f - fy + -fac2*fy*fac);
 +                                      
 +                                      fac2 = 1.0f - (w1+w2+w4);
 +                                      fac2 = fac2 / (float)(faceLen-3);
 +                                      for (j=0; j<faceLen; j++)
 +                                              w[j] = fac2;
 +                                      
 +                                      w[i] = w1;
 +                                      w[(i-1+faceLen)%faceLen] = w2;
 +                                      w[(i+1)%faceLen] = w4;
 +
 +                                      w += faceLen;
 +                              }
                        }
 -                      tw++;
 -                      qw++;
                }
        }
 +
 +      return wtable->weight_table[faceLen].w;
 +}
 +
 +static void free_ss_weights(WeightTable *wtable)
 +{
 +      int i;
 +
 +      for (i=0; i<wtable->len; i++) {
 +              if (wtable->weight_table[i].valid)
 +                      MEM_freeN(wtable->weight_table[i].w);
 +      }
 +      
 +      if (wtable->weight_table)
 +              MEM_freeN(wtable->weight_table);
 +}
 +
 +#if 0
 +static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
 +                                                               int drawInteriorEdges, int useSubsurfUv,
 +                                                               DerivedMesh *dm, struct MultiresSubsurf *ms)
 +{
 +      DerivedMesh *cgdm, *result;
 +      double curt = PIL_check_seconds_timer();
 +
 +      cgdm = getCCGDerivedMesh(ss, drawInteriorEdges, useSubsurfUv, dm);
 +      result = CDDM_copy(cgdm, 1);
 +
 +      printf("subsurf conversion time: %.6lf\n", PIL_check_seconds_timer() - curt);
 +
 +      cgdm->needsFree = 1;
 +      cgdm->release(cgdm);
 +
 +      CDDM_calc_normals(result);
 +
 +      return result;
  }
 +#endif
  
 -static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm,
 +static int ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm,
                                                                         float (*vertexCos)[3], int useFlatSubdiv)
  {
        float creaseFactor = (float) ccgSubSurf_getSubdivisionLevels(ss);
 -      CCGVertHDL fVerts[4];
 -      int totvert = dm->getNumVerts(dm);
 -      int totedge = dm->getNumEdges(dm);
 -      int totface = dm->getNumFaces(dm);
 -      int i;
 -      int *index;
 +      CCGVertHDL *fVerts = NULL;
 +      BLI_array_declare(fVerts);
        MVert *mvert = dm->getVertArray(dm);
        MEdge *medge = dm->getEdgeArray(dm);
 -      MFace *mface = dm->getFaceArray(dm);
 +      /* MFace *mface = dm->getTessFaceArray(dm); */ /* UNUSED */
        MVert *mv;
        MEdge *me;
 -      MFace *mf;
 +      MLoop *mloop = dm->getLoopArray(dm), *ml;
 +      MPoly *mpoly = dm->getPolyArray(dm), *mp;
 +      /*MFace *mf;*/ /*UNUSED*/
 +      int totvert = dm->getNumVerts(dm);
 +      int totedge = dm->getNumEdges(dm);
 +      /*int totface = dm->getNumTessFaces(dm);*/ /*UNUSED*/
 +      /*int totpoly = dm->getNumFaces(dm);*/ /*UNUSED*/
 +      int i, j;
 +      int *index;
  
        ccgSubSurf_initFullSync(ss);
  
                ((int*)ccgSubSurf_getEdgeUserData(ss, e))[1] = (index)? *index++: i;
        }
  
 -      mf = mface;
 -      index = (int *)dm->getFaceDataArray(dm, CD_ORIGINDEX);
 -      for (i = 0; i < totface; i++, mf++) {
 -              CCGFace *f;
 +      mp = mpoly;
 +      index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
 +      for (i=0; i<dm->numPolyData; i++, mp++) {
 +              CCGFace *f=NULL;
  
 -              fVerts[0] = SET_INT_IN_POINTER(mf->v1);
 -              fVerts[1] = SET_INT_IN_POINTER(mf->v2);
 -              fVerts[2] = SET_INT_IN_POINTER(mf->v3);
 -              fVerts[3] = SET_INT_IN_POINTER(mf->v4);
 +              BLI_array_empty(fVerts);
  
 -              // this is very bad, means mesh is internally consistent.
 -              // it is not really possible to continue without modifying
 -              // other parts of code significantly to handle missing faces.
 -              // since this really shouldn't even be possible we just bail.
 -              if(ccgSubSurf_syncFace(ss, SET_INT_IN_POINTER(i), fVerts[3] ? 4 : 3,
 +              ml = mloop + mp->loopstart;
 +              for (j=0; j<mp->totloop; j++, ml++) {
 +                      BLI_array_append(fVerts, SET_INT_IN_POINTER(ml->v));
 +              }
 +
 +              /* this is very bad, means mesh is internally inconsistent.
 +               * it is not really possible to continue without modifying
 +               * other parts of code significantly to handle missing faces.
 +               * since this really shouldn't even be possible we just bail.*/
 +              if(ccgSubSurf_syncFace(ss, SET_INT_IN_POINTER(i), mp->totloop,
                                                           fVerts, &f) == eCCGError_InvalidValue) {
                        static int hasGivenError = 0;
  
                        if(!hasGivenError) {
 -                              //XXX error("Unrecoverable error in SubSurf calculation,"
 -                              //      " mesh is inconsistent.");
 +                              printf("Unrecoverable error in SubSurf calculation,"
 +                                         " mesh is inconsistent.\n");
  
                                hasGivenError = 1;
                        }
  
 -                      return;
 +                      return 0;
                }
  
 -              ((int*)ccgSubSurf_getFaceUserData(ss, f))[1] = (index)? *index++: i;
 +              ((int*)ccgSubSurf_getFaceUserData(ss, f))[1] = index ? *index++: i;
        }
  
        ccgSubSurf_processSync(ss);
 +
 +      BLI_array_free(fVerts);
 +      return 1;
  }
  
  /***/
@@@ -614,9 -519,9 +614,9 @@@ static int ccgDM_getFaceMapIndex(CCGSub
        return ((int*) ccgSubSurf_getFaceUserData(ss, f))[1];
  }
  
 -static void ccgDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +static void cgdm_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) {
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        CCGVertIterator *vi = ccgSubSurf_getVertIterator(ss);
        CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
        CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
        ccgEdgeIterator_free(ei);
        ccgVertIterator_free(vi);
  }
 -static int ccgDM_getNumVerts(DerivedMesh *dm) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 +static int cgdm_getNumVerts(DerivedMesh *dm) {
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
  
 -      return ccgSubSurf_getNumFinalVerts(ccgdm->ss);
 +      return ccgSubSurf_getNumFinalVerts(cgdm->ss);
  }
 -static int ccgDM_getNumEdges(DerivedMesh *dm) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 +static int cgdm_getNumEdges(DerivedMesh *dm) {
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
  
 -      return ccgSubSurf_getNumFinalEdges(ccgdm->ss);
 +      return ccgSubSurf_getNumFinalEdges(cgdm->ss);
  }
 -static int ccgDM_getNumFaces(DerivedMesh *dm) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 +static int cgdm_getNumTessFaces(DerivedMesh *dm) {
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
  
 -      return ccgSubSurf_getNumFinalFaces(ccgdm->ss);
 +      return ccgSubSurf_getNumFinalFaces(cgdm->ss);
  }
  
  static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv)
  {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        DMGridData *vd;
        int i;
  
        memset(mv, 0, sizeof(*mv));
  
 -      if((vertNum < ccgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumFaces(ss) > 0)) {
 +      if((vertNum < cgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumFaces(ss) > 0)) {
                /* this vert comes from face data */
                int lastface = ccgSubSurf_getNumFaces(ss) - 1;
                CCGFace *f;
                int gridInternalEnd;
  
                i = 0;
 -              while(i < lastface && vertNum >= ccgdm->faceMap[i + 1].startVert)
 +              while(i < lastface && vertNum >= cgdm->faceMap[i + 1].startVert)
                        ++i;
  
 -              f = ccgdm->faceMap[i].face;
 +              f = cgdm->faceMap[i].face;
                numVerts = ccgSubSurf_getFaceNumVerts(f);
  
                gridSideVerts = gridSize - 2;
                gridSideEnd = 1 + numVerts * gridSideVerts;
                gridInternalEnd = gridSideEnd + numVerts * gridInternalVerts;
  
 -              offset = vertNum - ccgdm->faceMap[i].startVert;
 +              offset = vertNum - cgdm->faceMap[i].startVert;
                if(offset < 1) {
                        vd = ccgSubSurf_getFaceCenterData(f);
                        copy_v3_v3(mv->co, vd->co);
                        copy_v3_v3(mv->co, vd->co);
                        normal_float_to_short_v3(mv->no, vd->no);
                }
 -      } else if((vertNum < ccgdm->vertMap[0].startVert) && (ccgSubSurf_getNumEdges(ss) > 0)) {
 +      } else if((vertNum < cgdm->vertMap[0].startVert) && (ccgSubSurf_getNumEdges(ss) > 0)) {
                /* this vert comes from edge data */
                CCGEdge *e;
                int lastedge = ccgSubSurf_getNumEdges(ss) - 1;
                int x;
  
                i = 0;
 -              while(i < lastedge && vertNum >= ccgdm->edgeMap[i + 1].startVert)
 +              while(i < lastedge && vertNum >= cgdm->edgeMap[i + 1].startVert)
                        ++i;
  
 -              e = ccgdm->edgeMap[i].edge;
 +              e = cgdm->edgeMap[i].edge;
  
 -              x = vertNum - ccgdm->edgeMap[i].startVert + 1;
 +              x = vertNum - cgdm->edgeMap[i].startVert + 1;
                vd = ccgSubSurf_getEdgeData(ss, e, x);
                copy_v3_v3(mv->co, vd->co);
                normal_float_to_short_v3(mv->no, vd->no);
        } else {
                /* this vert comes from vert data */
                CCGVert *v;
 -              i = vertNum - ccgdm->vertMap[0].startVert;
 +              i = vertNum - cgdm->vertMap[0].startVert;
  
 -              v = ccgdm->vertMap[i].vert;
 +              v = cgdm->vertMap[i].vert;
                vd = ccgSubSurf_getVertData(ss, v);
                copy_v3_v3(mv->co, vd->co);
                normal_float_to_short_v3(mv->no, vd->no);
@@@ -776,13 -681,13 +776,13 @@@ static void ccgDM_getFinalVertNo(Derive
  
  static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med)
  {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        int i;
  
        memset(med, 0, sizeof(*med));
  
 -      if(edgeNum < ccgdm->edgeMap[0].startEdge) {
 +      if(edgeNum < cgdm->edgeMap[0].startEdge) {
                /* this edge comes from face data */
                int lastface = ccgSubSurf_getNumFaces(ss) - 1;
                CCGFace *f;
                int edgeSize = ccgSubSurf_getEdgeSize(ss);
                int gridSideEdges;
                int gridInternalEdges;
 +                              int lasti, previ;
 +
 +                              i = lastface;
 +                              lasti = 0;
 +                              while (1) {
 +                                      previ = i;
 +                                      if (cgdm->faceMap[i].startEdge >= edgeNum) {
 +                                              i -= fabsf(i-lasti)/2.0f;
 +                                      } else if (cgdm->faceMap[i].startEdge < edgeNum) {
 +                                              i += fabsf(i-lasti)/2.0f;
 +                                      } else {
 +                                              break;
 +                                      }
  
 -              i = 0;
 -              while(i < lastface && edgeNum >= ccgdm->faceMap[i + 1].startEdge)
 +                                      if (i < 0) {
 +                                              i = 0;
 +                                              break;
 +                                      }
 +
 +                                      if (i > lastface) {
 +                                              i = lastface;
 +                                              break;
 +
 +                                      }
 +
 +                                      if (i == lasti)
 +                                         break;
 +
 +                                      lasti = previ;
 +                              }
 +
 +                              i = i > 0 ? i - 1 : i;
 +              while(i < lastface && edgeNum >= cgdm->faceMap[i + 1].startEdge)
                        ++i;
  
 -              f = ccgdm->faceMap[i].face;
 +              f = cgdm->faceMap[i].face;
                /* numVerts = ccgSubSurf_getFaceNumVerts(f); */ /*UNUSED*/
  
                gridSideEdges = gridSize - 1;
                gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2; 
  
 -              offset = edgeNum - ccgdm->faceMap[i].startEdge;
 +              offset = edgeNum - cgdm->faceMap[i].startEdge;
                grid = offset / (gridSideEdges + gridInternalEdges);
                offset %= (gridSideEdges + gridInternalEdges);
  
                short *edgeFlag;
                unsigned int flags = 0;
  
 -              i = (edgeNum - ccgdm->edgeMap[0].startEdge) / (edgeSize - 1);
 +              i = (edgeNum - cgdm->edgeMap[0].startEdge) / (edgeSize - 1);
  
 -              e = ccgdm->edgeMap[i].edge;
 +              e = cgdm->edgeMap[i].edge;
  
                if(!ccgSubSurf_getEdgeNumFaces(e)) flags |= ME_LOOSEEDGE;
  
 -              x = edgeNum - ccgdm->edgeMap[i].startEdge;
 +              x = edgeNum - cgdm->edgeMap[i].startEdge;
  
                med->v1 = getEdgeIndex(ss, e, x, edgeSize);
                med->v2 = getEdgeIndex(ss, e, x+1, edgeSize);
  
 -              edgeFlag = (ccgdm->edgeFlags)? &ccgdm->edgeFlags[i]: NULL;
 +              edgeFlag = (cgdm->edgeFlags)? &cgdm->edgeFlags[i]: NULL;
                if(edgeFlag)
                        flags |= (*edgeFlag & (ME_SEAM | ME_SHARP))
                                         | ME_EDGEDRAW | ME_EDGERENDER;
  
  static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf)
  {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        int gridSize = ccgSubSurf_getGridSize(ss);
        int edgeSize = ccgSubSurf_getEdgeSize(ss);
        int gridSideEdges = gridSize - 1;
        int offset;
        int grid;
        int x, y;
 -      int lastface = ccgSubSurf_getNumFaces(ss) - 1;
 -      char *faceFlags = ccgdm->faceFlags;
 +      /*int lastface = ccgSubSurf_getNumFaces(ss) - 1;*/ /*UNUSED*/
 +      char *faceFlags = cgdm->faceFlags;
  
        memset(mf, 0, sizeof(*mf));
 +      if (faceNum >= cgdm->dm.numFaceData)
 +              return;
  
 -      i = 0;
 -      while(i < lastface && faceNum >= ccgdm->faceMap[i + 1].startFace)
 -              ++i;
 +      i = cgdm->reverseFaceMap[faceNum];
  
 -      f = ccgdm->faceMap[i].face;
 +      f = cgdm->faceMap[i].face;
        /*numVerts = ccgSubSurf_getFaceNumVerts(f);*/ /*UNUSED*/
  
 -      offset = faceNum - ccgdm->faceMap[i].startFace;
 +      offset = faceNum - cgdm->faceMap[i].startFace;
        grid = offset / gridFaces;
        offset %= gridFaces;
        y = offset / gridSideEdges;
  
  static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert)
  {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        DMGridData *vd;
        int index;
        int totvert, totedge, totface;
  
        totface = ccgSubSurf_getNumFaces(ss);
        for(index = 0; index < totface; index++) {
 -              CCGFace *f = ccgdm->faceMap[index].face;
 +              CCGFace *f = cgdm->faceMap[index].face;
                int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
  
                vd= ccgSubSurf_getFaceCenterData(f);
  
        totedge = ccgSubSurf_getNumEdges(ss);
        for(index = 0; index < totedge; index++) {
 -              CCGEdge *e = ccgdm->edgeMap[index].edge;
 +              CCGEdge *e = cgdm->edgeMap[index].edge;
                int x;
  
                for(x = 1; x < edgeSize - 1; x++, i++) {
  
        totvert = ccgSubSurf_getNumVerts(ss);
        for(index = 0; index < totvert; index++) {
 -              CCGVert *v = ccgdm->vertMap[index].vert;
 +              CCGVert *v = cgdm->vertMap[index].vert;
  
                vd= ccgSubSurf_getVertData(ss, v);
                copy_v3_v3(mvert[i].co, vd->co);
  
  static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
  {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        int index;
        int totedge, totface;
        int gridSize = ccgSubSurf_getGridSize(ss);
        int edgeSize = ccgSubSurf_getEdgeSize(ss);
        int i = 0;
 -      short *edgeFlags = ccgdm->edgeFlags;
 +      short *edgeFlags = cgdm->edgeFlags;
  
        totface = ccgSubSurf_getNumFaces(ss);
        for(index = 0; index < totface; index++) {
 -              CCGFace *f = ccgdm->faceMap[index].face;
 +              CCGFace *f = cgdm->faceMap[index].face;
                int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
  
                for(S = 0; S < numVerts; S++) {
                        for(x = 0; x < gridSize - 1; x++) {
                                MEdge *med = &medge[i];
  
 -                              if(ccgdm->drawInteriorEdges)
 +                              if(cgdm->drawInteriorEdges)
                                        med->flag = ME_EDGEDRAW | ME_EDGERENDER;
                                med->v1 = getFaceIndex(ss, f, S, x, 0, edgeSize, gridSize);
                                med->v2 = getFaceIndex(ss, f, S, x + 1, 0, edgeSize, gridSize);
                                        MEdge *med;
  
                                        med = &medge[i];
 -                                      if(ccgdm->drawInteriorEdges)
 +                                      if(cgdm->drawInteriorEdges)
                                                med->flag = ME_EDGEDRAW | ME_EDGERENDER;
                                        med->v1 = getFaceIndex(ss, f, S, x, y,
                                                                                   edgeSize, gridSize);
                                        i++;
  
                                        med = &medge[i];
 -                                      if(ccgdm->drawInteriorEdges)
 +                                      if(cgdm->drawInteriorEdges)
                                                med->flag = ME_EDGEDRAW | ME_EDGERENDER;
                                        med->v1 = getFaceIndex(ss, f, S, y, x,
                                                                                   edgeSize, gridSize);
  
        totedge = ccgSubSurf_getNumEdges(ss);
        for(index = 0; index < totedge; index++) {
 -              CCGEdge *e = ccgdm->edgeMap[index].edge;
 +              CCGEdge *e = cgdm->edgeMap[index].edge;
                unsigned int flags = 0;
                int x;
                int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e));
  
  static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface)
  {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        int index;
        int totface;
        int gridSize = ccgSubSurf_getGridSize(ss);
        int edgeSize = ccgSubSurf_getEdgeSize(ss);
        int i = 0;
 -      char *faceFlags = ccgdm->faceFlags;
 +      char *faceFlags = cgdm->faceFlags;
  
        totface = ccgSubSurf_getNumFaces(ss);
        for(index = 0; index < totface; index++) {
 -              CCGFace *f = ccgdm->faceMap[index].face;
 +              CCGFace *f = cgdm->faceMap[index].face;
                int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
                /* keep types in sync with MFace, avoid many conversions */
                char flag = (faceFlags)? faceFlags[index*2]: ME_SMOOTH;
                                                                                  edgeSize, gridSize);
                                        mf->v4 = getFaceIndex(ss, f, S, x + 1, y + 0,
                                                                                  edgeSize, gridSize);
 +                                      if (faceFlags) {
 +                                              mat_nr = faceFlags[index*2+1];
 +                                              mf->flag = faceFlags[index*2];
 +                                      } else mf->flag = flag;
 +
                                        mf->mat_nr = mat_nr;
                                        mf->flag = flag;
  
        }
  }
  
 -static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +static void ccgDM_copyFinalLoopArray(DerivedMesh *dm, MLoop *mloop)
 +{
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
 +      int index;
 +      int totface;
 +      int gridSize = ccgSubSurf_getGridSize(ss);
 +      int edgeSize = ccgSubSurf_getEdgeSize(ss);
 +      int i = 0;
 +      MLoop *mv;
 +      /* char *faceFlags = cgdm->faceFlags; */ /* UNUSED */
 +
 +      if (!cgdm->ehash) {
 +              MEdge *medge;
 +
 +              cgdm->ehash = BLI_edgehash_new();
 +              medge = cgdm->dm.getEdgeArray((DerivedMesh*)cgdm);
 +
 +              for (i=0; i<cgdm->dm.numEdgeData; i++) {
 +                      BLI_edgehash_insert(cgdm->ehash, medge[i].v1, medge[i].v2, SET_INT_IN_POINTER(i));
 +              }
 +      }
 +
 +      totface = ccgSubSurf_getNumFaces(ss);
 +      mv = mloop;
 +      for(index = 0; index < totface; index++) {
 +              CCGFace *f = cgdm->faceMap[index].face;
 +              int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
 +              /* int flag = (faceFlags)? faceFlags[index*2]: ME_SMOOTH; */ /* UNUSED */
 +              /* int mat_nr = (faceFlags)? faceFlags[index*2+1]: 0; */ /* UNUSED */
 +
 +              for(S = 0; S < numVerts; S++) {
 +                      for(y = 0; y < gridSize - 1; y++) {
 +                              for(x = 0; x < gridSize - 1; x++) {
 +                                      int v1, v2, v3, v4;
 +
 +                                      v1 = getFaceIndex(ss, f, S, x + 0, y + 0,
 +                                                                                edgeSize, gridSize);
 +
 +                                      v2 = getFaceIndex(ss, f, S, x + 0, y + 1,
 +                                                                                edgeSize, gridSize);
 +                                      v3 = getFaceIndex(ss, f, S, x + 1, y + 1,
 +                                                                                edgeSize, gridSize);
 +                                      v4 = getFaceIndex(ss, f, S, x + 1, y + 0,
 +                                                                                edgeSize, gridSize);
 +
 +                                      mv->v = v1;
 +                                      mv->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(cgdm->ehash, v1, v2));
 +                                      mv++, i++;
 +
 +                                      mv->v = v2;
 +                                      mv->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(cgdm->ehash, v2, v3));
 +                                      mv++, i++;
 +
 +                                      mv->v = v3;
 +                                      mv->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(cgdm->ehash, v3, v4));
 +                                      mv++, i++;
 +
 +                                      mv->v = v4;
 +                                      mv->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(cgdm->ehash, v4, v1));
 +                                      mv++, i++;
 +                              }
 +                      }
 +              }
 +      }
 +}
 +
 +
 +static void ccgDM_copyFinalPolyArray(DerivedMesh *dm, MPoly *mface)
 +{
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
 +      int index;
 +      int totface;
 +      int gridSize = ccgSubSurf_getGridSize(ss);
 +      /* int edgeSize = ccgSubSurf_getEdgeSize(ss); */ /* UNUSED */
 +      int i = 0, k = 0;
 +      char *faceFlags = cgdm->faceFlags;
 +
 +      totface = ccgSubSurf_getNumFaces(ss);
 +      for(index = 0; index < totface; index++) {
 +              CCGFace *f = cgdm->faceMap[index].face;
 +              int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
 +              int flag = (faceFlags)? faceFlags[index*2]: ME_SMOOTH;
 +              int mat_nr = (faceFlags)? faceFlags[index*2+1]: 0;
 +
 +              for(S = 0; S < numVerts; S++) {
 +                      for(y = 0; y < gridSize - 1; y++) {
 +                              for(x = 0; x < gridSize - 1; x++) {
 +                                      MPoly *mf = &mface[i];
 +
 +                                      if (faceFlags) {
 +                                              mat_nr = faceFlags[index*2+1];
 +                                              mf->flag = faceFlags[index*2];
 +                                      } else mf->flag = flag;
 +
 +                                      mf->mat_nr = mat_nr;
 +                                      mf->flag = flag;
 +                                      mf->loopstart = k;
 +                                      mf->totloop = 4;
 +
 +                                      k += 4;
 +                                      i++;
 +                              }
 +                      }
 +              }
 +      }
 +}
 +
 +static void cgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) {
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        int edgeSize = ccgSubSurf_getEdgeSize(ss);
        int gridSize = ccgSubSurf_getGridSize(ss);
        int i;
        MEM_freeN(edgeMap2);
        MEM_freeN(faceMap2);
  }
 -static void ccgDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGVertIterator *vi = ccgSubSurf_getVertIterator(ccgdm->ss);
 +static void cgdm_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData) {
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGVertIterator *vi = ccgSubSurf_getVertIterator(cgdm->ss);
  
        for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
                CCGVert *v = ccgVertIterator_getCurrent(vi);
 -              DMGridData *vd = ccgSubSurf_getVertData(ccgdm->ss, v);
 -              int index = ccgDM_getVertMapIndex(ccgdm->ss, v);
 +              DMGridData *vd = ccgSubSurf_getVertData(cgdm->ss, v);
 +              int index = ccgDM_getVertMapIndex(cgdm->ss, v);
  
                if (index!=-1)
                        func(userData, index, vd->co, vd->no, NULL);
  
        ccgVertIterator_free(vi);
  }
 -static void ccgDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +static void cgdm_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData) {
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
        int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
  
  }
  
  static void ccgDM_drawVerts(DerivedMesh *dm) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        int edgeSize = ccgSubSurf_getEdgeSize(ss);
        int gridSize = ccgSubSurf_getGridSize(ss);
        CCGVertIterator *vi;
@@@ -1412,8 -1173,6 +1412,6 @@@ static void ccgdm_pbvh_update(CCGDerive
  static void ccgDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int UNUSED(drawAllEdges)) {
        CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
        CCGSubSurf *ss = ccgdm->ss;
-       CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
-       CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
        int i, j, edgeSize = ccgSubSurf_getEdgeSize(ss);
        int totedge = ccgSubSurf_getNumEdges(ss);
        int gridSize = ccgSubSurf_getGridSize(ss);
        }
  
        if (ccgdm->drawInteriorEdges) {
-               for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
-                       CCGFace *f = ccgFaceIterator_getCurrent(fi);
+               int totface = ccgSubSurf_getNumFaces(ss);
+               for(j = 0; j < totface; j++) {
+                       CCGFace *f = ccgdm->faceMap[j].face;
                        int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
  
                        for (S=0; S<numVerts; S++) {
                        }
                }
        }
-       ccgFaceIterator_free(fi);
-       ccgEdgeIterator_free(ei);
  }
  static void ccgDM_drawLooseEdges(DerivedMesh *dm) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
-       CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
-       int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
+       int totedge = ccgSubSurf_getNumEdges(ss);
+       int i, j, edgeSize = ccgSubSurf_getEdgeSize(ss);
  
-       for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
-               CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
+       for (j=0; j< totedge; j++) {
+               CCGEdge *e = ccgdm->edgeMap[j].edge;
                DMGridData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
  
                if (!ccgSubSurf_getEdgeNumFaces(e)) {
                        glEnd();
                }
        }
-       ccgEdgeIterator_free(ei);
  }
  
  static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
  static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], int fast, int (*setMaterial)(int, void *attribs)) {
        CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
        CCGSubSurf *ss = ccgdm->ss;
-       CCGFaceIterator *fi;
        int gridSize = ccgSubSurf_getGridSize(ss);
        char *faceFlags = ccgdm->faceFlags;
        int step = (fast)? gridSize-1: 1;
+       int i, totface = ccgSubSurf_getNumFaces(ss);
+       int drawcurrent = 0, matnr = -1, shademodel = -1;
  
        ccgdm_pbvh_update(ccgdm);
  
                return;
        }
  
-       fi = ccgSubSurf_getFaceIterator(ss);
-       for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
-               CCGFace *f = ccgFaceIterator_getCurrent(fi);
+       for(i = 0; i < totface; i++) {
+               CCGFace *f = ccgdm->faceMap[i].face;
                int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
                int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
-               int drawSmooth, mat_nr;
+               int new_matnr, new_shademodel;
  
                if(faceFlags) {
-                       drawSmooth = (faceFlags[index*2] & ME_SMOOTH);
-                       mat_nr= faceFlags[index*2 + 1];
+                       new_shademodel = (faceFlags[index*2] & ME_SMOOTH)? GL_SMOOTH: GL_FLAT;
+                       new_matnr= faceFlags[index*2 + 1];
                }
                else {
-                       drawSmooth = 1;
-                       mat_nr= 0;
+                       new_shademodel = GL_SMOOTH;
+                       new_matnr= 0;
                }
                
-               if (!setMaterial(mat_nr+1, NULL))
+               if(shademodel != new_shademodel || matnr != new_matnr) {
+                       matnr= new_matnr;
+                       shademodel= new_shademodel;
+                       drawcurrent= setMaterial(matnr+1, NULL);
+                       glShadeModel(shademodel);
+               }
+               if(!drawcurrent)
                        continue;
  
-               glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT);
                for (S=0; S<numVerts; S++) {
                        DMGridData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
  
-                       if (drawSmooth) {
+                       if (shademodel == GL_SMOOTH) {
                                for (y=0; y<gridSize-1; y+=step) {
                                        glBegin(GL_QUAD_STRIP);
                                        for (x=0; x<gridSize; x+=step) {
                        }
                }
        }
-       ccgFaceIterator_free(fi);
  }
  
        /* Only used by non-editmesh types */
 -static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +static void cgdm_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData) {
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
-       CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
        GPUVertexAttribs gattribs;
        DMVertexAttribs attribs= {{{NULL}}};
 -      /* MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */
 +      /* MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */
        int gridSize = ccgSubSurf_getGridSize(ss);
        int gridFaces = gridSize - 1;
        int edgeSize = ccgSubSurf_getEdgeSize(ss);
 -      char *faceFlags = ccgdm->faceFlags;
 +      char *faceFlags = cgdm->faceFlags;
        int a, b, i, doDraw, numVerts, matnr, new_matnr, totface;
  
 -      ccgdm_pbvh_update(ccgdm);
 +      ccgdm_pbvh_update(cgdm);
  
        doDraw = 0;
        matnr = -1;
  
        totface = ccgSubSurf_getNumFaces(ss);
        for(a = 0, i = 0; i < totface; i++) {
 -              CCGFace *f = ccgdm->faceMap[i].face;
 +              CCGFace *f = cgdm->faceMap[i].face;
                int S, x, y, drawSmooth;
                int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
                int origIndex = ccgDM_getFaceMapIndex(ss, f);
        }
  
  #undef PASSATTRIB
-       ccgFaceIterator_free(fi);
  }
  
 -static void ccgDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) {
 +static void cgdm_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) {
        dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
  }
  
        /* Only used by non-editmesh types */
 -static void ccgDM_drawMappedFacesMat(DerivedMesh *dm, void (*setMaterial)(void *userData, int, void *attribs), int (*setFace)(void *userData, int index), void *userData) {
 +static void cgdm_drawMappedFacesMat(DerivedMesh *dm, void (*setMaterial)(void *userData, int, void *attribs), int (*setFace)(void *userData, int index), void *userData) {
        CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
        CCGSubSurf *ss = ccgdm->ss;
-       CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
        GPUVertexAttribs gattribs;
        DMVertexAttribs attribs= {{{NULL}}};
        int gridSize = ccgSubSurf_getGridSize(ss);
        }
  
  #undef PASSATTRIB
-       ccgFaceIterator_free(fi);
  }
  
  
 -static void ccgDM_drawFacesColored(DerivedMesh *dm, int UNUSED(useTwoSided), unsigned char *col1, unsigned char *col2) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +static void cgdm_drawFacesColored(DerivedMesh *dm, int UNUSED(useTwoSided), unsigned char *col1, unsigned char *col2) {
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
-       CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
        int gridSize = ccgSubSurf_getGridSize(ss);
        unsigned char *cp1, *cp2;
-       int useTwoSide=1;
+       int useTwoSide=1, i, totface;
  
 -      ccgdm_pbvh_update(ccgdm);
 +      ccgdm_pbvh_update(cgdm);
  
        cp1= col1;
        if(col2) {
        }
  
        glBegin(GL_QUADS);
-       for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
-               CCGFace *f = ccgFaceIterator_getCurrent(fi);
+       totface = ccgSubSurf_getNumFaces(ss);
+       for(i = 0; i < totface; i++) {
+               CCGFace *f = ccgdm->faceMap[i].face;
                int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
  
                for (S=0; S<numVerts; S++) {
                }
        }
        glEnd();
-       ccgFaceIterator_free(fi);
  }
  
 -static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
 +static void cgdm_drawFacesTex_common(DerivedMesh *dm,
        int (*drawParams)(MTFace *tface, int has_mcol, int matnr),
        int (*drawParamsMapped)(void *userData, int index),
        void *userData) 
  {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 -      MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
 -      MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
 -      char *faceFlags = ccgdm->faceFlags;
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
 +      MCol *mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL);
 +      MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
 +      char *faceFlags = cgdm->faceFlags;
        int i, totface, flag, gridSize = ccgSubSurf_getGridSize(ss);
        int gridFaces = gridSize - 1;
  
 -      ccgdm_pbvh_update(ccgdm);
 +      ccgdm_pbvh_update(cgdm);
  
        if(!mcol)
 -              mcol = dm->getFaceDataArray(dm, CD_MCOL);
 +              mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
  
        if(!mcol)
 -              mcol = dm->getFaceDataArray(dm, CD_TEXTURE_MCOL);
 +              mcol = dm->getTessFaceDataArray(dm, CD_TEXTURE_MCOL);
  
        totface = ccgSubSurf_getNumFaces(ss);
        for(i = 0; i < totface; i++) {
 -              CCGFace *f = ccgdm->faceMap[i].face;
 +              CCGFace *f = cgdm->faceMap[i].face;
                int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
                int drawSmooth, index = ccgDM_getFaceMapIndex(ss, f);
                int origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
        }
  }
  
 -static void ccgDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, int has_mcol, int matnr))
 +static void cgdm_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, int has_vcol, int matnr))
  {
 -      ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
 +      cgdm_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
  }
  
 -static void ccgDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
 +static void cgdm_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
  {
 -      ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
 +      cgdm_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
  }
  
 -static void ccgDM_drawUVEdges(DerivedMesh *dm)
 +static void cgdm_drawUVEdges(DerivedMesh *dm)
  {
  
 -      MFace *mf = dm->getFaceArray(dm);
 -      MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
 +      MFace *mf = dm->getTessFaceArray(dm);
 +      MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
        int i;
        
        if (tf) {
  
  static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors, int (*setMaterial)(int, void *attribs),
                        int (*compareDrawOptions)(void *userData, int cur_index, int next_index)) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        MCol *mcol= NULL;
        int i, gridSize = ccgSubSurf_getGridSize(ss);
 -      char *faceFlags = ccgdm->faceFlags;
 +      char *faceFlags = cgdm->faceFlags;
        int gridFaces = gridSize - 1, totface;
  
        /* currently unused -- each original face is handled separately */
        (void)compareDrawOptions;
  
        if(useColors) {
 -              mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
 +              mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL);
                if(!mcol)
 -                      mcol = dm->getFaceDataArray(dm, CD_MCOL);
 +                      mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
        }
  
        totface = ccgSubSurf_getNumFaces(ss);
        for(i = 0; i < totface; i++) {
 -              CCGFace *f = ccgdm->faceMap[i].face;
 +              CCGFace *f = cgdm->faceMap[i].face;
                int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
                int drawSmooth, index = ccgDM_getFaceMapIndex(ss, f);
                int origIndex;
                }
        }
  }
 -static void ccgDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +static void cgdm_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) {
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
        int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
  
  
        ccgEdgeIterator_free(ei);
  }
 -static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +static void cgdm_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData) {
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
        int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
  
  
        ccgEdgeIterator_free(ei);
  }
 -static void ccgDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +static void cgdm_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData) {
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
  
        for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
        ccgFaceIterator_free(fi);
  }
  
 -static void ccgDM_release(DerivedMesh *dm) {
 +static void cgdm_release(DerivedMesh *dm) {
        CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
  
        if (DM_release(dm)) {
                                ccgdm->multires.update(dm);
                }
  
 +              if (ccgdm->ehash)
 +                      BLI_edgehash_free(ccgdm->ehash, NULL);
 +
 +              if(ccgdm->reverseFaceMap) MEM_freeN(ccgdm->reverseFaceMap);
                if(ccgdm->gridFaces) MEM_freeN(ccgdm->gridFaces);
                if(ccgdm->gridData) MEM_freeN(ccgdm->gridData);
                if(ccgdm->gridAdjacency) MEM_freeN(ccgdm->gridAdjacency);
        }
  }
  
 +static void ccg_loops_to_corners(CustomData *fdata, CustomData *ldata, 
 +                        CustomData *pdata, int loopstart, int findex, 
 +                        int polyindex, int numTex, int numCol) 
 +{
 +      MTFace *texface;
 +      MTexPoly *texpoly;
 +      MCol *mcol;
 +      MLoopCol *mloopcol;
 +      MLoopUV *mloopuv;
 +      int i, j, hasWCol = CustomData_has_layer(ldata, CD_WEIGHT_MLOOPCOL);
 +
 +      for(i=0; i < numTex; i++){
 +              texface = CustomData_get_n(fdata, CD_MTFACE, findex, i);
 +              texpoly = CustomData_get_n(pdata, CD_MTEXPOLY, polyindex, i);
 +              
 +              texface->tpage = texpoly->tpage;
 +              texface->flag = texpoly->flag;
 +              texface->transp = texpoly->transp;
 +              texface->mode = texpoly->mode;
 +              texface->tile = texpoly->tile;
 +              texface->unwrap = texpoly->unwrap;
 +
 +              mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, loopstart, i);
 +              for (j=0; j<4; j++, mloopuv++) {
 +                      texface->uv[j][0] = mloopuv->uv[0];
 +                      texface->uv[j][1] = mloopuv->uv[1];
 +              }
 +      }
 +
 +      for(i=0; i < numCol; i++){
 +              mloopcol = CustomData_get_n(ldata, CD_MLOOPCOL, loopstart, i);
 +              mcol = CustomData_get_n(fdata, CD_MCOL, findex, i);
 +
 +              for (j=0; j<4; j++, mloopcol++) {
 +                      mcol[j].r = mloopcol->r;
 +                      mcol[j].g = mloopcol->g;
 +                      mcol[j].b = mloopcol->b;
 +                      mcol[j].a = mloopcol->a;
 +              }
 +      }
 +      
 +      if (hasWCol) {
 +              mloopcol = CustomData_get(ldata, loopstart, CD_WEIGHT_MLOOPCOL);
 +              mcol = CustomData_get(fdata, findex, CD_WEIGHT_MCOL);
 +
 +              for (j=0; j<4; j++, mloopcol++) {
 +                      mcol[j].r = mloopcol->r;
 +                      mcol[j].g = mloopcol->g;
 +                      mcol[j].b = mloopcol->b;
 +                      mcol[j].a = mloopcol->a;
 +              }
 +      }
 +}
 +
  static void *ccgDM_get_vert_data_layer(DerivedMesh *dm, int type)
  {
        if(type == CD_ORIGINDEX) {
                /* create origindex on demand to save memory */
 -              CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
 -              CCGSubSurf *ss= ccgdm->ss;
 +              CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
 +              CCGSubSurf *ss= cgdm->ss;
                int *origindex;
                int a, index, totnone, totorig;
  
                        origindex[a]= ORIGINDEX_NONE;
  
                for(index=0; index<totorig; index++, a++) {
 -                      CCGVert *v = ccgdm->vertMap[index].vert;
 -                      origindex[a] = ccgDM_getVertMapIndex(ccgdm->ss, v);
 +                      CCGVert *v = cgdm->vertMap[index].vert;
 +                      origindex[a] = ccgDM_getVertMapIndex(cgdm->ss, v);
                }
  
                return origindex;
@@@ -2478,8 -2174,8 +2471,8 @@@ static void *ccgDM_get_edge_data_layer(
  {
        if(type == CD_ORIGINDEX) {
                /* create origindex on demand to save memory */
 -              CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
 -              CCGSubSurf *ss= ccgdm->ss;
 +              CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
 +              CCGSubSurf *ss= cgdm->ss;
                int *origindex;
                int a, i, index, totnone, totorig, totedge;
                int edgeSize= ccgSubSurf_getEdgeSize(ss);
                        origindex[a]= ORIGINDEX_NONE;
  
                for(index=0; index<totedge; index++) {
 -                      CCGEdge *e= ccgdm->edgeMap[index].edge;
 +                      CCGEdge *e= cgdm->edgeMap[index].edge;
                        int mapIndex= ccgDM_getEdgeMapIndex(ss, e);
  
                        for(i = 0; i < edgeSize - 1; i++, a++)
@@@ -2513,19 -2209,19 +2506,19 @@@ static void *ccgDM_get_face_data_layer(
  {
        if(type == CD_ORIGINDEX) {
                /* create origindex on demand to save memory */
 -              CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
 -              CCGSubSurf *ss= ccgdm->ss;
 +              CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
 +              CCGSubSurf *ss= cgdm->ss;
                int *origindex;
                int a, i, index, totface;
                int gridFaces = ccgSubSurf_getGridSize(ss) - 1;
  
 -              DM_add_face_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
 -              origindex= DM_get_face_data_layer(dm, CD_ORIGINDEX);
 +              DM_add_tessface_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
 +              origindex= DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
  
                totface= ccgSubSurf_getNumFaces(ss);
  
                for(a=0, index=0; index<totface; index++) {
 -                      CCGFace *f = ccgdm->faceMap[index].face;
 +                      CCGFace *f = cgdm->faceMap[index].face;
                        int numVerts = ccgSubSurf_getFaceNumVerts(f);
                        int mapIndex = ccgDM_getFaceMapIndex(ss, f);
  
                return origindex;
        }
  
 -      return DM_get_face_data_layer(dm, type);
 +      return DM_get_tessface_data_layer(dm, type);
  }
  
  static int ccgDM_getNumGrids(DerivedMesh *dm)
  {
 -      CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
 +      CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
        int index, numFaces, numGrids;
  
 -      numFaces= ccgSubSurf_getNumFaces(ccgdm->ss);
 +      numFaces= ccgSubSurf_getNumFaces(cgdm->ss);
        numGrids= 0;
  
        for(index=0; index<numFaces; index++) {
 -              CCGFace *f = ccgdm->faceMap[index].face;
 +              CCGFace *f = cgdm->faceMap[index].face;
                numGrids += ccgSubSurf_getFaceNumVerts(f);
        }
  
  
  static int ccgDM_getGridSize(DerivedMesh *dm)
  {
 -      CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
 -      return ccgSubSurf_getGridSize(ccgdm->ss);
 +      CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
 +      return ccgSubSurf_getGridSize(cgdm->ss);
  }
  
 -static int ccgdm_adjacent_grid(CCGSubSurf *ss, int *gridOffset, CCGFace *f, int S, int offset)
 +static int cgdm_adjacent_grid(CCGSubSurf *ss, int *gridOffset, CCGFace *f, int S, int offset)
  {
        CCGFace *adjf;
        CCGEdge *e;
  
  static void ccgdm_create_grids(DerivedMesh *dm)
  {
 -      CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
 -      CCGSubSurf *ss= ccgdm->ss;
 +      CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
 +      CCGSubSurf *ss= cgdm->ss;
        DMGridData **gridData;
        DMGridAdjacency *gridAdjacency, *adj;
        CCGFace **gridFaces;
        int *gridOffset;
        int index, numFaces, numGrids, S, gIndex /*, gridSize*/;
  
 -      if(ccgdm->gridData)
 +      if(cgdm->gridData)
                return;
        
        numGrids = ccgDM_getNumGrids(dm);
        /*gridSize = ccgDM_getGridSize(dm);*/  /*UNUSED*/
  
        /* compute offset into grid array for each face */
 -      gridOffset = MEM_mallocN(sizeof(int)*numFaces, "ccgdm.gridOffset");
 +      gridOffset = MEM_mallocN(sizeof(int)*numFaces, "cgdm.gridOffset");
  
        for(gIndex = 0, index = 0; index < numFaces; index++) {
 -              CCGFace *f = ccgdm->faceMap[index].face;
 +              CCGFace *f = cgdm->faceMap[index].face;
                int numVerts = ccgSubSurf_getFaceNumVerts(f);
  
                gridOffset[index] = gIndex;
        }
  
        /* compute grid data */
 -      gridData = MEM_mallocN(sizeof(DMGridData*)*numGrids, "ccgdm.gridData");
 -      gridAdjacency = MEM_mallocN(sizeof(DMGridAdjacency)*numGrids, "ccgdm.gridAdjacency");
 -      gridFaces = MEM_mallocN(sizeof(CCGFace*)*numGrids, "ccgdm.gridFaces");
 +      gridData = MEM_mallocN(sizeof(DMGridData*)*numGrids, "cgdm.gridData");
 +      gridAdjacency = MEM_mallocN(sizeof(DMGridAdjacency)*numGrids, "cgdm.gridAdjacency");
 +      gridFaces = MEM_mallocN(sizeof(CCGFace*)*numGrids, "cgdm.gridFaces");
  
        for(gIndex = 0, index = 0; index < numFaces; index++) {
 -              CCGFace *f = ccgdm->faceMap[index].face;
 +              CCGFace *f = cgdm->faceMap[index].face;
                int numVerts = ccgSubSurf_getFaceNumVerts(f);
  
                for(S = 0; S < numVerts; S++, gIndex++) {
  
                        adj->index[0] = gIndex - S + nextS;
                        adj->rotation[0] = 3;
 -                      adj->index[1] = ccgdm_adjacent_grid(ss, gridOffset, f, prevS, 0);
 +                      adj->index[1] = cgdm_adjacent_grid(ss, gridOffset, f, prevS, 0);
                        adj->rotation[1] = 1;
 -                      adj->index[2] = ccgdm_adjacent_grid(ss, gridOffset, f, S, 1);
 +                      adj->index[2] = cgdm_adjacent_grid(ss, gridOffset, f, S, 1);
                        adj->rotation[2] = 3;
                        adj->index[3] = gIndex - S + prevS;
                        adj->rotation[3] = 1;
                }
        }
  
 -      ccgdm->gridData = gridData;
 -      ccgdm->gridFaces = gridFaces;
 -      ccgdm->gridAdjacency = gridAdjacency;
 -      ccgdm->gridOffset = gridOffset;
 +      cgdm->gridData = gridData;
 +      cgdm->gridFaces = gridFaces;
 +      cgdm->gridAdjacency = gridAdjacency;
 +      cgdm->gridOffset = gridOffset;
  }
  
  static DMGridData **ccgDM_getGridData(DerivedMesh *dm)
  {
 -      CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
 +      CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
  
        ccgdm_create_grids(dm);
 -      return ccgdm->gridData;
 +      return cgdm->gridData;
  }
  
  static DMGridAdjacency *ccgDM_getGridAdjacency(DerivedMesh *dm)
  {
 -      CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
 +      CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
  
        ccgdm_create_grids(dm);
 -      return ccgdm->gridAdjacency;
 +      return cgdm->gridAdjacency;
  }
  
  static int *ccgDM_getGridOffset(DerivedMesh *dm)
  {
 -      CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
 +      CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
  
        ccgdm_create_grids(dm);
 -      return ccgdm->gridOffset;
 +      return cgdm->gridOffset;
  }
  
  static ListBase *ccgDM_getFaceMap(Object *ob, DerivedMesh *dm)
@@@ -2758,89 -2454,55 +2751,89 @@@ static struct PBVH *ccgDM_getPBVH(Objec
        return ccgdm->pbvh;
  }
  
 +static void ccgDM_recalcTesselection(DerivedMesh *UNUSED(dm))
 +{
 +      /* Nothing to do: CCG handles creating its own tessfaces */
 +}
 +
 +static void ccgDM_calcNormals(DerivedMesh *UNUSED(dm))
 +{
 +      /* Nothing to do: CCG calculates normals during drawing */
 +}
 +
  static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
                                                                                 int drawInteriorEdges,
                                                                                 int useSubsurfUv,
                                                                                 DerivedMesh *dm)
  {
 -      CCGDerivedMesh *ccgdm = MEM_callocN(sizeof(*ccgdm), "ccgdm");
 +      CCGDerivedMesh *ccgdm = MEM_callocN(sizeof(*ccgdm), "cgdm");
        CCGVertIterator *vi;
        CCGEdgeIterator *ei;
        CCGFaceIterator *fi;
        int index, totvert, totedge, totface;
        int i;
        int vertNum, edgeNum, faceNum;
 +      int *vertOrigIndex, *faceOrigIndex, *polyOrigIndex, *base_polyOrigIndex; /* *edgeOrigIndex - as yet, unused  */
        short *edgeFlags;
        char *faceFlags;
 -      int edgeSize;
 +      int *loopidx = NULL, *vertidx = NULL;
 +      BLI_array_declare(loopidx);
 +      BLI_array_declare(vertidx);
 +      int loopindex, loopindex2;
 +      int edgeSize, has_edge_origindex;
        int gridSize;
 -      int gridFaces;
 +      int gridFaces, gridCuts;
        /*int gridSideVerts;*/
        int gridSideEdges;
 +      int numTex, numCol;
        int gridInternalEdges;
 +      float *w = NULL;
 +      WeightTable wtable = {0};
 +      /* MCol *mcol; */ /* UNUSED */
        MEdge *medge = NULL;
 -      MFace *mface = NULL;
 -      int *orig_indices;
 -      FaceVertWeight *qweight, *tweight;
 +      /* MFace *mface = NULL; */
 +      MPoly *mpoly = NULL;
  
        DM_from_template(&ccgdm->dm, dm, DM_TYPE_CCGDM,
                                         ccgSubSurf_getNumFinalVerts(ss),
                                         ccgSubSurf_getNumFinalEdges(ss),
 +                                       ccgSubSurf_getNumFinalFaces(ss),
 +                                       ccgSubSurf_getNumFinalFaces(ss)*4, 
                                         ccgSubSurf_getNumFinalFaces(ss));
 +      
 +      numTex = CustomData_number_of_layers(&ccgdm->dm.loopData, CD_MLOOPUV);
 +      numCol = CustomData_number_of_layers(&ccgdm->dm.loopData, CD_MLOOPCOL);
 +      
 +      if (numTex && CustomData_number_of_layers(&ccgdm->dm.faceData, CD_MTFACE) != numTex)
 +              CustomData_from_bmeshpoly(&ccgdm->dm.faceData, &ccgdm->dm.polyData, &ccgdm->dm.loopData, ccgSubSurf_getNumFinalFaces(ss));
 +      else if (numCol && CustomData_number_of_layers(&ccgdm->dm.faceData, CD_MCOL) != numCol)
 +              CustomData_from_bmeshpoly(&ccgdm->dm.faceData, &ccgdm->dm.polyData, &ccgdm->dm.loopData, ccgSubSurf_getNumFinalFaces(ss));
 +
 +      ccgdm->dm.getMinMax = cgdm_getMinMax;
 +      ccgdm->dm.getNumVerts = cgdm_getNumVerts;
 +      ccgdm->dm.getNumEdges = cgdm_getNumEdges;
 +      ccgdm->dm.getNumTessFaces = cgdm_getNumTessFaces;
 +      ccgdm->dm.getNumFaces = cgdm_getNumTessFaces;
  
 -      ccgdm->dm.getMinMax = ccgDM_getMinMax;
 -      ccgdm->dm.getNumVerts = ccgDM_getNumVerts;
 -      ccgdm->dm.getNumFaces = ccgDM_getNumFaces;
 +      ccgdm->dm.getNumGrids = ccgDM_getNumGrids;
 +      ccgdm->dm.getPBVH = ccgDM_getPBVH;
  
 -      ccgdm->dm.getNumEdges = ccgDM_getNumEdges;
        ccgdm->dm.getVert = ccgDM_getFinalVert;
        ccgdm->dm.getEdge = ccgDM_getFinalEdge;
 -      ccgdm->dm.getFace = ccgDM_getFinalFace;
 +      ccgdm->dm.getTessFace = ccgDM_getFinalFace;
        ccgdm->dm.getVertCo = ccgDM_getFinalVertCo;
        ccgdm->dm.getVertNo = ccgDM_getFinalVertNo;
        ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray;
        ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray;
 -      ccgdm->dm.copyFaceArray = ccgDM_copyFinalFaceArray;
 +      ccgdm->dm.copyTessFaceArray = ccgDM_copyFinalFaceArray;
 +      ccgdm->dm.copyLoopArray = ccgDM_copyFinalLoopArray;
 +      ccgdm->dm.copyPolyArray = ccgDM_copyFinalPolyArray;
        ccgdm->dm.getVertData = DM_get_vert_data;
        ccgdm->dm.getEdgeData = DM_get_edge_data;
 -      ccgdm->dm.getFaceData = DM_get_face_data;
 +      ccgdm->dm.getTessFaceData = DM_get_face_data;
        ccgdm->dm.getVertDataArray = ccgDM_get_vert_data_layer;
        ccgdm->dm.getEdgeDataArray = ccgDM_get_edge_data_layer;
 -      ccgdm->dm.getFaceDataArray = ccgDM_get_face_data_layer;
 +      ccgdm->dm.getTessFaceDataArray = ccgDM_get_face_data_layer;
        ccgdm->dm.getNumGrids = ccgDM_getNumGrids;
        ccgdm->dm.getGridSize = ccgDM_getGridSize;
        ccgdm->dm.getGridData = ccgDM_getGridData;
        ccgdm->dm.getFaceMap = ccgDM_getFaceMap;
        ccgdm->dm.getPBVH = ccgDM_getPBVH;
  
 -      ccgdm->dm.getVertCos = ccgdm_getVertCos;
 -      ccgdm->dm.foreachMappedVert = ccgDM_foreachMappedVert;
 -      ccgdm->dm.foreachMappedEdge = ccgDM_foreachMappedEdge;
 -      ccgdm->dm.foreachMappedFaceCenter = ccgDM_foreachMappedFaceCenter;
 +      ccgdm->dm.getTessFace = ccgDM_getFinalFace;
 +      ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray;
 +      ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray;
 +      ccgdm->dm.copyTessFaceArray = ccgDM_copyFinalFaceArray;
 +      ccgdm->dm.getVertData = DM_get_vert_data;
 +      ccgdm->dm.getEdgeData = DM_get_edge_data;
 +      ccgdm->dm.getTessFaceData = DM_get_face_data;
 +
 +      ccgdm->dm.calcNormals = ccgDM_calcNormals;
 +      ccgdm->dm.recalcTesselation = ccgDM_recalcTesselection;
 +
 +      ccgdm->dm.getVertCos = cgdm_getVertCos;
 +      ccgdm->dm.foreachMappedVert = cgdm_foreachMappedVert;
 +      ccgdm->dm.foreachMappedEdge = cgdm_foreachMappedEdge;
 +      ccgdm->dm.foreachMappedFaceCenter = cgdm_foreachMappedFaceCenter;
        
        ccgdm->dm.drawVerts = ccgDM_drawVerts;
        ccgdm->dm.drawEdges = ccgDM_drawEdges;
        ccgdm->dm.drawLooseEdges = ccgDM_drawLooseEdges;
        ccgdm->dm.drawFacesSolid = ccgDM_drawFacesSolid;
 -      ccgdm->dm.drawFacesColored = ccgDM_drawFacesColored;
 -      ccgdm->dm.drawFacesTex = ccgDM_drawFacesTex;
 -      ccgdm->dm.drawFacesGLSL = ccgDM_drawFacesGLSL;
 +      ccgdm->dm.drawFacesColored = cgdm_drawFacesColored;
 +      ccgdm->dm.drawFacesTex = cgdm_drawFacesTex;
 +      ccgdm->dm.drawFacesGLSL = cgdm_drawFacesGLSL;
        ccgdm->dm.drawMappedFaces = ccgDM_drawMappedFaces;
 -      ccgdm->dm.drawMappedFacesTex = ccgDM_drawMappedFacesTex;
 -      ccgdm->dm.drawMappedFacesGLSL = ccgDM_drawMappedFacesGLSL;
 -      ccgdm->dm.drawMappedFacesMat = ccgDM_drawMappedFacesMat;
 -      ccgdm->dm.drawUVEdges = ccgDM_drawUVEdges;
 +      ccgdm->dm.drawMappedFacesTex = cgdm_drawMappedFacesTex;
 +      ccgdm->dm.drawMappedFacesGLSL = cgdm_drawMappedFacesGLSL;
 +      ccgdm->dm.drawMappedFacesMat = cgdm_drawMappedFacesMat;
 +      ccgdm->dm.drawUVEdges = cgdm_drawUVEdges;
  
 -      ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp;
 -      ccgdm->dm.drawMappedEdges = ccgDM_drawMappedEdges;
 -      
 -      ccgdm->dm.release = ccgDM_release;
 +      ccgdm->dm.drawMappedEdgesInterp = cgdm_drawMappedEdgesInterp;
 +      ccgdm->dm.drawMappedEdges = cgdm_drawMappedEdges;
 +
 +      ccgdm->dm.release = cgdm_release;
        
        ccgdm->ss = ss;
        ccgdm->drawInteriorEdges = drawInteriorEdges;
        ccgdm->useSubsurfUv = useSubsurfUv;
  
        totvert = ccgSubSurf_getNumVerts(ss);
 -      ccgdm->vertMap = MEM_mallocN(totvert * sizeof(*ccgdm->vertMap), "vertMap");
 +      ccgdm->vertMap = MEM_callocN(totvert * sizeof(*ccgdm->vertMap), "vertMap");
        vi = ccgSubSurf_getVertIterator(ss);
        for(; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
                CCGVert *v = ccgVertIterator_getCurrent(vi);
        ccgVertIterator_free(vi);
  
        totedge = ccgSubSurf_getNumEdges(ss);
 -      ccgdm->edgeMap = MEM_mallocN(totedge * sizeof(*ccgdm->edgeMap), "edgeMap");
 +      ccgdm->edgeMap = MEM_callocN(totedge * sizeof(*ccgdm->edgeMap), "edgeMap");
        ei = ccgSubSurf_getEdgeIterator(ss);
        for(; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
                CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
        }
  
        totface = ccgSubSurf_getNumFaces(ss);
 -      ccgdm->faceMap = MEM_mallocN(totface * sizeof(*ccgdm->faceMap), "faceMap");
 +      ccgdm->faceMap = MEM_callocN(totface * sizeof(*ccgdm->faceMap), "faceMap");
        fi = ccgSubSurf_getFaceIterator(ss);
        for(; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
                CCGFace *f = ccgFaceIterator_getCurrent(fi);
        }
        ccgFaceIterator_free(fi);
  
 +      ccgdm->reverseFaceMap = MEM_callocN(sizeof(int)*ccgSubSurf_getNumFinalFaces(ss), "reverseFaceMap");
 +
        edgeSize = ccgSubSurf_getEdgeSize(ss);
        gridSize = ccgSubSurf_getGridSize(ss);
        gridFaces = gridSize - 1;
 -      /*gridSideVerts = gridSize - 2;*/ /*UNUSED*/
 -      /*gridInternalVerts = gridSideVerts * gridSideVerts; */ /*UNUSED*/
 +      gridCuts = gridSize - 2;
 +      /*gridInternalVerts = gridSideVerts * gridSideVerts; - as yet, unused */
        gridSideEdges = gridSize - 1;
        gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2; 
  
 -      calc_ss_weights(gridFaces, &qweight, &tweight);
 -
        vertNum = 0;
        edgeNum = 0;
        faceNum = 0;
  
 -      /* mvert = dm->getVertArray(dm); - as yet unused */
 +      /* mvert = dm->getVertArray(dm); */ /* UNUSED */
        medge = dm->getEdgeArray(dm);
 -      mface = dm->getFaceArray(dm);
 +      /* mface = dm->getTessFaceArray(dm); */ /* UNUSED */
  
 +      mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
 +      base_polyOrigIndex = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
 +      
 +      /*CDDM hack*/
 +      edgeFlags = ccgdm->edgeFlags = MEM_callocN(sizeof(short)*totedge, "faceFlags");
        faceFlags = ccgdm->faceFlags = MEM_callocN(sizeof(char)*2*totface, "faceFlags");
  
 -      orig_indices = (int*)ccgdm->dm.getFaceDataArray(&ccgdm->dm, CD_ORIGINDEX);
 -      for(index = 0; index < totface; ++index) {
 +      vertOrigIndex = DM_get_vert_data_layer(&ccgdm->dm, CD_ORIGINDEX);
 +      /*edgeOrigIndex = DM_get_edge_data_layer(&cgdm->dm, CD_ORIGINDEX);*/
 +      faceOrigIndex = DM_get_tessface_data_layer(&ccgdm->dm, CD_ORIGINDEX);
 +
 +      polyOrigIndex = DM_get_face_data_layer(&ccgdm->dm, CD_ORIGINDEX);
 +
 +#if 0
 +      /* this is not in trunk, can gives problems because colors initialize
 +       * as black, just dont do it!, it works fine - campbell */
 +      if (!CustomData_has_layer(&ccgdm->dm.faceData, CD_MCOL))
 +              DM_add_tessface_layer(&ccgdm->dm, CD_MCOL, CD_CALLOC, NULL);
 +      mcol = DM_get_tessface_data_layer(&ccgdm->dm, CD_MCOL);
 +#endif
 +
 +      has_edge_origindex = CustomData_has_layer(&ccgdm->dm.edgeData, CD_ORIGINDEX);
 +
 +      faceNum = 0;
 +      loopindex = loopindex2 = 0; //current loop index
 +      for (index = 0; index < totface; index++) {
                CCGFace *f = ccgdm->faceMap[index].face;
                int numVerts = ccgSubSurf_getFaceNumVerts(f);
                int numFinalEdges = numVerts * (gridSideEdges + gridInternalEdges);
                int origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
 -              FaceVertWeight *weight = (numVerts == 4) ? qweight : tweight;
 -              int S, x, y;
 -              int vertIdx[4];
 +              int g2_wid = gridCuts+2;
 +              float *w2;
 +              int s, x, y;
 +              
 +              origIndex = base_polyOrigIndex ? base_polyOrigIndex[origIndex] : origIndex;
 +              
 +              w = get_ss_weights(&wtable, gridCuts, numVerts);
  
                ccgdm->faceMap[index].startVert = vertNum;
                ccgdm->faceMap[index].startEdge = edgeNum;
                ccgdm->faceMap[index].startFace = faceNum;
 -
 -              if(orig_indices)
 -                      orig_indices[faceNum] = origIndex;
 +              
 +              faceFlags[0] = mpoly ?  mpoly[origIndex].flag : 0;
 +              faceFlags[1] = mpoly ? mpoly[origIndex].mat_nr : 0;
 +              faceFlags += 2;
  
                /* set the face base vert */
                *((int*)ccgSubSurf_getFaceUserData(ss, f)) = vertNum;
  
 -              for(S = 0; S < numVerts; S++) {
 -                      CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
 +              BLI_array_empty(loopidx);               
 +              for (s=0; s<numVerts; s++) {
 +                      BLI_array_growone(loopidx);
 +                      loopidx[s] = loopindex++;
 +              }
 +              
 +              BLI_array_empty(vertidx);
 +                              for(s = 0; s < numVerts; s++) {
 +                      CCGVert *v = ccgSubSurf_getFaceVert(ss, f, s);
 +                      
 +                      BLI_array_growone(vertidx);
 +                      vertidx[s] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
 +              }
 +              
  
 -                      vertIdx[S] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
 +              /*I think this is for interpolating the center vert?*/
 +              w2 = w; // + numVerts*(g2_wid-1)*(g2_wid-1); //numVerts*((g2_wid-1)*g2_wid+g2_wid-1);
 +              DM_interp_vert_data(dm, &ccgdm->dm, vertidx, w2,
 +                                  numVerts, vertNum);
 +              if (vertOrigIndex) {
 +                      *vertOrigIndex = ORIGINDEX_NONE;
 +                      ++vertOrigIndex;
                }
  
 -              DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, weight[0][0],
 -                                                      numVerts, vertNum);
                ++vertNum;
  
 -              for(S = 0; S < numVerts; S++) {
 -                      int prevS = (S - 1 + numVerts) % numVerts;
 -                      int nextS = (S + 1) % numVerts;
 -                      int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
 +              /*interpolate per-vert data*/
 +              for(s = 0; s < numVerts; s++) {
                        for(x = 1; x < gridFaces; x++) {
 -                              float w[4];
 -                              w[prevS]  = weight[x][0][0];
 -                              w[S]      = weight[x][0][1];
 -                              w[nextS]  = weight[x][0][2];
 -                              w[otherS] = weight[x][0][3];
 -                              DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w,
 -                                                                      numVerts, vertNum);
 +                              w2 = w + s*numVerts*g2_wid*g2_wid + x*numVerts;
 +                              DM_interp_vert_data(dm, &ccgdm->dm, vertidx, w2,
 +                                                  numVerts, vertNum);
 +
 +                              if (vertOrigIndex) {
 +                                      *vertOrigIndex = ORIGINDEX_NONE;
 +                                      ++vertOrigIndex;
 +                              }
 +
                                ++vertNum;
                        }
                }
  
 -              for(S = 0; S < numVerts; S++) {
 -                      int prevS = (S - 1 + numVerts) % numVerts;
 -                      int nextS = (S + 1) % numVerts;
 -                      int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
 +              /*interpolate per-vert data*/
 +              for(s = 0; s < numVerts; s++) {
                        for(y = 1; y < gridFaces; y++) {
                                for(x = 1; x < gridFaces; x++) {
 -                                      float w[4];
 -                                      w[prevS]  = weight[y * gridFaces + x][0][0];
 -                                      w[S]      = weight[y * gridFaces + x][0][1];
 -                                      w[nextS]  = weight[y * gridFaces + x][0][2];
 -                                      w[otherS] = weight[y * gridFaces + x][0][3];
 -                                      DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w,
 -                                                                              numVerts, vertNum);
 +                                      w2 = w + s*numVerts*g2_wid*g2_wid + (y*g2_wid+x)*numVerts;
 +                                      DM_interp_vert_data(dm, &ccgdm->dm, vertidx, w2,
 +                                                          numVerts, vertNum);
 +
 +                                      if (vertOrigIndex) {
 +                                              *vertOrigIndex = ORIGINDEX_NONE;
 +                                              ++vertOrigIndex;
 +                                      }
 +
                                        ++vertNum;
                                }
                        }
                }
  
 -              for(S = 0; S < numVerts; S++) {
 -                      int prevS = (S - 1 + numVerts) % numVerts;
 -                      int nextS = (S + 1) % numVerts;
 -                      int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
 -
 -                      weight = (numVerts == 4) ? qweight : tweight;
 -
 -                      for(y = 0; y < gridFaces; y++) {
 -                              for(x = 0; x < gridFaces; x++) {
 -                                      FaceVertWeight w;
 -                                      int j;
 -
 -                                      for(j = 0; j < 4; ++j) {
 -                                              w[j][prevS]  = (*weight)[j][0];
 -                                              w[j][S]      = (*weight)[j][1];
 -                                              w[j][nextS]  = (*weight)[j][2];
 -                                              w[j][otherS] = (*weight)[j][3];
 +              if (has_edge_origindex) {
 +                      for(i = 0; i < numFinalEdges; ++i)
 +                              *(int *)DM_get_edge_data(&ccgdm->dm, edgeNum + i,
 +                                                       CD_ORIGINDEX) = ORIGINDEX_NONE;
 +              }
 +
 +              for (s=0; s<numVerts; s++) {
 +                      /*interpolate per-face data*/
 +                      for (y=0; y<gridFaces; y++) {
 +                              for (x=0; x<gridFaces; x++) {
 +                                      w2 = w + s*numVerts*g2_wid*g2_wid + (y*g2_wid+x)*numVerts;
 +                                      CustomData_interp(&dm->loopData, &ccgdm->dm.loopData,
 +                                                        loopidx, w2, NULL, numVerts, loopindex2);
 +                                      loopindex2++;
 +
 +                                      w2 = w + s*numVerts*g2_wid*g2_wid + ((y+1)*g2_wid+(x))*numVerts;
 +                                      CustomData_interp(&dm->loopData, &ccgdm->dm.loopData,
 +                                                        loopidx, w2, NULL, numVerts, loopindex2);
 +                                      loopindex2++;
 +
 +                                      w2 = w + s*numVerts*g2_wid*g2_wid + ((y+1)*g2_wid+(x+1))*numVerts;
 +                                      CustomData_interp(&dm->loopData, &ccgdm->dm.loopData,
 +                                                        loopidx, w2, NULL, numVerts, loopindex2);
 +                                      loopindex2++;
 +                                      
 +                                      w2 = w + s*numVerts*g2_wid*g2_wid + ((y)*g2_wid+(x+1))*numVerts;
 +                                      CustomData_interp(&dm->loopData, &ccgdm->dm.loopData,
 +                                                        loopidx, w2, NULL, numVerts, loopindex2);
 +                                      loopindex2++;
 +
 +                                      /*copy over poly data, e.g. mtexpoly*/
 +                                      CustomData_copy_data(&dm->polyData, &ccgdm->dm.polyData, origIndex, faceNum, 1);
 +
 +                                      /*generate tesselated face data used for drawing*/
 +                                      ccg_loops_to_corners(&ccgdm->dm.faceData, &ccgdm->dm.loopData,
 +                                              &ccgdm->dm.polyData, loopindex2-4, faceNum, faceNum, numTex, numCol);
 +                                      
 +                                      /*set original index data*/
 +                                      if (faceOrigIndex) {
 +                                              *faceOrigIndex = origIndex;
 +                                              faceOrigIndex++;
 +                                      }
 +                                      if (polyOrigIndex) {
 +                                              *polyOrigIndex = origIndex;
 +                                              polyOrigIndex++;
                                        }
  
 -                                      DM_interp_face_data(dm, &ccgdm->dm, &origIndex, NULL,
 -                                                                              &w, 1, faceNum);
 -                                      weight++;
 +                                      ccgdm->reverseFaceMap[faceNum] = index;
  
 -                                      ++faceNum;
 +                                      faceNum++;
                                }
                        }
                }
  
 -              faceFlags[index*2] = mface[origIndex].flag;
 -              faceFlags[index*2 + 1] = mface[origIndex].mat_nr;
 -
                edgeNum += numFinalEdges;
        }
  
 -      if(useSubsurfUv) {
 -              CustomData *fdata = &ccgdm->dm.faceData;
 -              CustomData *dmfdata = &dm->faceData;
 -              int numlayer = CustomData_number_of_layers(fdata, CD_MTFACE);
 -              int dmnumlayer = CustomData_number_of_layers(dmfdata, CD_MTFACE);
 -
 -              for (i=0; i<numlayer && i<dmnumlayer; i++)
 -                      set_subsurf_uv(ss, dm, &ccgdm->dm, i);
 -      }
 -
 -      edgeFlags = ccgdm->edgeFlags = MEM_callocN(sizeof(short)*totedge, "edgeFlags");
 -
        for(index = 0; index < totedge; ++index) {
                CCGEdge *e = ccgdm->edgeMap[index].edge;
                int numFinalEdges = edgeSize - 1;
 +              int mapIndex = ccgDM_getEdgeMapIndex(ss, e);
                int x;
                int vertIdx[2];
                int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e));
                ccgdm->edgeMap[index].startVert = vertNum;
                ccgdm->edgeMap[index].startEdge = edgeNum;
  
 +              if(edgeIdx >= 0 && edgeFlags)
 +                      edgeFlags[edgeIdx] = medge[edgeIdx].flag;
 +
                /* set the edge base vert */
                *((int*)ccgSubSurf_getEdgeUserData(ss, e)) = vertNum;
  
                        w[1] = (float) x / (edgeSize - 1);
                        w[0] = 1 - w[1];
                        DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w, 2, vertNum);
 +                      if (vertOrigIndex) {
 +                              *vertOrigIndex = ORIGINDEX_NONE;
 +                              ++vertOrigIndex;
 +                      }
                        ++vertNum;
                }
  
 -              edgeFlags[index]= medge[edgeIdx].flag;
 +              for(i = 0; i < numFinalEdges; ++i) {
 +                      if (has_edge_origindex) {
 +                              *(int *)DM_get_edge_data(&ccgdm->dm, edgeNum + i,
 +                                               CD_ORIGINDEX) = mapIndex;
 +                      }
 +              }
  
                edgeNum += numFinalEdges;
        }
  
 +      if(useSubsurfUv) {
 +              CustomData *ldata = &ccgdm->dm.loopData;
 +              CustomData *dmldata = &dm->loopData;
 +              int numlayer = CustomData_number_of_layers(ldata, CD_MLOOPUV);
 +              int dmnumlayer = CustomData_number_of_layers(dmldata, CD_MLOOPUV);
 +
 +              for (i=0; i<numlayer && i<dmnumlayer; i++)
 +                      set_subsurf_uv(ss, dm, &ccgdm->dm, i);
 +      }
 +
        for(index = 0; index < totvert; ++index) {
                CCGVert *v = ccgdm->vertMap[index].vert;
 -              int vertIdx;
 +              int mapIndex = ccgDM_getVertMapIndex(ccgdm->ss, v);
 +              int vidx;
  
 -              vertIdx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
 +              vidx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
  
                ccgdm->vertMap[index].startVert = vertNum;
  
                /* set the vert base vert */
                *((int*) ccgSubSurf_getVertUserData(ss, v)) = vertNum;
  
 -              DM_copy_vert_data(dm, &ccgdm->dm, vertIdx, vertNum, 1);
 +              DM_copy_vert_data(dm, &ccgdm->dm, vidx, vertNum, 1);
  
 +              if (vertOrigIndex) {
 +                      *vertOrigIndex = mapIndex;
 +                      ++vertOrigIndex;
 +              }
                ++vertNum;
        }
  
 -      MEM_freeN(qweight);
 -      MEM_freeN(tweight);
 +      ccgdm->dm.numVertData = vertNum;
 +      ccgdm->dm.numEdgeData = edgeNum;
 +      ccgdm->dm.numFaceData = faceNum;
 +      ccgdm->dm.numLoopData = loopindex2;
 +      ccgdm->dm.numPolyData = faceNum;
 +
 +      BLI_array_free(vertidx);
 +      BLI_array_free(loopidx);
 +      free_ss_weights(&wtable);
  
        return ccgdm;
  }
@@@ -3201,7 -2763,7 +3194,7 @@@ struct DerivedMesh *subsurf_make_derive
        int useAging = smd->flags & eSubsurfModifierFlag_DebugIncr;
        int useSubsurfUv = smd->flags & eSubsurfModifierFlag_SubsurfUv;
        int drawInteriorEdges = !(smd->flags & eSubsurfModifierFlag_ControlEdges);
 -      CCGDerivedMesh *result;
 +      CCGDerivedMesh *result = NULL;
  
        if(forEditMode) {
                int levels= (smd->modifier.scene)? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels): smd->levels;
  
                result->freeSS = 1;
        } else {
 -              int useIncremental = (smd->flags & eSubsurfModifierFlag_Incremental);
 +              int useIncremental = 1; //(smd->flags & eSubsurfModifierFlag_Incremental);
                int useAging = smd->flags & eSubsurfModifierFlag_DebugIncr;
                int levels= (smd->modifier.scene)? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels): smd->levels;
                CCGSubSurf *ss;
                        smd->mCache = ss = _getSubSurf(smd->mCache, levels,
                                                                                   useAging, 0, useSimple);
  
 -                      ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
 +                      if (!ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple)) {
 +                              //ccgSubSurf_free(smd->mCache);
 +                              smd->mCache = ss = _getSubSurf(NULL, levels,
 +                                                                                         useAging, 0, useSimple);
 +                              
 +                              ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
 +      
 +                      }
  
                        result = getCCGDerivedMesh(smd->mCache,
                                                                           drawInteriorEdges,
@@@ -35,7 -35,6 +35,7 @@@
  #include <ctype.h>
  #include <string.h>
  #include <stdlib.h>
 +#include <stddef.h>
  #include <assert.h>
  
  #include "MEM_guardedalloc.h"
@@@ -45,6 -44,7 +45,7 @@@
  #include "BLI_fileops.h"
  #include "BLI_path_util.h"
  #include "BLI_string.h"
+ #include "BLI_string_utf8.h"
  #include "BLI_utildefines.h"
  
  #include "BKE_utildefines.h"
@@@ -221,16 -221,25 +222,25 @@@ int BLI_uniquename_cb(int (*unique_chec
        }
  
        if(unique_check(arg, name)) {
+               char    numstr[16];
                char    tempname[UNIQUE_NAME_MAX];
                char    left[UNIQUE_NAME_MAX];
                int             number;
                int             len= BLI_split_name_num(left, &number, name, delim);
                do {
-                       int newlen= BLI_snprintf(tempname, name_len, "%s%c%03d", left, delim, ++number);
-                       if(newlen >= name_len) {
-                               len -= ((newlen + 1) - name_len);
-                               if(len < 0) len= number= 0;
-                               left[len]= '\0';
+                       int numlen= BLI_snprintf(numstr, sizeof(numstr), "%c%03d", delim, ++number);
+                       /* highly unlikely the string only has enough room for the number
+                        * but support anyway */
+                       if ((len == 0) || (numlen >= name_len)) {
+                               /* number is know not to be utf-8 */
+                               BLI_strncpy(tempname, numstr, name_len);
+                       }
+                       else {
+                               char *tempname_buf;
+                               tempname[0]= '\0';
+                               tempname_buf =BLI_strncat_utf8(tempname, left, name_len - numlen);
+                               memcpy(tempname_buf, numstr, numlen + 1);
                        }
                } while(unique_check(arg, tempname));
  
@@@ -308,7 -317,7 +318,7 @@@ void BLI_uniquename(ListBase *list, voi
  
  void BLI_cleanup_path(const char *relabase, char *dir)
  {
 -      short a;
 +      ptrdiff_t a;
        char *start, *eind;
        if (relabase) {
                BLI_path_abs(dir, relabase);
  
  #include "MEM_guardedalloc.h"
  
 +#include "BLI_utildefines.h"
  #include "BLI_blenlib.h"
  #include "BLI_math.h"
 -#include "BLI_utildefines.h"
 +#include "BLI_cellalloc.h"
 +#include "BLI_edgehash.h"
  
  #include "BKE_anim.h"
  #include "BKE_action.h"
@@@ -2673,16 -2671,6 +2673,16 @@@ static void lib_link_key(FileData *fd, 
  
        key= main->key.first;
        while(key) {
 +              /*check if we need to generate unique ids for the shapekeys*/
 +              if (!key->uidgen) {
 +                      KeyBlock *block;
 +
 +                      key->uidgen = 1;
 +                      for (block=key->block.first; block; block=block->next) {
 +                              block->uid = key->uidgen++;
 +                      }
 +              }
 +
                if(key->id.flag & LIB_NEEDLINK) {
                        if(key->adt) lib_link_animdata(fd, &key->id, key->adt);
                        
@@@ -3605,26 -3593,6 +3605,26 @@@ static void lib_link_customdata_mtface(
  
  }
  
 +static void lib_link_customdata_mtpoly(FileData *fd, Mesh *me, CustomData *pdata, int totface)
 +{
 +      int i;
 +
 +      for(i=0; i<pdata->totlayer; i++) {
 +              CustomDataLayer *layer = &pdata->layers[i];
 +              
 +              if(layer->type == CD_MTEXPOLY) {
 +                      MTexPoly *tf= layer->data;
 +                      int i;
 +
 +                      for (i=0; i<totface; i++, tf++) {
 +                              tf->tpage= newlibadr(fd, me->id.lib, tf->tpage);
 +                              if(tf->tpage && tf->tpage->id.us==0)
 +                                      tf->tpage->id.us= 1;
 +                      }
 +              }
 +      }
 +}
 +
  static void lib_link_mesh(FileData *fd, Main *main)
  {
        Mesh *me;
                        me->texcomesh= newlibadr_us(fd, me->id.lib, me->texcomesh);
  
                        lib_link_customdata_mtface(fd, me, &me->fdata, me->totface);
 +                      lib_link_customdata_mtpoly(fd, me, &me->pdata, me->totpoly);
                        if(me->mr && me->mr->levels.first)
                                lib_link_customdata_mtface(fd, me, &me->mr->fdata,
                                                           ((MultiresLevel*)me->mr->levels.first)->totface);
  
 +                      /*check if we need to convert mfaces to mpolys*/
 +                      if (me->totface && !me->totpoly) {
 +                              convert_mfaces_to_mpolys(me);
 +                      }
 +                      
 +                      /*
 +                       * Re-tesselate, even if the polys were just created from tessfaces, this
 +                       * is important because it:
 +                       *  - fill the CD_POLYINDEX layer
 +                       *  - gives consistency of tessface between loading from a file and
 +                       *    converting an edited BMesh back into a mesh (i.e. it replaces
 +                       *    quad tessfaces in a loaded mesh immediately, instead of lazily
 +                       *    waiting until edit mode has been entered/exited, making it easier
 +                       *    to recognize problems that would otherwise only show up after edits).
 +                       */
 +                      me->totface = mesh_recalcTesselation(
 +                              &me->fdata, &me->ldata, &me->pdata,
 +                              me->mvert, me->totface, me->totloop, me->totpoly);
 +
 +                      mesh_update_customdata_pointers(me);
 +
                        me->id.flag -= LIB_NEEDLINK;
                }
                me= me->id.next;
@@@ -3696,17 -3642,10 +3696,17 @@@ static void direct_link_dverts(FileDat
        }
  
        for (i= count; i > 0; i--, mdverts++) {
 -              if(mdverts->dw) {
 -                      mdverts->dw= newdataadr(fd, mdverts->dw);
 +              /*convert to vgroup allocation system*/
 +              MDeformWeight *dw;
 +              if(mdverts->dw && (dw= newdataadr(fd, mdverts->dw))) {
 +                      const ssize_t dw_len= mdverts->totweight * sizeof(MDeformWeight);
 +                      void *dw_tmp= BLI_cellalloc_malloc(dw_len, "direct_link_dverts");
 +                      memcpy(dw_tmp, dw, dw_len);
 +                      mdverts->dw= dw_tmp;
 +                      MEM_freeN(dw);
                }
 -              if (mdverts->dw == NULL) {
 +              else {
 +                      mdverts->dw= NULL;
                        mdverts->totweight= 0;
                }
        }
@@@ -3719,18 -3658,7 +3719,18 @@@ static void direct_link_mdisps(FileDat
  
                for(i = 0; i < count; ++i) {
                        mdisps[i].disps = newdataadr(fd, mdisps[i].disps);
 -
 +                      
 +                      /*put .disps into cellalloc system*/
 +                      if (mdisps[i].disps) {
 +                              float *disp2;
 +                              
 +                              disp2 = BLI_cellalloc_malloc(MEM_allocN_len(mdisps[i].disps), "cellalloc .disps copy");
 +                              memcpy(disp2, mdisps[i].disps, MEM_allocN_len(mdisps[i].disps));
 +                              
 +                              MEM_freeN(mdisps[i].disps);
 +                              mdisps[i].disps = (float (*)[3])disp2;
 +                      }
 +                      
                        if( (fd->flags & FD_FLAGS_SWITCH_ENDIAN) && (mdisps[i].disps) ) {
                                /* DNA_struct_switch_endian doesn't do endian swap for (*disps)[] */
                                /* this does swap for data written at write_mdisps() - readfile.c */
        }
  }
  
 +/*this isn't really a public api function, so prototyped here*/
  static void direct_link_customdata(FileData *fd, CustomData *data, int count)
  {
        int i = 0;
                        i++;
                }
        }
 +
 +      CustomData_update_typemap(data);
  }
  
  static void direct_link_mesh(FileData *fd, Mesh *mesh)
        mesh->mvert= newdataadr(fd, mesh->mvert);
        mesh->medge= newdataadr(fd, mesh->medge);
        mesh->mface= newdataadr(fd, mesh->mface);
 +      mesh->mloop= newdataadr(fd, mesh->mloop);
 +      mesh->mpoly= newdataadr(fd, mesh->mpoly);
        mesh->tface= newdataadr(fd, mesh->tface);
        mesh->mtface= newdataadr(fd, mesh->mtface);
        mesh->mcol= newdataadr(fd, mesh->mcol);
        mesh->msticky= newdataadr(fd, mesh->msticky);
        mesh->dvert= newdataadr(fd, mesh->dvert);
 -      
 +      mesh->mloopcol= newdataadr(fd, mesh->mloopcol);
 +      mesh->mloopuv= newdataadr(fd, mesh->mloopuv);
 +      mesh->mtpoly= newdataadr(fd, mesh->mtpoly);
 +
        /* animdata */
        mesh->adt= newdataadr(fd, mesh->adt);
        direct_link_animdata(fd, mesh->adt);
        direct_link_customdata(fd, &mesh->vdata, mesh->pv ? mesh->pv->totvert : mesh->totvert);
        direct_link_customdata(fd, &mesh->edata, mesh->pv ? mesh->pv->totedge : mesh->totedge);
        direct_link_customdata(fd, &mesh->fdata, mesh->pv ? mesh->pv->totface : mesh->totface);
 -
 +      direct_link_customdata(fd, &mesh->ldata, mesh->totloop);
 +      direct_link_customdata(fd, &mesh->pdata, mesh->totpoly);
 +      
        mesh->bb= NULL;
        mesh->mselect = NULL;
 -      mesh->edit_mesh= NULL;
 +      mesh->edit_btmesh= NULL;
        
        /* Multires data */
        mesh->mr= newdataadr(fd, mesh->mr);
@@@ -7430,6 -7348,67 +7430,67 @@@ static void do_versions_nodetree_conver
        }
  }
  
+ void do_versions_image_settings_2_60(Scene *sce)
+ {
+       /* note: rd->subimtype is moved into indervidual settings now and no longer
+        * exists */
+       RenderData *rd= &sce->r;
+       ImageFormatData *imf= &sce->r.im_format;
+       imf->imtype= rd->imtype;
+       imf->planes= rd->planes;
+       imf->compress= rd->quality;
+       imf->quality= rd->quality;
+       /* default, was stored in multiple places, may override later */
+       imf->depth= R_IMF_CHAN_DEPTH_8;
+       /* openexr */
+       imf->exr_codec = rd->quality & 7; /* strange but true! 0-4 are valid values, OPENEXR_COMPRESS */
+       switch (imf->imtype) {
+       case R_IMF_IMTYPE_OPENEXR:
+               imf->depth=  (rd->subimtype & R_OPENEXR_HALF) ? R_IMF_CHAN_DEPTH_16 : R_IMF_CHAN_DEPTH_32;
+               if (rd->subimtype & R_PREVIEW_JPG) {
+                       imf->flag |= R_IMF_FLAG_PREVIEW_JPG;
+               }
+               if (rd->subimtype & R_OPENEXR_ZBUF) {
+                       imf->flag |= R_IMF_FLAG_ZBUF;
+               }
+               break;
+       case R_IMF_IMTYPE_TIFF:
+               if (rd->subimtype & R_TIFF_16BIT) {
+                       imf->depth= R_IMF_CHAN_DEPTH_16;
+               }
+               break;
+       case R_IMF_IMTYPE_JP2:
+               if (rd->subimtype & R_JPEG2K_16BIT) {
+                       imf->depth= R_IMF_CHAN_DEPTH_16;
+               }
+               else if (rd->subimtype & R_JPEG2K_12BIT) {
+                       imf->depth= R_IMF_CHAN_DEPTH_12;
+               }
+               if (rd->subimtype & R_JPEG2K_YCC) {
+                       imf->jp2_flag |= R_IMF_JP2_FLAG_YCC;
+               }
+               if (rd->subimtype & R_JPEG2K_CINE_PRESET) {
+                       imf->jp2_flag |= R_IMF_JP2_FLAG_CINE_PRESET;
+               }
+               if (rd->subimtype & R_JPEG2K_CINE_48FPS) {
+                       imf->jp2_flag |= R_IMF_JP2_FLAG_CINE_48;
+               }
+               break;
+       case R_IMF_IMTYPE_CINEON:
+       case R_IMF_IMTYPE_DPX:
+               if (rd->subimtype & R_CINEON_LOG) {
+                       imf->cineon_flag |= R_IMF_CINEON_FLAG_LOG;
+               }
+               break;
+       }
+ }
  static void do_versions(FileData *fd, Library *lib, Main *main)
  {
        /* WATCH IT!!!: pointers from libdata have not been converted */
                Mesh *me;
  
                for(me= main->mesh.first; me; me= me->id.next)
 -                      mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
 +                      mesh_calc_tessface_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
        }
  
        if (main->versionfile < 256 || (main->versionfile == 256 && main->subversionfile < 2)){
  
        /* put compatibility code here until next subversion bump */
        {
+               Scene *sce;
+               for(sce = main->scene.first; sce; sce = sce->id.next) {
+                       if (sce->r.im_format.depth == 0) {
+                               do_versions_image_settings_2_60(sce);
+                       }
+               }
        }
  
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
@@@ -13,7 -13,7 +13,7 @@@
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software Foundation,
 - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 + * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   *
   * The Original Code is Copyright (C) 2007 Blender Foundation.
   * All rights reserved.
@@@ -30,8 -30,6 +30,8 @@@
  
  
  #include <float.h>
 +#define _USE_MATH_DEFINES
 +#include <math.h>
  #include <string.h>
  #include <ctype.h>
  #include <stdio.h>
@@@ -41,6 -39,7 +41,6 @@@
  #include "DNA_screen_types.h"
  #include "DNA_scene_types.h"
  #include "DNA_userdef_types.h"
 -#include "DNA_windowmanager_types.h"
  
  #include "MEM_guardedalloc.h"
  
@@@ -49,7 -48,7 +49,7 @@@
  #include "BLI_blenlib.h"
  #include "BLI_dynstr.h" /*for WM_operator_pystring */
  #include "BLI_editVert.h"
 -#include "BLI_math.h"
 +#include "BLI_array.h"
  #include "BLI_utildefines.h"
  
  #include "BKE_blender.h"
@@@ -60,8 -59,6 +60,8 @@@
  #include "BKE_report.h"
  #include "BKE_scene.h"
  #include "BKE_array_mallocn.h"
 +#include "BKE_tessmesh.h"
 +#include "BKE_depsgraph.h"
  
  #include "BIF_gl.h"
  #include "BIF_glutil.h" /* for paint cursor */
@@@ -72,6 -69,7 +72,7 @@@
  #include "ED_space_api.h"
  #include "ED_view3d.h"
  #include "ED_mesh.h"
+ #include "ED_numinput.h"
  
  #include "RNA_access.h"
  #include "RNA_define.h"
@@@ -96,8 -94,9 +97,9 @@@ typedef struct tringselOpData 
        ViewContext vc;
  
        Object *ob;
 -      EditMesh *em;
 -      EditEdge *eed;
 +      BMEditMesh *em;
 +      BMEdge *eed;
+       NumInput num;
  
        int extend;
        int do_cut;
@@@ -131,62 -130,17 +133,62 @@@ static void ringsel_draw(const bContex
        }
  }
  
 +/*given two opposite edges in a face, finds the ordering of their vertices so
 +  that cut preview lines won't cross each other*/
 +static void edgering_find_order(BMEditMesh *em, BMEdge *lasteed, BMEdge *eed, 
 +                                BMVert *lastv1, BMVert *v[2][2])
 +{
 +      BMIter liter;
 +      BMLoop *l, *l2;
 +      int rev;
 +
 +      l = eed->l;
 +
 +      /*find correct order for v[1]*/
 +      if (!(BM_Edge_In_Face(l->f, eed) && BM_Edge_In_Face(l->f, lasteed))) {
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_LOOP, l) {
 +                      if (BM_Edge_In_Face(l->f, eed) && BM_Edge_In_Face(l->f, lasteed))
 +                              break;
 +              }
 +      }
 +      
 +      /*this should never happen*/
 +      if (!l) {
 +              v[0][0] = eed->v1;
 +              v[0][1] = eed->v2;
 +              v[1][0] = lasteed->v1;
 +              v[1][1] = lasteed->v2;
 +              return;
 +      }
 +      
 +      l2 = BM_OtherFaceLoop(l->e, l->f, eed->v1);
 +      rev = (l2 == l->prev);
 +      while (l2->v != lasteed->v1 && l2->v != lasteed->v2) {
 +              l2 = rev ? l2->prev : l2->next;
 +      }
 +
 +      if (l2->v == lastv1) {
 +              v[0][0] = eed->v1;
 +              v[0][1] = eed->v2;
 +      } else {
 +              v[0][0] = eed->v2;
 +              v[0][1] = eed->v1;
 +      }
 +}
 +
  static void edgering_sel(tringselOpData *lcd, int previewlines, int select)
  {
 -      EditMesh *em = lcd->em;
 -      EditEdge *startedge = lcd->eed;
 -      EditEdge *eed;
 -      EditFace *efa;
 -      EditVert *v[2][2];
 +      BMEditMesh *em = lcd->em;
 +      BMEdge *startedge = lcd->eed;
 +      BMEdge *eed, *lasteed;
 +      BMVert *v[2][2], *lastv1;
 +      BMWalker walker;
        float (*edges)[2][3] = NULL;
 -      V_DYNDECLARE(edges);
 +      BLI_array_declare(edges);
        float co[2][3];
 -      int looking=1, i, tot=0;
 +      int i, tot=0;
 +      
 +      memset(v, 0, sizeof(v));
        
        if (!startedge)
                return;
        }
  
        if (!lcd->extend) {
 -              EM_clear_flag_all(lcd->em, SELECT);
 +              EDBM_clear_flag_all(lcd->em, BM_SELECT);
        }
  
 -      /* in eed->f1 we put the valence (amount of faces in edge) */
 -      /* in eed->f2 we put tagged flag as correct loop */
 -      /* in efa->f1 we put tagged flag as correct to select */
 +      if (select) {
 +              BMW_Init(&walker, em->bm, BMW_EDGERING, 0, 0);
 +              eed = BMW_Begin(&walker, startedge);
 +              for (; eed; eed=BMW_Step(&walker)) {
 +                      BM_Select(em->bm, eed, 1);
 +              }
 +              BMW_End(&walker);
  
 -      for(eed= em->edges.first; eed; eed= eed->next) {
 -              eed->f1= 0;
 -              eed->f2= 0;
 +              return;
        }
  
 -      for(efa= em->faces.first; efa; efa= efa->next) {
 -              efa->f1= 0;
 -              if(efa->h==0) {
 -                      efa->e1->f1++;
 -                      efa->e2->f1++;
 -                      efa->e3->f1++;
 -                      if(efa->e4) efa->e4->f1++;
 -              }
 -      }
 -      
 -      // tag startedge OK
 -      startedge->f2= 1;
 -      
 -      while(looking) {
 -              looking= 0;
 -              
 -              for(efa= em->faces.first; efa; efa= efa->next) {
 -                      if(efa->e4 && efa->f1==0 && efa->h == 0) {      // not done quad
 -                              if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { // valence ok
 -
 -                                      // if edge tagged, select opposing edge and mark face ok
 -                                      if(efa->e1->f2) {
 -                                              efa->e3->f2= 1;
 -                                              efa->f1= 1;
 -                                              looking= 1;
 -                                      }
 -                                      else if(efa->e2->f2) {
 -                                              efa->e4->f2= 1;
 -                                              efa->f1= 1;
 -                                              looking= 1;
 -                                      }
 -                                      if(efa->e3->f2) {
 -                                              efa->e1->f2= 1;
 -                                              efa->f1= 1;
 -                                              looking= 1;
 -                                      }
 -                                      if(efa->e4->f2) {
 -                                              efa->e2->f2= 1;
 -                                              efa->f1= 1;
 -                                              looking= 1;
 -                                      }
 -                              }
 +      BMW_Init(&walker, em->bm, BMW_EDGERING, 0, 0);
 +      eed = startedge = BMW_Begin(&walker, startedge);
 +      lastv1 = NULL;
 +      for (lasteed=NULL; eed; eed=BMW_Step(&walker)) {
 +              if (lasteed) {
 +                      if (lastv1) {
 +                              v[1][0] = v[0][0];
 +                              v[1][1] = v[0][1];
 +                      } else {
 +                              v[1][0] = lasteed->v1;
 +                              v[1][1] = lasteed->v2;
 +                              lastv1 = lasteed->v1;
 +                      }
 +
 +                      edgering_find_order(em, lasteed, eed, lastv1, v);
 +                      lastv1 = v[0][0];
 +
 +                      for(i=1;i<=previewlines;i++){
 +                              co[0][0] = (v[0][1]->co[0] - v[0][0]->co[0])*(i/((float)previewlines+1))+v[0][0]->co[0];
 +                              co[0][1] = (v[0][1]->co[1] - v[0][0]->co[1])*(i/((float)previewlines+1))+v[0][0]->co[1];
 +                              co[0][2] = (v[0][1]->co[2] - v[0][0]->co[2])*(i/((float)previewlines+1))+v[0][0]->co[2];
 +
 +                              co[1][0] = (v[1][1]->co[0] - v[1][0]->co[0])*(i/((float)previewlines+1))+v[1][0]->co[0];
 +                              co[1][1] = (v[1][1]->co[1] - v[1][0]->co[1])*(i/((float)previewlines+1))+v[1][0]->co[1];
 +                              co[1][2] = (v[1][1]->co[2] - v[1][0]->co[2])*(i/((float)previewlines+1))+v[1][0]->co[2];                                        
 +                              
 +                              BLI_array_growone(edges);
 +                              VECCOPY(edges[tot][0], co[0]);
 +                              VECCOPY(edges[tot][1], co[1]);
 +                              tot++;
                        }
                }
 +              lasteed = eed;
        }
        
 -      if(previewlines > 0 && !select){
 -                      for(efa= em->faces.first; efa; efa= efa->next) {
 -                              if(efa->v4 == NULL) {  continue; }
 -                              if(efa->h == 0){
 -                                      if(efa->e1->f2 == 1){
 -                                              if(efa->e1->h == 1 || efa->e3->h == 1 )
 -                                                      continue;
 -                                              
 -                                              v[0][0] = efa->v1;
 -                                              v[0][1] = efa->v2;
 -                                              v[1][0] = efa->v4;
 -                                              v[1][1] = efa->v3;
 -                                      } else if(efa->e2->f2 == 1){
 -                                              if(efa->e2->h == 1 || efa->e4->h == 1)
 -                                                      continue;
 -                                              v[0][0] = efa->v2;
 -                                              v[0][1] = efa->v3;
 -                                              v[1][0] = efa->v1;
 -                                              v[1][1] = efa->v4;                                      
 -                                      } else { continue; }
 -                                                                                
 -                                      for(i=1;i<=previewlines;i++){
 -                                              co[0][0] = (v[0][1]->co[0] - v[0][0]->co[0])*(i/((float)previewlines+1))+v[0][0]->co[0];
 -                                              co[0][1] = (v[0][1]->co[1] - v[0][0]->co[1])*(i/((float)previewlines+1))+v[0][0]->co[1];
 -                                              co[0][2] = (v[0][1]->co[2] - v[0][0]->co[2])*(i/((float)previewlines+1))+v[0][0]->co[2];
 -
 -                                              co[1][0] = (v[1][1]->co[0] - v[1][0]->co[0])*(i/((float)previewlines+1))+v[1][0]->co[0];
 -                                              co[1][1] = (v[1][1]->co[1] - v[1][0]->co[1])*(i/((float)previewlines+1))+v[1][0]->co[1];
 -                                              co[1][2] = (v[1][1]->co[2] - v[1][0]->co[2])*(i/((float)previewlines+1))+v[1][0]->co[2];                                        
 -                                              
 -                                              V_GROW(edges);
 -                                              VECCOPY(edges[tot][0], co[0]);
 -                                              VECCOPY(edges[tot][1], co[1]);
 -                                              tot++;
 -                                      }
 -                              }
 -                      }
 -      } else {
 -              select = (startedge->f & SELECT) == 0;
 +      if (lasteed != startedge && BM_Edge_Share_Faces(lasteed, startedge)) {
 +              v[1][0] = v[0][0];
 +              v[1][1] = v[0][1];
 +
 +              edgering_find_order(em, lasteed, startedge, lastv1, v);
 +              
 +              for(i=1;i<=previewlines;i++){
 +                      if (!v[0][0] || !v[0][1] || !v[1][0] || !v[1][1])
 +                              continue;
 +                      
 +                      co[0][0] = (v[0][1]->co[0] - v[0][0]->co[0])*(i/((float)previewlines+1))+v[0][0]->co[0];
 +                      co[0][1] = (v[0][1]->co[1] - v[0][0]->co[1])*(i/((float)previewlines+1))+v[0][0]->co[1];
 +                      co[0][2] = (v[0][1]->co[2] - v[0][0]->co[2])*(i/((float)previewlines+1))+v[0][0]->co[2];
  
 -              /* select the edges */
 -              for(eed= em->edges.first; eed; eed= eed->next) {
 -                      if(eed->f2) EM_select_edge(eed, select);
 +                      co[1][0] = (v[1][1]->co[0] - v[1][0]->co[0])*(i/((float)previewlines+1))+v[1][0]->co[0];
 +                      co[1][1] = (v[1][1]->co[1] - v[1][0]->co[1])*(i/((float)previewlines+1))+v[1][0]->co[1];
 +                      co[1][2] = (v[1][1]->co[2] - v[1][0]->co[2])*(i/((float)previewlines+1))+v[1][0]->co[2];                                        
 +                      
 +                      BLI_array_growone(edges);
 +                      VECCOPY(edges[tot][0], co[0]);
 +                      VECCOPY(edges[tot][1], co[1]);
 +                      tot++;
                }
        }
  
 +      BMW_End(&walker);
        lcd->edges = edges;
        lcd->totedge = tot;
  }
@@@ -282,8 -265,7 +284,8 @@@ static void ringsel_find_edge(tringselO
        if (lcd->eed) {
                edgering_sel(lcd, cuts, 0);
        } else if(lcd->edges) {
 -              MEM_freeN(lcd->edges);
 +              if (lcd->edges)
 +                      MEM_freeN(lcd->edges);
                lcd->edges = NULL;
                lcd->totedge = 0;
        }
  static void ringsel_finish(bContext *C, wmOperator *op)
  {
        tringselOpData *lcd= op->customdata;
 -      int cuts= (lcd->do_cut)? RNA_int_get(op->ptr,"number_cuts"): 0;
 +      int cuts= RNA_int_get(op->ptr, "number_cuts");
  
        if (lcd->eed) {
 -              EditMesh *em = BKE_mesh_get_editmesh(lcd->ob->data);
 -              
 +              BMEditMesh *em = lcd->em;
 +
                edgering_sel(lcd, cuts, 1);
                
                if (lcd->do_cut) {
 -
 -                      esubdivideflag(lcd->ob, em, SELECT, 0.0f, 0.0f, 0, cuts, 0, SUBDIV_SELECT_LOOPCUT);
 -
 +                      BM_esubdivideflag(lcd->ob, em->bm, BM_SELECT, 0.0f, 
 +                                        0.0f, 0, cuts, SUBDIV_SELECT_LOOPCUT, 
 +                                        SUBD_PATH, 0, 0, 0);
 +                      
                        /* force edge slide to edge select mode in in face select mode */
                        if (em->selectmode & SCE_SELECT_FACE) {
                                if (em->selectmode == SCE_SELECT_FACE)
                                else
                                        em->selectmode &= ~SCE_SELECT_FACE;
                                CTX_data_tool_settings(C)->selectmode= em->selectmode;
 -                              EM_selectmode_set(em);
 +                              EDBM_selectmode_set(em);
 +
 +                              WM_event_add_notifier(C, NC_SCENE|ND_TOOLSETTINGS, CTX_data_scene(C));
  
                                WM_event_add_notifier(C, NC_SCENE|ND_TOOLSETTINGS, CTX_data_scene(C));
                        }
 -                      
 +
 +                      WM_event_add_notifier(C, NC_GEOM|ND_SELECT|ND_DATA, lcd->ob->data);
                        DAG_id_tag_update(lcd->ob->data, 0);
 -                      WM_event_add_notifier(C, NC_GEOM|ND_DATA, lcd->ob->data);
                }
                else {
                        
                        /* sets as active, useful for other tools */
                        if(em->selectmode & SCE_SELECT_VERTEX)
 -                              EM_store_selection(em, lcd->eed->v1, EDITVERT);
 +                              EDBM_selectmode_flush(em);
                        if(em->selectmode & SCE_SELECT_EDGE)
 -                              EM_store_selection(em, lcd->eed, EDITEDGE);
 +                              EDBM_selectmode_flush(em);
                        
 -                      EM_selectmode_flush(lcd->em);
 +                      EDBM_selectmode_flush(lcd->em);
                        WM_event_add_notifier(C, NC_GEOM|ND_SELECT, lcd->ob->data);
                }
        }
  }
  
  /* called when modal loop selection is done... */
 -static void ringsel_exit(wmOperator *op)
 +static void ringsel_exit(bContext *UNUSED(C), wmOperator *op)
  {
        tringselOpData *lcd= op->customdata;
 -
 +      
        /* deactivate the extra drawing stuff in 3D-View */
        ED_region_draw_cb_exit(lcd->ar->type, lcd->draw_handle);
        
@@@ -365,9 -344,14 +367,14 @@@ static int ringsel_init (bContext *C, w
        lcd->ar= CTX_wm_region(C);
        lcd->draw_handle= ED_region_draw_cb_activate(lcd->ar->type, ringsel_draw, lcd, REGION_DRAW_POST_VIEW);
        lcd->ob = CTX_data_edit_object(C);
 -      lcd->em= BKE_mesh_get_editmesh((Mesh *)lcd->ob->data);
 +      lcd->em= ((Mesh *)lcd->ob->data)->edit_btmesh;
        lcd->extend = do_cut ? 0 : RNA_boolean_get(op->ptr, "extend");
        lcd->do_cut = do_cut;
+       
+       initNumInput(&lcd->num);
+       lcd->num.idx_max = 0;
+       lcd->num.flag |= NUM_NO_NEGATIVE | NUM_NO_FRACTION;
+       
        em_setup_viewcontext(C, &lcd->vc);
  
        ED_region_tag_redraw(lcd->ar);
        return 1;
  }
  
 -static int ringcut_cancel (bContext *UNUSED(C), wmOperator *op)
 +static int ringcut_cancel (bContext *C, wmOperator *op)
  {
        /* this is just a wrapper around exit() */
 -      ringsel_exit(op);
 +      ringsel_exit(C, op);
        return OPERATOR_CANCELLED;
  }
  
 -static int ringsel_invoke (bContext *C, wmOperator *op, wmEvent *evt)
 -{
 -      tringselOpData *lcd;
 -      EditEdge *edge;
 -      int dist = 75;
 -      
 -      view3d_operator_needs_opengl(C);
 -
 -      if (!ringsel_init(C, op, 0))
 -              return OPERATOR_CANCELLED;
 -      
 -      lcd = op->customdata;
 -      
 -      if (lcd->em->selectmode == SCE_SELECT_FACE) {
 -              ringsel_exit(op);
 -              WM_operator_name_call(C, "MESH_OT_loop_select", WM_OP_INVOKE_REGION_WIN, NULL);
 -              return OPERATOR_CANCELLED;
 -      }
 -
 -      lcd->vc.mval[0] = evt->mval[0];
 -      lcd->vc.mval[1] = evt->mval[1];
 -      
 -      edge = findnearestedge(&lcd->vc, &dist);
 -      if(!edge) {
 -              ringsel_exit(op);
 -              return OPERATOR_CANCELLED;
 -      }
 -
 -      lcd->eed = edge;
 -      ringsel_find_edge(lcd, 1);
 -
 -      ringsel_finish(C, op);
 -      ringsel_exit(op);
 -
 -      return OPERATOR_FINISHED;
 -}
 -
  static int ringcut_invoke (bContext *C, wmOperator *op, wmEvent *evt)
  {
        Object *obedit= CTX_data_edit_object(C);
        tringselOpData *lcd;
 -      EditEdge *edge;
 +      BMEdge *edge;
        int dist = 75;
  
        if(modifiers_isDeformedByLattice(obedit) || modifiers_isDeformedByArmature(obedit))
        lcd->vc.mval[0] = evt->mval[0];
        lcd->vc.mval[1] = evt->mval[1];
        
 -      edge = findnearestedge(&lcd->vc, &dist);
 +      edge = EDBM_findnearestedge(&lcd->vc, &dist);
        if (edge != lcd->eed) {
                lcd->eed = edge;
                ringsel_find_edge(lcd, 1);
        return OPERATOR_RUNNING_MODAL;
  }
  
 -static int ringcut_modal (bContext *C, wmOperator *op, wmEvent *event)
 +static int loopcut_modal (bContext *C, wmOperator *op, wmEvent *event)
  {
        int cuts= RNA_int_get(op->ptr,"number_cuts");
        tringselOpData *lcd= op->customdata;
  
        view3d_operator_needs_opengl(C);
  
 -
        switch (event->type) {
 +              case RETKEY:
                case LEFTMOUSE: /* confirm */ // XXX hardcoded
                        if (event->val == KM_PRESS) {
                                /* finish */
                                ED_region_tag_redraw(lcd->ar);
                                
                                ringsel_finish(C, op);
 -                              ringsel_exit(op);
 +                              ringsel_exit(C, op);
 +                              
                                ED_area_headerprint(CTX_wm_area(C), NULL);
                                
                                return OPERATOR_FINISHED;
                        ED_region_tag_redraw(lcd->ar);
                        break;
                case RIGHTMOUSE: /* abort */ // XXX hardcoded
 +                      ED_region_tag_redraw(lcd->ar);
 +                      ringsel_exit(C, op);
 +                      ED_area_headerprint(CTX_wm_area(C), NULL);
 +
 +                      return OPERATOR_FINISHED;
                case ESCKEY:
                        if (event->val == KM_RELEASE) {
                                /* cancel */
                        
                        ED_region_tag_redraw(lcd->ar);
                        break;
 -              case WHEELUPMOUSE:  /* change number of cuts */
+               case PADPLUSKEY:
                case PAGEUPKEY:
 -                      if (event->val == KM_PRESS) {
 -                              cuts++;
 -                              RNA_int_set(op->ptr, "number_cuts",cuts);
 -                              ringsel_find_edge(lcd, cuts);
 -                              
 -                              ED_region_tag_redraw(lcd->ar);
 -                      }
 +              case WHEELUPMOUSE:  /* change number of cuts */
 +                      if (event->val == KM_RELEASE)
 +                              break;
 +
 +                      cuts++;
 +                      RNA_int_set(op->ptr,"number_cuts",cuts);
 +                      ringsel_find_edge(lcd, cuts);
 +                      
 +                      ED_region_tag_redraw(lcd->ar);
                        break;
 -              case WHEELDOWNMOUSE:  /* change number of cuts */
+               case PADMINUS:
                case PAGEDOWNKEY:
 -                      if (event->val == KM_PRESS) {
 -                              cuts=MAX2(cuts-1,1);
 -                              RNA_int_set(op->ptr,"number_cuts",cuts);
 -                              ringsel_find_edge(lcd, cuts);
 -                              
 -                              ED_region_tag_redraw(lcd->ar);
 -                      }
 +              case WHEELDOWNMOUSE:  /* change number of cuts */
 +                      if (event->val == KM_RELEASE)
 +                              break;
 +
 +                      cuts=MAX2(cuts-1,1);
 +                      RNA_int_set(op->ptr,"number_cuts",cuts);
 +                      ringsel_find_edge(lcd, cuts);
 +                      
 +                      ED_region_tag_redraw(lcd->ar);
                        break;
                case MOUSEMOVE: { /* mouse moved somewhere to select another loop */
                        int dist = 75;
 -                      EditEdge *edge;
 +                      BMEdge *edge;
  
                        lcd->vc.mval[0] = event->mval[0];
                        lcd->vc.mval[1] = event->mval[1];
 -                      edge = findnearestedge(&lcd->vc, &dist);
 +                      edge = EDBM_findnearestedge(&lcd->vc, &dist);
  
                        if (edge != lcd->eed) {
                                lcd->eed = edge;
                }                       
        }
        
+       /* using the keyboard to input the number of cuts */
+       if (event->val==KM_PRESS) {
+               float value;
+               
+               if (handleNumInput(&lcd->num, event))
+               {
+                       applyNumInput(&lcd->num, &value);
+                       
+                       cuts= CLAMPIS(value, 1, 32);
+                       
+                       RNA_int_set(op->ptr,"number_cuts",cuts);
+                       ringsel_find_edge(lcd, cuts);
+                       
+                       ED_region_tag_redraw(lcd->ar);
+               }
+       }
+       
        /* keep going until the user confirms */
        return OPERATOR_RUNNING_MODAL;
  }
  
 -void MESH_OT_edgering_select (wmOperatorType *ot)
 -{
 -      /* description */
 -      ot->name= "Edge Ring Select";
 -      ot->idname= "MESH_OT_edgering_select";
 -      ot->description= "Select an edge ring";
 -      
 -      /* callbacks */
 -      ot->invoke= ringsel_invoke;
 -      ot->poll= ED_operator_editmesh_region_view3d; 
 -      
 -      /* flags */
 -      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 -
 -      RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
 -}
 -
  void MESH_OT_loopcut (wmOperatorType *ot)
  {
        /* description */
        
        /* callbacks */
        ot->invoke= ringcut_invoke;
 -      ot->modal= ringcut_modal;
 +      ot->modal= loopcut_modal;
        ot->cancel= ringcut_cancel;
        ot->poll= ED_operator_editmesh_region_view3d;
        
@@@ -364,16 -364,6 +364,16 @@@ static int multiresbake_test_break(Mult
  static void do_multires_bake(MultiresBakeRender *bkr, Image* ima, MPassKnownData passKnownData,
                               MInitBakeData initBakeData, MApplyBakeData applyBakeData, MFreeBakeData freeBakeData)
  {
 +#if 1 // BMESH_TODO
 +      (void)bkr;
 +      (void)ima;
 +      (void)passKnownData;
 +      (void)initBakeData;
 +      (void)applyBakeData;
 +      (void)freeBakeData;
 +
 +      printf("BMESH_TODO" AT "\n");
 +#else
        DerivedMesh *dm= bkr->lores_dm;
        ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
        const int lvl= bkr->lvl;
                if(freeBakeData)
                        freeBakeData(data.bake_data);
        }
 +#endif // BMESH_TODO
  }
  
  static void interp_bilinear_quad_data(float data[4][3], float u, float v, float res[3])
@@@ -519,17 -508,6 +519,17 @@@ static void interp_bilinear_grid(DMGrid
  
  static void get_ccgdm_data(DerivedMesh *lodm, DerivedMesh *hidm, const int *origindex,  const int lvl, const int face_index, const float u, const float v, float co[3], float n[3])
  {
 +#if 1 // BMESH_TODO
 +      (void)lodm;
 +      (void)hidm;
 +      (void)origindex;
 +      (void)lvl;
 +      (void)face_index;
 +      (void)u;
 +      (void)v;
 +      (void)co;
 +      (void)n;
 +#else
        MFace mface;
        DMGridData **grid_data;
        float crn_x, crn_y;
  
        if(co != NULL)
                interp_bilinear_grid(grid_data[g_index + S], grid_size, crn_x, crn_y, 1, co);
 +#endif
  }
  
  /* mode = 0: interpolate normals,
@@@ -642,7 -619,7 +642,7 @@@ static void *init_heights_data(Multires
                height_data->ssdm= subsurf_make_derived_from_derived(bkr->lores_dm, &smd, 0, NULL, 0, 0, 0);
        }
  
 -      height_data->origindex= lodm->getFaceDataArray(lodm, CD_ORIGINDEX);
 +      height_data->origindex= lodm->getTessFaceDataArray(lodm, CD_ORIGINDEX);
  
        return (void*)height_data;
  }
@@@ -654,7 -631,7 +654,7 @@@ static void *init_normal_data(MultiresB
  
        normal_data= MEM_callocN(sizeof(MNormalBakeData), "MultiresBake normalData");
  
 -      normal_data->origindex= lodm->getFaceDataArray(lodm, CD_ORIGINDEX);
 +      normal_data->origindex= lodm->getTessFaceDataArray(lodm, CD_ORIGINDEX);
  
        return (void*)normal_data;
  }
@@@ -716,16 -693,6 +716,16 @@@ static void apply_heights_callback(Deri
                                     const int face_index, const int lvl, const float st[2],
                                     float UNUSED(tangmat[3][3]), const int x, const int y)
  {
 +#if 1 // BMESH_TODO
 +      (void)lores_dm;
 +      (void)hires_dm;
 +      (void)bake_data;
 +      (void)face_index;
 +      (void)lvl;
 +      (void)st;
 +      (void)x;
 +      (void)y;
 +#else
        MTFace *mtface= CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
        MFace mface;
        Image *ima= mtface[face_index].tpage;
                char *rrgb= (char*)ibuf->rect + pixel*4;
                rrgb[3]= 255;
        }
 +#endif // BMESH_TODO
  }
  
  /* MultiresBake callback for normals' baking
@@@ -794,17 -760,6 +794,17 @@@ static void apply_tangmat_callback(Deri
                                     const int face_index, const int lvl, const float st[2],
                                     float tangmat[3][3], const int x, const int y)
  {
 +#if 1 // BMESH_TODO
 +      (void)lores_dm;
 +      (void)hires_dm;
 +      (void)bake_data;
 +      (void)face_index;
 +      (void)lvl;
 +      (void)st;
 +      (void)tangmat;
 +      (void)y;
 +      (void)x;
 +#else
        MTFace *mtface= CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
        MFace mface;
        Image *ima= mtface[face_index].tpage;
                rrgb[2]= FTOCHAR(vec[2]);
                rrgb[3]= 255;
        }
 +#endif
  }
  
  static void count_images(MultiresBakeRender *bkr)
@@@ -1037,7 -991,7 +1037,7 @@@ static DerivedMesh *multiresbake_create
  
        if(*lvl==0) {
                DerivedMesh *tmp_dm= CDDM_from_mesh(me, ob);
 -              dm= CDDM_copy(tmp_dm);
 +              dm= CDDM_copy(tmp_dm, 0);
                tmp_dm->release(tmp_dm);
        } else {
                MultiresModifierData tmp_mmd= *mmd;
@@@ -1085,7 -1039,7 +1085,7 @@@ static void clear_images(MTFace *mtface
                if((ima->id.flag&LIB_DOIT)==0) {
                        ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
  
-                       IMB_rectfill(ibuf, (ibuf->depth == 32) ? vec_alpha : vec_solid);
+                       IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
                        ima->id.flag|= LIB_DOIT;
                }
        }
@@@ -79,7 -79,6 +79,7 @@@
  #include "BKE_sca.h"
  #include "BKE_softbody.h"
  #include "BKE_modifier.h"
 +#include "BKE_tessmesh.h"
  
  #include "ED_armature.h"
  #include "ED_curve.h"
@@@ -322,18 -321,18 +322,18 @@@ void ED_object_exit_editmode(bContext *
  //            if(retopo_mesh_paint_check())
  //                    retopo_end_okee();
                
 -              if(me->edit_mesh->totvert>MESH_MAX_VERTS) {
 +              if(me->edit_btmesh->bm->totvert>MESH_MAX_VERTS) {
                        error("Too many vertices");
                        return;
                }
 -              load_editMesh(scene, obedit);
 +              
 +              EDBM_LoadEditBMesh(scene, obedit);
                
                if(freedata) {
 -                      free_editMesh(me->edit_mesh);
 -                      MEM_freeN(me->edit_mesh);
 -                      me->edit_mesh= NULL;
 +                      EDBM_FreeEditBMesh(me->edit_btmesh);
 +                      MEM_freeN(me->edit_btmesh);
 +                      me->edit_btmesh= NULL;
                }
 -              
                if(obedit->restore_mode & OB_MODE_WEIGHT_PAINT) {
                        mesh_octree_table(NULL, NULL, NULL, 'e');
                        mesh_mirrtopo_table(NULL, 'e');
@@@ -446,7 -445,7 +446,7 @@@ void ED_object_enter_editmode(bContext 
                ok= 1;
                scene->obedit= ob;      // context sees this
                
 -              make_editMesh(scene, ob);
 +              EDBM_MakeEditBMesh(CTX_data_tool_settings(C), scene, ob);
  
                WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_MESH, scene);
        }
@@@ -2057,10 -2056,8 +2057,8 @@@ static int game_property_copy_exec(bCon
                
                if(prop) {
                        CTX_DATA_BEGIN(C, Object*, ob_iter, selected_editable_objects) {
-                               if (ob != ob_iter) {
-                                       if (ob->data != ob_iter->data)
-                                               set_ob_property(ob_iter, prop);
-                               }
+                               if (ob != ob_iter)
+                                       set_ob_property(ob_iter, prop);
                        } CTX_DATA_END;
                }
        }
        else {
                CTX_DATA_BEGIN(C, Object*, ob_iter, selected_editable_objects) {
                        if (ob != ob_iter) {
-                               if (ob->data != ob_iter->data){
-                                       if (type == COPY_PROPERTIES_REPLACE)
-                                               copy_properties( &ob_iter->prop, &ob->prop );
-                                       /* merge - the default when calling with no argument */
-                                       else {
-                                               for(prop = ob->prop.first; prop; prop= prop->next ) {
-                                                       set_ob_property(ob_iter, prop);
-                                               }
-                                       }
-                               }
+                               if (type == COPY_PROPERTIES_REPLACE)
+                                       copy_properties(&ob_iter->prop, &ob->prop);
+                               /* merge - the default when calling with no argument */
+                               else
+                                       for(prop = ob->prop.first; prop; prop= prop->next)
+                                               set_ob_property(ob_iter, prop);
                        }
                }
                CTX_DATA_END;
@@@ -62,7 -62,6 +62,7 @@@
  #include "BKE_scene.h"
  #include "BKE_texture.h"
  #include "BKE_world.h"
 +#include "BKE_tessmesh.h"
  
  #include "IMB_imbuf.h"
  #include "IMB_imbuf_types.h"
@@@ -164,15 -163,13 +164,15 @@@ static int material_slot_assign_exec(bC
  
        if(ob && ob->actcol>0) {
                if(ob->type == OB_MESH) {
 -                      EditMesh *em= ((Mesh*)ob->data)->edit_mesh;
 -                      EditFace *efa;
 +                      BMEditMesh *em= ((Mesh*)ob->data)->edit_btmesh;
 +                      BMFace *efa;
 +                      BMIter iter;
  
                        if(em) {
 -                              for(efa= em->faces.first; efa; efa=efa->next)
 -                                      if(efa->f & SELECT)
 +                              BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +                                      if(BM_TestHFlag(efa, BM_SELECT))
                                                efa->mat_nr= ob->actcol-1;
 +                              }
                        }
                }
                else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
@@@ -225,10 -222,13 +225,10 @@@ static int material_slot_de_select(bCon
                return OPERATOR_CANCELLED;
  
        if(ob->type == OB_MESH) {
 -              EditMesh *em= ((Mesh*)ob->data)->edit_mesh;
 +              BMEditMesh *em= ((Mesh*)ob->data)->edit_btmesh;
  
                if(em) {
 -                      if(select)
 -                              EM_select_by_material(em, ob->actcol-1);
 -                      else
 -                              EM_deselect_by_material(em, ob->actcol-1);
 +                      EDBM_deselect_by_material(em, ob->actcol-1, select);
                }
        }
        else if ELEM(ob->type, OB_CURVE, OB_SURF) {
@@@ -658,7 -658,7 +658,7 @@@ void TEXTURE_OT_slot_move(wmOperatorTyp
  
  /********************** environment map operators *********************/
  
- static int save_envmap(wmOperator *op, Scene *scene, EnvMap *env, char *path, int imtype)
+ static int save_envmap(wmOperator *op, Scene *scene, EnvMap *env, char *path, const char imtype)
  {
        float layout[12];
        if ( RNA_struct_find_property(op->ptr, "layout") )
@@@ -680,7 -680,7 +680,7 @@@ static int envmap_save_exec(bContext *C
        Tex *tex= CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
        Scene *scene = CTX_data_scene(C);
        //int imtype = RNA_enum_get(op->ptr, "file_type");
-       int imtype = scene->r.imtype;
+       char imtype = scene->r.im_format.imtype;
        char path[FILE_MAX];
        
        RNA_string_get(op->ptr, "filepath", path);
@@@ -707,7 -707,7 +707,7 @@@ static int envmap_save_invoke(bContext 
        if(RNA_property_is_set(op->ptr, "filepath"))
                return envmap_save_exec(C, op);
  
-       //RNA_enum_set(op->ptr, "file_type", scene->r.imtype);
+       //RNA_enum_set(op->ptr, "file_type", scene->r.im_format.imtype);
        RNA_string_set(op->ptr, "filepath", G.main->name);
        WM_event_add_fileselect(C, op);
        
@@@ -2962,11 -2962,11 +2962,11 @@@ static void project_paint_begin(ProjPai
        }
        
        ps->dm_mvert = ps->dm->getVertArray(ps->dm);
 -      ps->dm_mface = ps->dm->getFaceArray(ps->dm);
 -      ps->dm_mtface= ps->dm->getFaceDataArray(ps->dm, CD_MTFACE);
 +      ps->dm_mface = ps->dm->getTessFaceArray(ps->dm);
 +      ps->dm_mtface= ps->dm->getTessFaceDataArray(ps->dm, CD_MTFACE);
        
        ps->dm_totvert = ps->dm->getNumVerts(ps->dm);
 -      ps->dm_totface = ps->dm->getNumFaces(ps->dm);
 +      ps->dm_totface = ps->dm->getNumTessFaces(ps->dm);
        
        /* use clone mtface? */
        
        }
        
        /* when using subsurf or multires, mface arrays are thrown away, we need to keep a copy */
 -      if(ps->dm->type != DM_TYPE_CDDM) {
 +      // this seems like a bad check, since some constructive modifiers use cddm? - joeedh
 +      if(1) { //ps->dm->type != DM_TYPE_CDDM) {
                ps->dm_mvert= MEM_dupallocN(ps->dm_mvert);
                ps->dm_mface= MEM_dupallocN(ps->dm_mface);
                /* looks like these are ok for now.*/
 -              /*
 +              
                ps->dm_mtface= MEM_dupallocN(ps->dm_mtface);
 -              ps->dm_mtface_clone= MEM_dupallocN(ps->dm_mtface_clone);
 -              ps->dm_mtface_stencil= MEM_dupallocN(ps->dm_mtface_stencil);
 -               */
 +              if (ps->dm_mtface_clone)
 +                      ps->dm_mtface_clone= MEM_dupallocN(ps->dm_mtface_clone);
 +              if (ps->dm_mtface_stencil)
 +                      ps->dm_mtface_stencil= MEM_dupallocN(ps->dm_mtface_stencil);
 +               
        }
        
        ps->viewDir[0] = 0.0f;
@@@ -3489,8 -3486,7 +3489,8 @@@ static void project_paint_end(ProjPaint
        }
        
        /* copy for subsurf/multires, so throw away */
 -      if(ps->dm->type != DM_TYPE_CDDM) {
 +      // this seems like a bad check, since some constructive modifiers use cddm? - joeedh
 +      if(1) { //ps->dm->type != DM_TYPE_CDDM) {
                if(ps->dm_mvert) MEM_freeN(ps->dm_mvert);
                if(ps->dm_mface) MEM_freeN(ps->dm_mface);
                /* looks like these dont need copying */
@@@ -4337,7 -4333,7 +4337,7 @@@ static ImBuf *imapaint_lift_clone(ImBu
        /* note: allocImbuf returns zero'd memory, so regions outside image will
           have zero alpha, and hence not be blended onto the image */
        int w=ibufb->x, h=ibufb->y, destx=0, desty=0, srcx=pos[0], srcy=pos[1];
-       ImBuf *clonebuf= IMB_allocImBuf(w, h, ibufb->depth, ibufb->flags);
+       ImBuf *clonebuf= IMB_allocImBuf(w, h, ibufb->planes, ibufb->flags);
  
        IMB_rectclip(clonebuf, ibuf, &destx, &desty, &srcx, &srcy, &w, &h);
        IMB_rectblend(clonebuf, ibuf, destx, desty, srcx, srcy, w, h,
@@@ -4799,20 -4795,9 +4799,20 @@@ static int texture_paint_init(bContext 
        pop->orig_brush_size= brush_size(brush);
  
        if(pop->mode != PAINT_MODE_2D) {
 +              Mesh *me;
 +
                pop->s.ob = OBACT;
 +              if (!pop->ps.ob)
 +                      pop->ps.ob = pop->s.ob;
 +              
                pop->s.me = get_mesh(pop->s.ob);
                if (!pop->s.me) return 0;
 +              
 +              me = pop->s.me;
 +
 +              /* Dont allow brush size below 2 */
 +              if (pop->ps.brush && pop->ps.brush->size<=1)
 +                      pop->ps.brush->size = 2;
        }
        else {
                pop->s.image = pop->s.sima->image;
@@@ -48,7 -48,6 +48,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"
@@@ -81,8 -80,6 +81,8 @@@
  #include "BKE_movieclip.h"
  #include "BKE_tracking.h"
  
 +#include "BKE_tessmesh.h"
 +
  #include "smoke_API.h"
  
  #include "IMB_imbuf.h"
@@@ -1892,18 -1889,16 +1892,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);
  }
@@@ -1959,23 -1954,17 +1959,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);
  }
@@@ -2107,53 -2093,46 +2107,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);
  
        }
  
        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;
 +                      }
 +
 +                      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);
                        }
 +                      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) {
 -              EditEdge *e1, *e2, *e3, *e4;
 +              BMFace *efa;
 +
                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);
 -                      }
 -                      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);
 +
 +
 +              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)) {
                        if(draw_glsl_material(scene, ob, v3d, dt)) {
-                               /* if em has no faces the drawMappedFaces callback will fail */
-                               if(em->bm->totface) {
-                                       glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
+                               glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
 -                              
 +
-                                       finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
-                                                                    draw_em_fancy__setGLSLFaceOpts, em);
-                                       GPU_disable_material();
+                               finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
 -                                                           draw_em_fancy__setGLSLFaceOpts, NULL);
++                                                           draw_em_fancy__setGLSLFaceOpts, em);
+                               GPU_disable_material();
 -                              
 +
-                                       glFrontFace(GL_CCW);
-                               }
+                               glFrontFace(GL_CCW);
                        }
                        else {
                                draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
                        }
                }
                else {
-                       /* if em has no faces the drawMappedFaces callback will fail */
-                       if(em->bm->totface) {
-                               /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
-                               glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
+                       /* 3 floats for position, 3 for normal and times two because the faces may actually be quads instead of triangles */
+                       glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
 -                      
 +
-                               glEnable(GL_LIGHTING);
-                               glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
-                               finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, me->edit_btmesh, 0, GPU_enable_material, NULL);
+                       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);
-                       }
+                       glFrontFace(GL_CCW);
+                       glDisable(GL_LIGHTING);
                }
                        
                // Setup for drawing wire over, disable zbuffer
                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 */
@@@ -3031,7 -2942,7 +3025,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);
@@@ -3293,7 -3204,7 +3287,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) {
@@@ -6855,51 -6766,44 +6849,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);
        }
  }
  
@@@ -6998,36 -6899,36 +6992,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 {
@@@ -7071,7 -6972,7 +7065,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);
  
@@@ -255,6 -255,7 +255,7 @@@ extern StructRNA RNA_HookModifier
  extern StructRNA RNA_ID;
  extern StructRNA RNA_IKParam;
  extern StructRNA RNA_Image;
+ extern StructRNA RNA_ImageFormatSettings;
  extern StructRNA RNA_ImagePaint;
  extern StructRNA RNA_ImageSequence;
  extern StructRNA RNA_ImageTexture;
@@@ -308,8 -309,6 +309,8 @@@ extern StructRNA RNA_MeshColorLayer
  extern StructRNA RNA_MeshDeformModifier;
  extern StructRNA RNA_MeshEdge;
  extern StructRNA RNA_MeshFace;
 +extern StructRNA RNA_MeshPolygon;
 +extern StructRNA RNA_MeshLoop;
  extern StructRNA RNA_MeshFloatProperty;
  extern StructRNA RNA_MeshFloatPropertyLayer;
  extern StructRNA RNA_MeshIntProperty;
@@@ -39,8 -39,6 +39,8 @@@
  #include "DNA_userdef_types.h"
  #include "BLI_math.h"
  
 +#include "BKE_tessmesh.h"
 +
  /* Include for Bake Options */
  #include "RE_engine.h"
  #include "RE_pipeline.h"
@@@ -104,65 -102,124 +104,124 @@@ EnumPropertyItem snap_element_items[] 
        {SCE_SNAP_MODE_VOLUME, "VOLUME", ICON_SNAP_VOLUME, "Volume", "Snap to volume"},
        {0, NULL, 0, NULL, NULL}};
  
+ /* note on duplicate block, perhaps we should use some trick to avoid
+  * the duplicate, but with the inline defines it becomes very tricky
+  * this awaits someone who has very good preprocessor-fu.
+  * for now just make sure they stay in sync - campbell */
+ EnumPropertyItem image_only_type_items[] = {
+     /* --- duplicate block warning (see below) --- */
+ #define IMAGE_TYPE_ITEMS_IMAGE_ONLY
+       {R_IMF_IMTYPE_BMP, "BMP", ICON_FILE_IMAGE, "BMP", "Output image in bitmap format"},
+ #ifdef WITH_DDS
+       {R_IMF_IMTYPE_DDS, "DDS", ICON_FILE_IMAGE, "DDS", "Output image in DDS format"},
+ #endif
+       {R_IMF_IMTYPE_IRIS, "IRIS", ICON_FILE_IMAGE, "Iris", "Output image in (old!) SGI IRIS format"},
+       {R_IMF_IMTYPE_PNG, "PNG", ICON_FILE_IMAGE, "PNG", "Output image in PNG format"},
+       {R_IMF_IMTYPE_JPEG90, "JPEG", ICON_FILE_IMAGE, "JPEG", "Output image in JPEG format"},
+ #ifdef WITH_OPENJPEG
+       {R_IMF_IMTYPE_JP2, "JPEG2000", ICON_FILE_IMAGE, "JPEG 2000", "Output image in JPEG 2000 format"},
+ #endif
+       {R_IMF_IMTYPE_TARGA, "TARGA", ICON_FILE_IMAGE, "Targa", "Output image in Targa format"},
+       {R_IMF_IMTYPE_RAWTGA, "TARGA_RAW", ICON_FILE_IMAGE, "Targa Raw", "Output image in uncompressed Targa format"},
+       {0, "", 0, " ", NULL},
+ #ifdef WITH_CINEON
+       {R_IMF_IMTYPE_CINEON, "CINEON", ICON_FILE_IMAGE, "Cineon", "Output image in Cineon format"},
+       {R_IMF_IMTYPE_DPX, "DPX",ICON_FILE_IMAGE, "DPX", "Output image in DPX format"},
+ #endif
+ #ifdef WITH_OPENEXR
+       {R_IMF_IMTYPE_MULTILAYER, "MULTILAYER", ICON_FILE_IMAGE, "MultiLayer", "Output image in multilayer OpenEXR format"},
+       {R_IMF_IMTYPE_OPENEXR, "OPEN_EXR", ICON_FILE_IMAGE, "OpenEXR", "Output image in OpenEXR format"},
+ #endif
+ #ifdef WITH_HDR
+       {R_IMF_IMTYPE_RADHDR, "HDR", ICON_FILE_IMAGE, "Radiance HDR", "Output image in Radiance HDR format"},
+ #endif
+ #ifdef WITH_TIFF
+       {R_IMF_IMTYPE_TIFF, "TIFF", ICON_FILE_IMAGE, "TIFF", "Output image in TIFF format"},
+ #endif
+     /* --- end duplicate block (see below) --- */
+       {0, NULL, 0, NULL, NULL}};
  EnumPropertyItem image_type_items[] = {
        {0, "", 0, "Image", NULL},
-       {R_BMP, "BMP", ICON_FILE_IMAGE, "BMP", "Output image in bitmap format"},
+     /* --- duplicate block warning (see above) --- */
+ #define IMAGE_TYPE_ITEMS_IMAGE_ONLY
+       {R_IMF_IMTYPE_BMP, "BMP", ICON_FILE_IMAGE, "BMP", "Output image in bitmap format"},
  #ifdef WITH_DDS
-       {R_DDS, "DDS", ICON_FILE_IMAGE, "DDS", "Output image in DDS format"},
+       {R_IMF_IMTYPE_DDS, "DDS", ICON_FILE_IMAGE, "DDS", "Output image in DDS format"},
  #endif
-       {R_IRIS, "IRIS", ICON_FILE_IMAGE, "Iris", "Output image in (old!) SGI IRIS format"},
-       {R_PNG, "PNG", ICON_FILE_IMAGE, "PNG", "Output image in PNG format"},
-       {R_JPEG90, "JPEG", ICON_FILE_IMAGE, "JPEG", "Output image in JPEG format"},
+       {R_IMF_IMTYPE_IRIS, "IRIS", ICON_FILE_IMAGE, "Iris", "Output image in (old!) SGI IRIS format"},
+       {R_IMF_IMTYPE_PNG, "PNG", ICON_FILE_IMAGE, "PNG", "Output image in PNG format"},
+       {R_IMF_IMTYPE_JPEG90, "JPEG", ICON_FILE_IMAGE, "JPEG", "Output image in JPEG format"},
  #ifdef WITH_OPENJPEG
-       {R_JP2, "JPEG2000", ICON_FILE_IMAGE, "JPEG 2000", "Output image in JPEG 2000 format"},
+       {R_IMF_IMTYPE_JP2, "JPEG2000", ICON_FILE_IMAGE, "JPEG 2000", "Output image in JPEG 2000 format"},
  #endif
-       {R_TARGA, "TARGA", ICON_FILE_IMAGE, "Targa", "Output image in Targa format"},
-       {R_RAWTGA, "TARGA_RAW", ICON_FILE_IMAGE, "Targa Raw", "Output image in uncompressed Targa format"},
+       {R_IMF_IMTYPE_TARGA, "TARGA", ICON_FILE_IMAGE, "Targa", "Output image in Targa format"},
+       {R_IMF_IMTYPE_RAWTGA, "TARGA_RAW", ICON_FILE_IMAGE, "Targa Raw", "Output image in uncompressed Targa format"},
        {0, "", 0, " ", NULL},
  #ifdef WITH_CINEON
-       {R_CINEON, "CINEON", ICON_FILE_IMAGE, "Cineon", "Output image in Cineon format"},
-       {R_DPX, "DPX",ICON_FILE_IMAGE, "DPX", "Output image in DPX format"},
+       {R_IMF_IMTYPE_CINEON, "CINEON", ICON_FILE_IMAGE, "Cineon", "Output image in Cineon format"},
+       {R_IMF_IMTYPE_DPX, "DPX",ICON_FILE_IMAGE, "DPX", "Output image in DPX format"},
  #endif
  #ifdef WITH_OPENEXR
-       {R_MULTILAYER, "MULTILAYER", ICON_FILE_IMAGE, "MultiLayer", "Output image in multilayer OpenEXR format"},
-       {R_OPENEXR, "OPEN_EXR", ICON_FILE_IMAGE, "OpenEXR", "Output image in OpenEXR format"},
+       {R_IMF_IMTYPE_MULTILAYER, "MULTILAYER", ICON_FILE_IMAGE, "MultiLayer", "Output image in multilayer OpenEXR format"},
+       {R_IMF_IMTYPE_OPENEXR, "OPEN_EXR", ICON_FILE_IMAGE, "OpenEXR", "Output image in OpenEXR format"},
  #endif
  #ifdef WITH_HDR
-       {R_RADHDR, "HDR", ICON_FILE_IMAGE, "Radiance HDR", "Output image in Radiance HDR format"},
+       {R_IMF_IMTYPE_RADHDR, "HDR", ICON_FILE_IMAGE, "Radiance HDR", "Output image in Radiance HDR format"},
  #endif
  #ifdef WITH_TIFF
-       {R_TIFF, "TIFF", ICON_FILE_IMAGE, "TIFF", "Output image in TIFF format"},
+       {R_IMF_IMTYPE_TIFF, "TIFF", ICON_FILE_IMAGE, "TIFF", "Output image in TIFF format"},
  #endif
+     /* --- end duplicate block (see above) --- */
        {0, "", 0, "Movie", NULL},
  #ifdef _WIN32
-       {R_AVICODEC, "AVICODEC", ICON_FILE_MOVIE, "AVI Codec", "Output video in AVI format"}, // XXX Missing codec menu
+       {R_IMF_IMTYPE_AVICODEC, "AVICODEC", ICON_FILE_MOVIE, "AVI Codec", "Output video in AVI format"}, // XXX Missing codec menu
  #endif
-       {R_AVIJPEG, "AVI_JPEG", ICON_FILE_MOVIE, "AVI JPEG", "Output video in AVI JPEG format"},
-       {R_AVIRAW, "AVI_RAW", ICON_FILE_MOVIE, "AVI Raw", "Output video in AVI Raw format"},
+       {R_IMF_IMTYPE_AVIJPEG, "AVI_JPEG", ICON_FILE_MOVIE, "AVI JPEG", "Output video in AVI JPEG format"},
+       {R_IMF_IMTYPE_AVIRAW, "AVI_RAW", ICON_FILE_MOVIE, "AVI Raw", "Output video in AVI Raw format"},
  #ifdef WITH_FRAMESERVER
-       {R_FRAMESERVER, "FRAMESERVER", ICON_FILE_SCRIPT, "Frame Server", "Output image to a frameserver"},
+       {R_IMF_IMTYPE_FRAMESERVER, "FRAMESERVER", ICON_FILE_SCRIPT, "Frame Server", "Output image to a frameserver"},
  #endif
  #ifdef WITH_FFMPEG
-       {R_H264, "H264", ICON_FILE_MOVIE, "H.264", "Output video in H.264 format"},
-       {R_FFMPEG, "FFMPEG", ICON_FILE_MOVIE, "MPEG", "Output video in MPEG format"},
-       {R_THEORA, "THEORA", ICON_FILE_MOVIE, "Ogg Theora", "Output video in Ogg format"},
+       {R_IMF_IMTYPE_H264, "H264", ICON_FILE_MOVIE, "H.264", "Output video in H.264 format"},
+       {R_IMF_IMTYPE_FFMPEG, "FFMPEG", ICON_FILE_MOVIE, "MPEG", "Output video in MPEG format"},
+       {R_IMF_IMTYPE_THEORA, "THEORA", ICON_FILE_MOVIE, "Ogg Theora", "Output video in Ogg format"},
  #endif
  #ifdef WITH_QUICKTIME
  #     ifdef USE_QTKIT
-       {R_QUICKTIME, "QUICKTIME_QTKIT", ICON_FILE_MOVIE, "QuickTime", "Output video in Quicktime format"},
+       {R_IMF_IMTYPE_QUICKTIME, "QUICKTIME_QTKIT", ICON_FILE_MOVIE, "QuickTime", "Output video in Quicktime format"},
  #     else
-       {R_QUICKTIME, "QUICKTIME_CARBON", ICON_FILE_MOVIE, "QuickTime", "Output video in Quicktime format"},
+       {R_IMF_IMTYPE_QUICKTIME, "QUICKTIME_CARBON", ICON_FILE_MOVIE, "QuickTime", "Output video in Quicktime format"},
  #     endif
  #endif
  #ifdef WITH_FFMPEG
-       {R_XVID, "XVID", ICON_FILE_MOVIE, "Xvid", "Output video in Xvid format"},
+       {R_IMF_IMTYPE_XVID, "XVID", ICON_FILE_MOVIE, "Xvid", "Output video in Xvid format"},
  #endif
        {0, NULL, 0, NULL, NULL}};
  
  EnumPropertyItem image_color_mode_items[] ={
-       {R_PLANESBW, "BW", 0, "BW", "Images get saved in 8 bits grayscale (only PNG, JPEG, TGA, TIF)"},
-       {R_PLANES24, "RGB", 0, "RGB", "Images are saved with RGB (color) data"},
-       {R_PLANES32, "RGBA", 0, "RGBA", "Images are saved with RGB and Alpha data (if supported)"},
+       {R_IMF_PLANES_BW, "BW", 0, "BW", "Images get saved in 8 bits grayscale (only PNG, JPEG, TGA, TIF)"},
+       {R_IMF_PLANES_RGB, "RGB", 0, "RGB", "Images are saved with RGB (color) data"},
+       {R_IMF_PLANES_RGBA, "RGBA", 0, "RGBA", "Images are saved with RGB and Alpha data (if supported)"},
+       {0, NULL, 0, NULL, NULL}};
+ EnumPropertyItem image_color_depth_items[] = {
+       /* 1 (monochrome) not used */
+       {R_IMF_CHAN_DEPTH_8,   "8", 0, "8",  "8 bit color channels"},
+       {R_IMF_CHAN_DEPTH_12, "12", 0, "12", "12 bit color channels"},
+       {R_IMF_CHAN_DEPTH_16, "16", 0, "16", "16 bit color channels"},
+       /* 24 not used */
+       {R_IMF_CHAN_DEPTH_32, "32", 0, "32", "32 bit color channels"},
        {0, NULL, 0, NULL, NULL}};
  
  #ifdef RNA_RUNTIME
@@@ -531,7 -588,7 +590,7 @@@ static int rna_RenderSettings_threads_g
  static int rna_RenderSettings_is_movie_fomat_get(PointerRNA *ptr)
  {
        RenderData *rd= (RenderData*)ptr->data;
-       return BKE_imtype_is_movie(rd->imtype);
+       return BKE_imtype_is_movie(rd->im_format.imtype);
  }
  
  static int rna_RenderSettings_save_buffers_get(PointerRNA *ptr)
@@@ -550,71 -607,156 +609,156 @@@ static int rna_RenderSettings_full_samp
        return (rd->scemode & R_FULL_SAMPLE) && !(rd->mode & R_BORDER);
  }
  
- static void rna_RenderSettings_file_format_set(PointerRNA *ptr, int value)
+ static void rna_ImageFormatSettings_file_format_set(PointerRNA *ptr, int value)
  {
-       RenderData *rd= (RenderData*)ptr->data;
+       ImageFormatData *imf= (ImageFormatData *)ptr->data;
+       ID *id= ptr->id.data;
+       imf->imtype= value;
+       /* ensure depth and color settings match */
+       if (!BKE_imtype_supports_alpha(imf->imtype)) {
+               imf->planes= R_IMF_PLANES_RGB;
+       }
+       /* ensure usable depth */
+       {
+               const int depth_ok= BKE_imtype_valid_depths(imf->imtype);
+               if ((imf->depth & depth_ok) == 0) {
+                       /* set first available depth */
+                       char depth_ls[]= {R_IMF_CHAN_DEPTH_32,
+                                         R_IMF_CHAN_DEPTH_24,
+                                         R_IMF_CHAN_DEPTH_16,
+                                         R_IMF_CHAN_DEPTH_12,
+                                         R_IMF_CHAN_DEPTH_8,
+                                         R_IMF_CHAN_DEPTH_1,
+                                         0};
+                       int i;
+                       for (i= 0; depth_ls[i]; i++) {
+                               if (depth_ok & depth_ls[i]) {
+                                       imf->depth= depth_ls[i];
+                                       break;
+                               }
+                       }
+               }
+       }
  
-       rd->imtype= value;
+       if (id && GS(id->name) == ID_SCE) {
+               Scene *scene= ptr->id.data;
+               RenderData *rd= &scene->r;
  #ifdef WITH_FFMPEG
-       ffmpeg_verify_image_type(rd);
+               ffmpeg_verify_image_type(rd);
  #endif
  #ifdef WITH_QUICKTIME
-       quicktime_verify_image_type(rd);
+               quicktime_verify_image_type(rd);
  #endif
+               (void)rd;
+       }
  }
  
- static int rna_SceneRender_file_ext_length(PointerRNA *ptr)
+ static EnumPropertyItem *rna_ImageFormatSettings_file_format_itemf(bContext *C, PointerRNA *ptr,
+                                                                    PropertyRNA *UNUSED(prop), int *free)
  {
-       RenderData *rd= (RenderData*)ptr->data;
-       char ext[8];
-       ext[0]= '\0';
-       BKE_add_image_extension(ext, rd->imtype);
-       return strlen(ext);
+       ID *id= ptr->id.data;
+       if (id && GS(id->name) == ID_SCE) {
+               return image_type_items;
+       }
+       else {
+               return image_only_type_items;
+       }
  }
  
- static void rna_SceneRender_file_ext_get(PointerRNA *ptr, char *str)
+ static EnumPropertyItem *rna_ImageFormatSettings_color_mode_itemf(bContext *C, PointerRNA *ptr,
+                                                                   PropertyRNA *UNUSED(prop), int *free)
  {
-       RenderData *rd= (RenderData*)ptr->data;
-       str[0]= '\0';
-       BKE_add_image_extension(str, rd->imtype);
+       ImageFormatData *imf= (ImageFormatData *)ptr->data;
+       if ((imf == NULL) || BKE_imtype_supports_alpha(imf->imtype)) {
+               return image_color_mode_items;
+       }
+       else {
+               static EnumPropertyItem color_mode_items[] ={
+                       {R_IMF_PLANES_BW, "BW", 0, "BW", "Images get saved in 8 bits grayscale (only PNG, JPEG, TGA, TIF)"},
+                       {R_IMF_PLANES_RGB, "RGB", 0, "RGB", "Images are saved with RGB (color) data"},
+                       {0, NULL, 0, NULL, NULL}};
+               return color_mode_items;
+       }
  }
  
- void rna_RenderSettings_jpeg2k_preset_update(RenderData *rd)
+ static EnumPropertyItem *rna_ImageFormatSettings_color_depth_itemf(bContext *C, PointerRNA *ptr,
+                                                                   PropertyRNA *UNUSED(prop), int *free)
  {
-       rd->subimtype &= ~(R_JPEG2K_12BIT|R_JPEG2K_16BIT | R_JPEG2K_CINE_PRESET|R_JPEG2K_CINE_48FPS);
-       
-       switch(rd->jp2_depth) {
-       case 8:         break;
-       case 12:        rd->subimtype |= R_JPEG2K_12BIT; break;
-       case 16:        rd->subimtype |= R_JPEG2K_16BIT; break;
+       ImageFormatData *imf= (ImageFormatData *)ptr->data;
+       if (imf == NULL) {
+               return image_color_depth_items;
        }
-       
-       switch(rd->jp2_preset) {
-       case 1: rd->subimtype |= R_JPEG2K_CINE_PRESET;                                          break;
-       case 2: rd->subimtype |= R_JPEG2K_CINE_PRESET|R_JPEG2K_CINE_48FPS;      break;
-       case 3: rd->subimtype |= R_JPEG2K_CINE_PRESET;                                          break;
-       case 4: rd->subimtype |= R_JPEG2K_CINE_PRESET;                                          break;
-       case 5: rd->subimtype |= R_JPEG2K_CINE_PRESET|R_JPEG2K_CINE_48FPS;      break;
-       case 6: rd->subimtype |= R_JPEG2K_CINE_PRESET;                                          break;
-       case 7: rd->subimtype |= R_JPEG2K_CINE_PRESET|R_JPEG2K_CINE_48FPS;      break;
+       else {
+               const int depth_ok= BKE_imtype_valid_depths(imf->imtype);
+               const int is_float= ELEM3(imf->imtype, R_IMF_IMTYPE_RADHDR, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER);
+               EnumPropertyItem *item_8bit=  &image_color_depth_items[0];
+               EnumPropertyItem *item_12bit= &image_color_depth_items[1];
+               EnumPropertyItem *item_16bit= &image_color_depth_items[2];
+               EnumPropertyItem *item_32bit= &image_color_depth_items[3];
+               int totitem= 0;
+               EnumPropertyItem *item= NULL;
+               EnumPropertyItem tmp = {0, "", 0, "", ""};
+               if (depth_ok & R_IMF_CHAN_DEPTH_8) {
+                       RNA_enum_item_add(&item, &totitem, item_8bit);
+               }
+               if (depth_ok & R_IMF_CHAN_DEPTH_12) {
+                       RNA_enum_item_add(&item, &totitem, item_12bit);
+               }
+               if (depth_ok & R_IMF_CHAN_DEPTH_16) {
+                       if (is_float) {
+                               tmp= *item_16bit;
+                               tmp.name= "Float (Half)";
+                               RNA_enum_item_add(&item, &totitem, &tmp);
+                       }
+                       else {
+                               RNA_enum_item_add(&item, &totitem, item_16bit);
+                       }
+               }
+               if (depth_ok & R_IMF_CHAN_DEPTH_32) {
+                       if (is_float) {
+                               tmp= *item_32bit;
+                               tmp.name= "Float (Full)";
+                               RNA_enum_item_add(&item, &totitem, &tmp);
+                       }
+                       else {
+                               RNA_enum_item_add(&item, &totitem, item_32bit);
+                       }
+               }
+               RNA_enum_item_end(&item, &totitem);
+               *free= 1;
+               return item;
        }
  }
  
- #ifdef WITH_OPENJPEG
- static void rna_RenderSettings_jpeg2k_preset_set(PointerRNA *ptr, int value)
+ static int rna_SceneRender_file_ext_length(PointerRNA *ptr)
  {
        RenderData *rd= (RenderData*)ptr->data;
-       rd->jp2_preset= value;
-       rna_RenderSettings_jpeg2k_preset_update(rd);
+       char ext[8];
+       ext[0]= '\0';
+       BKE_add_image_extension(ext, rd->im_format.imtype);
+       return strlen(ext);
  }
  
- static void rna_RenderSettings_jpeg2k_depth_set(PointerRNA *ptr, int value)
+ static void rna_SceneRender_file_ext_get(PointerRNA *ptr, char *str)
  {
        RenderData *rd= (RenderData*)ptr->data;
-       rd->jp2_depth= value;
-       rna_RenderSettings_jpeg2k_preset_update(rd);
+       str[0]= '\0';
+       BKE_add_image_extension(str, rd->im_format.imtype);
  }
- #endif
  
  #ifdef WITH_QUICKTIME
  static int rna_RenderSettings_qtcodecsettings_codecType_get(PointerRNA *ptr)
@@@ -924,9 -1066,9 +1068,9 @@@ static void rna_Scene_editmesh_select_m
  
                if(scene->basact) {
                        Mesh *me= get_mesh(scene->basact->object);
 -                      if(me && me->edit_mesh && me->edit_mesh->selectmode != flag) {
 -                              me->edit_mesh->selectmode= flag;
 -                              EM_selectmode_set(me->edit_mesh);
 +                      if(me && me->edit_btmesh && me->edit_btmesh->selectmode != flag) {
 +                              me->edit_btmesh->selectmode= flag;
 +                              EDBM_selectmode_set(me->edit_btmesh);
                        }
                }
        }
@@@ -938,7 -1080,7 +1082,7 @@@ static void rna_Scene_editmesh_select_m
  
        if(scene->basact) {
                me= get_mesh(scene->basact->object);
 -              if(me && me->edit_mesh==NULL)
 +              if(me && me->edit_btmesh==NULL)
                        me= NULL;
        }
  
@@@ -2248,6 -2390,138 +2392,138 @@@ static void rna_def_render_layers(Blend
        RNA_def_property_flag(parm, PROP_REQUIRED|PROP_NEVER_NULL);
  }
  
+ /* use for render output and image save operator,
+  * note: there are some cases where the members act differently when this is
+  * used from a scene, video formats can only be selected for render output
+  * for example, this is checked by seeing if the ptr->id.data is a Scene id */
+ static void rna_def_scene_image_format_data(BlenderRNA *brna)
+ {
+ #ifdef WITH_OPENEXR
+       static EnumPropertyItem exr_codec_items[] = {
+               {R_IMF_EXR_CODEC_NONE, "NONE", 0, "None", ""},
+               {R_IMF_EXR_CODEC_PXR24, "PXR24", 0, "Pxr24 (lossy)", ""},
+               {R_IMF_EXR_CODEC_ZIP, "ZIP", 0, "ZIP (lossless)", ""},
+               {R_IMF_EXR_CODEC_PIZ, "PIZ", 0, "PIZ (lossless)", ""},
+               {R_IMF_EXR_CODEC_RLE, "RLE", 0, "RLE (lossless)", ""},
+               {0, NULL, 0, NULL, NULL}};
+ #endif
+       StructRNA *srna;
+       PropertyRNA *prop;
+       srna= RNA_def_struct(brna, "ImageFormatSettings", NULL);
+       RNA_def_struct_sdna(srna, "ImageFormatData");
+       RNA_def_struct_nested(brna, srna, "Scene");
+       // RNA_def_struct_path_func(srna, "rna_RenderSettings_path"); // no need for the path, its not animated!
+       RNA_def_struct_ui_text(srna, "Image Format", "Settings for image formats");
+       prop= RNA_def_property(srna, "file_format", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "imtype");
+       RNA_def_property_enum_items(prop, image_type_items);
+       RNA_def_property_enum_funcs(prop, NULL, "rna_ImageFormatSettings_file_format_set", "rna_ImageFormatSettings_file_format_itemf");
+       RNA_def_property_ui_text(prop, "File Format", "File format to save the rendered images as");
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+       prop= RNA_def_property(srna, "color_mode", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_bitflag_sdna(prop, NULL, "planes");
+       RNA_def_property_enum_items(prop, image_color_mode_items);
+       RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_ImageFormatSettings_color_mode_itemf");
+       RNA_def_property_ui_text(prop, "Color Mode",
+                                "Choose BW for saving greyscale images, RGB for saving red, green and blue channels, "
+                                "and RGBA for saving red, green, blue and alpha channels");
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+       prop= RNA_def_property(srna, "color_depth", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_bitflag_sdna(prop, NULL, "depth");
+       RNA_def_property_enum_items(prop, image_color_depth_items);
+       RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_ImageFormatSettings_color_depth_itemf");
+       RNA_def_property_ui_text(prop, "Color Depth", "Bit depth per channel");
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+       /* was 'file_quality' */
+       prop= RNA_def_property(srna, "quality", PROP_INT, PROP_PERCENTAGE);
+       RNA_def_property_int_sdna(prop, NULL, "quality");
+       RNA_def_property_range(prop, 0, 100); /* 0 is needed for compression. */
+       RNA_def_property_ui_text(prop, "Quality", "Quality for image formats that support lossy compression");
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+       /* was shared with file_quality */
+       prop= RNA_def_property(srna, "compression", PROP_INT, PROP_PERCENTAGE);
+       RNA_def_property_int_sdna(prop, NULL, "compress");
+       RNA_def_property_range(prop, 0, 100); /* 0 is needed for compression. */
+       RNA_def_property_ui_text(prop, "Compression", "Compression level for formats that support lossless compression");
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+       /* flag */
+       prop= RNA_def_property(srna, "use_zbuffer", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", R_IMF_FLAG_ZBUF);
+       RNA_def_property_ui_text(prop, "Z Buffer", "Save the z-depth per pixel (32 bit unsigned int z-buffer)Save the z-depth per pixel (32 bit unsigned int z-buffer)");
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+       prop= RNA_def_property(srna, "use_preview", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", R_IMF_FLAG_PREVIEW_JPG);
+       RNA_def_property_ui_text(prop, "Preview", "When rendering animations, save JPG preview images in same directory");
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+       /* format spesific */
+ #ifdef WITH_OPENEXR
+       /* OpenEXR */
+       prop= RNA_def_property(srna, "exr_codec", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "exr_codec");
+       RNA_def_property_enum_items(prop, exr_codec_items);
+       RNA_def_property_ui_text(prop, "Codec", "Codec settings for OpenEXR");
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+ #endif
+ #ifdef WITH_OPENJPEG
+       /* Jpeg 2000 */
+       prop= RNA_def_property(srna, "use_jpeg2k_ycc", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "jp2_flag", R_IMF_JP2_FLAG_YCC);
+       RNA_def_property_ui_text(prop, "YCC", "Save luminance-chrominance-chrominance channels instead of RGB colors");
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+       prop= RNA_def_property(srna, "use_jpeg2k_cinema_preset", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "jp2_flag", R_IMF_JP2_FLAG_CINE_PRESET);
+       RNA_def_property_ui_text(prop, "Cinema", "Use Openjpeg Cinema Preset");
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+       prop= RNA_def_property(srna, "use_jpeg2k_cinema_48", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "jp2_flag", R_IMF_JP2_FLAG_CINE_48);
+       RNA_def_property_ui_text(prop, "Cinema (48)", "Use Openjpeg Cinema Preset (48fps)");
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+ #endif
+       /* Cineon and DPX */
+       prop= RNA_def_property(srna, "use_cineon_log", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "cineon_flag", R_CINEON_LOG);
+       RNA_def_property_ui_text(prop, "Log", "Convert to logarithmic color space");
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+       prop= RNA_def_property(srna, "cineon_black", PROP_INT, PROP_NONE);
+       RNA_def_property_int_sdna(prop, NULL, "cineon_black");
+       RNA_def_property_range(prop, 0, 1024);
+       RNA_def_property_ui_text(prop, "B", "Log conversion reference blackpoint");
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+       prop= RNA_def_property(srna, "cineon_white", PROP_INT, PROP_NONE);
+       RNA_def_property_int_sdna(prop, NULL, "cineon_white");
+       RNA_def_property_range(prop, 0, 1024);
+       RNA_def_property_ui_text(prop, "W", "Log conversion reference whitepoint");
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+       prop= RNA_def_property(srna, "cineon_gamma", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "cineon_gamma");
+       RNA_def_property_range(prop, 0.0f, 10.0f);
+       RNA_def_property_ui_text(prop, "G", "Log conversion gamma");
+       RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+ }
  static void rna_def_scene_render_data(BlenderRNA *brna)
  {
        StructRNA *srna;
                {0, "AUTO", 0, "Auto-detect", "Automatically determine the number of threads, based on CPUs"},
                {R_FIXED_THREADS, "FIXED", 0, "Fixed", "Manually determine the number of threads"},
                {0, NULL, 0, NULL, NULL}};
-               
- #ifdef WITH_OPENEXR   
-       static EnumPropertyItem exr_codec_items[] = {
-               {0, "NONE", 0, "None", ""},
-               {1, "PXR24", 0, "Pxr24 (lossy)", ""},
-               {2, "ZIP", 0, "ZIP (lossless)", ""},
-               {3, "PIZ", 0, "PIZ (lossless)", ""},
-               {4, "RLE", 0, "RLE (lossless)", ""},
-               {0, NULL, 0, NULL, NULL}};
- #endif
- #ifdef WITH_OPENJPEG
-       static EnumPropertyItem jp2_preset_items[] = {
-               {0, "NO_PRESET", 0, "No Preset", ""},
-               {1, "CINE_2