svn merge ^/trunk/blender -r43420:43436
authorCampbell Barton <ideasman42@gmail.com>
Tue, 17 Jan 2012 02:20:23 +0000 (02:20 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 17 Jan 2012 02:20:23 +0000 (02:20 +0000)
15 files changed:
1  2 
CMakeLists.txt
source/blender/blenkernel/BKE_blender.h
source/blender/blenkernel/intern/dynamicpaint.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/interface/interface_templates.c
source/blender/editors/mesh/mesh_ops.c
source/blender/editors/object/object_add.c
source/blender/editors/object/object_ops.c
source/blender/editors/screen/screen_ops.c
source/blender/editors/space_view3d/view3d_header.c
source/blender/editors/uvedit/uvedit_ops.c
source/blender/modifiers/intern/MOD_boolean.c
source/blenderplayer/CMakeLists.txt
source/creator/CMakeLists.txt
source/creator/creator.c

diff --combined CMakeLists.txt
index 64ed3e641dff2f5fe99e39f17114d3af1275c320,fb6b946b0c6620248dfb39c221c91cb5eb1aceb5..e7becd06d5388a8d27246b15190fb4b88f45c110
@@@ -129,7 -129,7 +129,7 @@@ option(WITH_BUILDINFO     "Include extr
  option(WITH_IK_ITASC      "Enable ITASC IK solver (only disable for development & for incompatible C++ compilers)" ON)
  option(WITH_FFTW3         "Enable FFTW3 support (Used for smoke and audio effects)" OFF)
  option(WITH_BULLET        "Enable Bullet (Physics Engine)" ON)
 -option(WITH_GAMEENGINE    "Enable Game Engine" ON)
 +option(WITH_GAMEENGINE    "Enable Game Engine" OFF)  # DISABLE FOR BMESH UNTIL NAVMESH IS WORKING
  option(WITH_PLAYER        "Build Player" OFF)
  
  # GHOST Windowing Library Options
@@@ -208,6 -208,9 +208,9 @@@ option(WITH_LZMA          "Enable best 
  # Camera/motion tracking
  option(WITH_LIBMV         "Enable libmv structure from motion library" ON)
  
+ # Mesh boolean lib
+ option(WITH_CARVE         "Enable Carve library to handle mesh boolean operations" ON)
  # Misc
  option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ON)
  option(WITH_RAYOPTIMIZATION   "Enable use of SIMD (SSE) optimizations for the raytracer" ON)
@@@ -300,9 -303,13 +303,13 @@@ if(WITH_PYTHON_MODULE
        set(WITH_HEADLESS ON)
  endif()
  
- # auto enable openimageio and boost for cycles
+ # auto enable openimageio for cycles
  if(WITH_CYCLES)
        set(WITH_OPENIMAGEIO ON)
+ endif()
+ # auto enable boost for cycles and carve
+ if(WITH_CYCLES OR WITH_CARVE)
        set(WITH_BOOST ON)
  endif()
  
@@@ -1085,16 -1092,28 +1092,28 @@@ elseif(APPLE
        endif()
  
        if(WITH_PYTHON)
-               # we use precompiled libraries for py 3.2 and up by default
+               if(NOT WITH_PYTHON_MODULE)
+                       # we use precompiled libraries for py 3.2 and up by default
  
-               # normally cached but not since we include them with blender
-               set(PYTHON_VERSION 3.2)
-               set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}")
-               # set(PYTHON_BINARY "${LIBDIR}/python/bin/python${PYTHON_VERSION}") # not used yet
-               set(PYTHON_LIBRARY python${PYTHON_VERSION})
-               set(PYTHON_LIBPATH "${LIBDIR}/python/lib/python${PYTHON_VERSION}")
-               # set(PYTHON_LINKFLAGS "-u _PyMac_Error")  # won't  build with this enabled
+                       # normally cached but not since we include them with blender
+                       set(PYTHON_VERSION 3.2)
+                       set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}")
+                       # set(PYTHON_BINARY "${LIBDIR}/python/bin/python${PYTHON_VERSION}") # not used yet
+                       set(PYTHON_LIBRARY python${PYTHON_VERSION})
+                       set(PYTHON_LIBPATH "${LIBDIR}/python/lib/python${PYTHON_VERSION}")
+                       # set(PYTHON_LINKFLAGS "-u _PyMac_Error")  # won't  build with this enabled
+               else()
+                       # module must be compiled against Python framework
  
+                       # normally cached but not since we include them with blender
+                       set(PYTHON_VERSION 3.2)
+                       set(PYTHON_INCLUDE_DIR "/Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}/include/python${PYTHON_VERSION}m")
+                       set(PYTHON_BINARY "/Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}/bin/python${PYTHON_VERSION}")
+                       #set(PYTHON_LIBRARY python${PYTHON_VERSION})
+                       set(PYTHON_LIBPATH "/Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}/lib/python${PYTHON_VERSION}/config-3.2m")
+                       #set(PYTHON_LINKFLAGS "-u _PyMac_Error -framework Python")  # won't  build with this enabled
+               endif()
+               
                # uncached vars
                set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}")
                set(PYTHON_LIBRARIES  "${PYTHON_LIBRARY}")
                set(PLATFORM_LINKFLAGS "-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Carbon -framework AGL -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework QuickTime")
                set(WITH_INPUT_NDOF OFF)  # unsupported
        endif()
+       
+       if(WITH_PYTHON_MODULE)
+               set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}/python")# force cmake to link right framework
+       endif()
+       
        if(WITH_OPENCOLLADA)
                set(OPENCOLLADA ${LIBDIR}/opencollada)
  
index af6f4b88f4b7993979414e7c37cf163278fa59bf,f24687e0fc9bf0ce9a535fba4c59daf5d4ce5830..98fe6e15e67caa93f7f9396a7974c9eb64f248a1
@@@ -42,7 -42,7 +42,7 @@@ extern "C" 
   * and keep comment above the defines.
   * Use STRINGIFY() rather than defining with quotes */
  #define BLENDER_VERSION                       261
- #define BLENDER_SUBVERSION            2
+ #define BLENDER_SUBVERSION            3
  
  #define BLENDER_MINVERSION            250
  #define BLENDER_MINSUBVERSION 0
@@@ -90,7 -90,6 +90,7 @@@ extern void BKE_reset_undo(void)
  extern char *BKE_undo_menu_string(void);
  extern void BKE_undo_number(struct bContext *C, int nr);
  extern const char *BKE_undo_get_name(int nr, int *active);
 +void BKE_undo_save(char *fname);
  extern void BKE_undo_save_quit(void);
  extern struct Main *BKE_undo_get_main(struct Scene **scene);
  
index b7acede4b7b0e1e0d54e103b25e427767baff9a2,50f423280437a36eb05b44c6e7a548dbc53a252c..944de316eb153c521270347b3c3d76bee8b7a565
@@@ -101,9 -101,10 +101,10 @@@ static int neighY[8] = {0,1,1, 1, 0,-1,
  #define EFF_MOVEMENT_PER_FRAME 0.05f
  /* initial wave time factor */
  #define WAVE_TIME_FAC (1.0f/24.f)
- #define WAVE_INIT_SIZE 5.0f
+ #define CANVAS_REL_SIZE 5.0f
  /* drying limits */
  #define MIN_WETNESS 0.001f
+ #define MAX_WETNESS 5.0f
  /* dissolve macro */
  #define VALUE_DISSOLVE(VALUE, TIME, SCALE, LOG) (VALUE) = (LOG) ? (VALUE) * (pow(MIN_WETNESS,1.0f/(1.2f*((float)(TIME))/(SCALE)))) : (VALUE) - 1.0f/(TIME)*(SCALE)
  
@@@ -422,15 -423,31 +423,31 @@@ static void blendColors(float t_color[3
        result[3] = f_alpha;
  }
  
- /* assumes source alpha > 0.0f or results NaN colors */
- static void mixColors(float *t_color, float t_alpha, float *s_color, float s_alpha)
+ /* Mix two alpha weighed colors by a defined ratio. output is saved at a_color */
+ static float mixColors(float a_color[3], float a_weight, float b_color[3], float b_weight, float ratio)
  {
-       float factor = (s_alpha<t_alpha) ? 1.0f : t_alpha/s_alpha;
+       float weight_ratio, factor;
+       if (b_weight) {
+               /* if first value has no weight just use b_color */
+               if (!a_weight) {
+                       copy_v3_v3(a_color, b_color);
+                       return b_weight*ratio;
+               }
+               weight_ratio = b_weight/(a_weight+b_weight);
+       }
+       else return a_weight*(1.0f-ratio);
  
-       /* set initial color depending on existing alpha */
-       interp_v3_v3v3(t_color, s_color, t_color, factor);
+       /* calculate final interpolation factor */
+       if (ratio<=0.5f) {
+               factor = weight_ratio*(ratio*2.0f);
+       }
+       else {
+               ratio = (ratio*2.0f - 1.0f);
+               factor = weight_ratio*(1.0f-ratio) + ratio;
+       }
        /* mix final color */
-       interp_v3_v3v3(t_color, t_color, s_color, s_alpha);
+       interp_v3_v3v3(a_color, a_color, b_color, factor);
+       return (1.0f-factor)*a_weight + factor*b_weight;
  }
  
  /* set "ignore cache" flag for all caches on this object */
@@@ -617,6 -634,12 +634,12 @@@ static void boundInsert(Bounds3D *b, fl
        }
  }
  
+ float getSurfaceDimension(PaintSurfaceData *sData)
+ {
+       Bounds3D *mb = &sData->bData->mesh_bounds;
+       return MAX3((mb->max[0]-mb->min[0]), (mb->max[1]-mb->min[1]), (mb->max[2]-mb->min[2]));
+ }
  static void freeGrid(PaintSurfaceData *data)
  {
        PaintBakeData *bData = data->bData;
@@@ -959,17 -982,21 +982,21 @@@ struct DynamicPaintSurface *dynamicPain
  
        /* Set initial values */
        surface->flags = MOD_DPAINT_ANTIALIAS | MOD_DPAINT_MULALPHA | MOD_DPAINT_DRY_LOG | MOD_DPAINT_DISSOLVE_LOG |
-                                        MOD_DPAINT_ACTIVE | MOD_DPAINT_PREVIEW | MOD_DPAINT_OUT1;
+                                        MOD_DPAINT_ACTIVE | MOD_DPAINT_PREVIEW | MOD_DPAINT_OUT1 | MOD_DPAINT_USE_DRYING;
        surface->effect = 0;
        surface->effect_ui = 1;
  
        surface->diss_speed = 250;
        surface->dry_speed = 500;
+       surface->color_dry_threshold = 1.0f;
        surface->depth_clamp = 0.0f;
        surface->disp_factor = 1.0f;
        surface->disp_type = MOD_DPAINT_DISP_DISPLACE;
        surface->image_fileformat = MOD_DPAINT_IMGFORMAT_PNG;
  
+       surface->influence_scale = 1.0f;
+       surface->radius_scale = 1.0f;
        surface->init_color[0] = 1.0f;
        surface->init_color[1] = 1.0f;
        surface->init_color[2] = 1.0f;
@@@ -1233,9 -1260,9 +1260,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++) {
@@@ -1321,8 -1348,8 +1348,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[MAX_CUSTOMDATA_LAYER_NAME];
  
                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++) {
@@@ -1508,7 -1535,7 +1535,7 @@@ static int dynamicPaint_checkSurfaceDat
  
  
  /* apply displacing vertex surface to the derived mesh */
- static void dynamicPaint_applySurfaceDisplace(DynamicPaintSurface *surface, DerivedMesh *result, int update_normals)
+ static void dynamicPaint_applySurfaceDisplace(DynamicPaintSurface *surface, DerivedMesh *result)
  {
        PaintSurfaceData *sData = surface->data;
  
                        mvert[i].co[2] -= normal[2]*val;
                }
        }
-       else return;
-       if (update_normals)
-               CDDM_calc_normals_mapping(result);
  }
  
  /*
@@@ -1544,11 -1567,12 +1567,12 @@@ static struct DerivedMesh *dynamicPaint
                                                         Object *ob,
                                                         DerivedMesh *dm)
  {     
 -      DerivedMesh *result = CDDM_copy(dm);
 +      DerivedMesh *result = CDDM_copy(dm, 0);
  
        if(pmd->canvas && !(pmd->canvas->flags & MOD_DPAINT_BAKING)) {
  
                DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
+               int update_normals = 0;
                pmd->canvas->flags &= ~MOD_DPAINT_PREVIEW_READY;
  
                /* loop through surfaces */
                                        /* vertex color paint */
                                        if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
  
 -                                              MFace *mface = result->getFaceArray(result);
 -                                              int numOfFaces = result->getNumFaces(result);
                                                int i;
                                                PaintPoint* pPoint = (PaintPoint*)sData->type_data;
 -                                              MCol *col;
 +                                              MLoopCol *col = NULL;
 +                                              MLoop *mloop = CDDM_get_loops(result);
 +                                              int totloop = result->numLoopData;
  
                                                /* paint is stored on dry and wet layers, so mix final color first */
                                                float *fcolor = MEM_callocN(sizeof(float)*sData->total_points*4, "Temp paint color");
                                                }
  
                                                /* viewport preview */
 -                                              if (surface->flags & MOD_DPAINT_PREVIEW) {
 -                                                      /* Save preview results to weight layer, to be
 +                                              if (0 && surface->flags & MOD_DPAINT_PREVIEW) {
 +                                                      MPoly *mp = CDDM_get_polys(result);
 +                                                      int totpoly = result->numPolyData;
 +
 +                                                      /* Save preview results to weight layer to be
                                                        *   able to share same drawing methods */
 -                                                      col = result->getFaceDataArray(result, CD_WEIGHT_MCOL);
 -                                                      if (!col) col = CustomData_add_layer(&result->faceData, CD_WEIGHT_MCOL, CD_CALLOC, NULL, numOfFaces);
 +                                                      col = CustomData_get_layer(&dm->loopData, CD_WEIGHT_MLOOPCOL);
 +                                                      if (!col) col = CustomData_add_layer(&dm->loopData, CD_WEIGHT_MLOOPCOL, CD_CALLOC, NULL, totloop);
  
                                                        if (col) {
                                                                #pragma omp parallel for schedule(static)
 -                                                              for (i=0; i<numOfFaces; i++) {
 +                                                              for (i=0; i<totpoly; i++) {
                                                                        int j=0;
 -                                                                      Material *material = give_current_material(ob, mface[i].mat_nr+1);
 +                                                                      Material *material = give_current_material(ob, mp[i].mat_nr+1);
  
 -                                                                      for (; j<((mface[i].v4)?4:3); j++) {
 -                                                                              int index = (j==0)?mface[i].v1: (j==1)?mface[i].v2: (j==2)?mface[i].v3: mface[i].v4;
 +                                                                      for (; j<mp[i].totloop; j++) {
 +                                                                              int l_index = mp[i].loopstart + j;
 +                                                                              int v_index = mloop[l_index].v;
  
                                                                                if (surface->preview_id == MOD_DPAINT_SURFACE_PREV_PAINT) {
                                                                                        float c[3];
 -                                                                                      index *= 4;
 +                                                                                      v_index *= 4;
  
                                                                                        /* Apply material color as base vertex color for preview */
 -                                                                                      col[i*4+j].a = 255;
 +                                                                                      col[l_index].a = 255;
                                                                                        if (material) {
                                                                                                c[0] = material->r;
                                                                                                c[1] = material->g;
                                                                                                c[2] = 0.65f;
                                                                                        }
                                                                                        /* mix surface color */
 -                                                                                      interp_v3_v3v3(c, c, &fcolor[index], fcolor[index+3]);
 +                                                                                      interp_v3_v3v3(c, c, &fcolor[v_index], fcolor[v_index+3]);
  
 -                                                                                      col[i*4+j].r = FTOCHAR(c[2]);
 -                                                                                      col[i*4+j].g = FTOCHAR(c[1]);
 -                                                                                      col[i*4+j].b = FTOCHAR(c[0]);
 +                                                                                      col[l_index].r = FTOCHAR(c[2]);
 +                                                                                      col[l_index].g = FTOCHAR(c[1]);
 +                                                                                      col[l_index].b = FTOCHAR(c[0]);
                                                                                }
                                                                                else {
 -                                                                                      col[i*4+j].a = 255;
 -                                                                                      col[i*4+j].r =
 -                                                                                      col[i*4+j].g =
 -                                                                                      col[i*4+j].b = FTOCHAR(pPoint[index].wetness);
 +                                                                                      col[l_index].a = 255;
 +                                                                                      col[l_index].r =
 +                                                                                      col[l_index].g =
 +                                                                                      col[l_index].b = FTOCHAR(pPoint[v_index].wetness);
                                                                                }
                                                                        }
                                                                }
                                                /* save layer data to output layer */
  
                                                /* paint layer */
 -                                              col = CustomData_get_layer_named(&result->faceData, CD_MCOL, surface->output_name);
 +                                              col = CustomData_get_layer_named(&result->loopData, CD_MLOOPCOL, surface->output_name);
                                                /* if output layer is lost from a constructive modifier, re-add it */
                                                if (!col && dynamicPaint_outputLayerExists(surface, ob, 0))
 -                                                      col = CustomData_add_layer_named(&result->faceData, CD_MCOL, CD_CALLOC, NULL, numOfFaces, surface->output_name);
 +                                                      col = CustomData_add_layer_named(&result->loopData, CD_MLOOPCOL, CD_CALLOC, NULL, totloop, surface->output_name);
                                                /* apply color */
                                                if (col) {
                                                        #pragma omp parallel for schedule(static)
 -                                                      for (i=0; i<numOfFaces; i++) {
 -                                                              int j=0;
 -                                                              for (; j<((mface[i].v4)?4:3); j++) {
 -                                                                      int index = (j==0)?mface[i].v1: (j==1)?mface[i].v2: (j==2)?mface[i].v3: mface[i].v4;
 -                                                                      index *= 4;
 -
 -                                                                      col[i*4+j].a = FTOCHAR(fcolor[index+3]);
 -                                                                      col[i*4+j].r = FTOCHAR(fcolor[index+2]);
 -                                                                      col[i*4+j].g = FTOCHAR(fcolor[index+1]);
 -                                                                      col[i*4+j].b = FTOCHAR(fcolor[index]);
 -                                                              }
 +                                                      for (i=0; i<totloop; i++) {
 +                                                              int index = mloop[i].v*4;
 +                                                              col[i].a = FTOCHAR(fcolor[index+3]);
 +                                                              col[i].r = FTOCHAR(fcolor[index+2]);
 +                                                              col[i].g = FTOCHAR(fcolor[index+1]);
 +                                                              col[i].b = FTOCHAR(fcolor[index]);
                                                        }
                                                }
                                                
                                                MEM_freeN(fcolor);
  
                                                /* wet layer */
 -                                              col = CustomData_get_layer_named(&result->faceData, CD_MCOL, surface->output_name2);
 +                                              col = CustomData_get_layer_named(&result->loopData, CD_MLOOPCOL, surface->output_name2);
                                                /* if output layer is lost from a constructive modifier, re-add it */
                                                if (!col && dynamicPaint_outputLayerExists(surface, ob, 1))
 -                                                      col = CustomData_add_layer_named(&result->faceData, CD_MCOL, CD_CALLOC, NULL, numOfFaces, surface->output_name2);
 +                                                      col = CustomData_add_layer_named(&result->loopData, CD_MLOOPCOL, CD_CALLOC, NULL, totloop, surface->output_name2);
                                                /* apply color */
                                                if (col) {
                                                        #pragma omp parallel for schedule(static)
 -                                                      for (i=0; i<numOfFaces; i++) {
 -                                                              int j=0;
 -
 -                                                              for (; j<((mface[i].v4)?4:3); j++) {
 -                                                                      int index = (j==0)?mface[i].v1: (j==1)?mface[i].v2: (j==2)?mface[i].v3: mface[i].v4;
 -                                                                      col[i*4+j].a = 255;
 -                                                                      col[i*4+j].r =
 -                                                                      col[i*4+j].g =
 -                                                                      col[i*4+j].b = FTOCHAR(pPoint[index].wetness);
 -                                                              }
 +                                                      for (i=0; i<totloop; i++) {
 +                                                              int index = mloop[i].v;
 +                                                              col[i].a = 255;
 +                                                              col[i].r =
 +                                                              col[i].g =
 +                                                              col[i].b = FTOCHAR(pPoint[index].wetness);
                                                        }
                                                }
                                        }
                                        /* vertex group paint */
                                        else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
 +                                              MLoop *mloop = CDDM_get_loops(result);
 +                                              int totloop = result->numLoopData;
 +
                                                int defgrp_index = defgroup_name_index(ob, surface->output_name);
                                                MDeformVert *dvert = result->getVertDataArray(result, CD_MDEFORMVERT);
                                                float *weight = (float*)sData->type_data;
 +
                                                /* viewport preview */
 -                                              if (surface->flags & MOD_DPAINT_PREVIEW) {
 -                                                      /* Save preview results to weight layer, to be
 +                                              if (0 && surface->flags & MOD_DPAINT_PREVIEW) {
 +                                                      /* Save preview results to weight layer to be
                                                        *   able to share same drawing methods */
 -                                                      MFace *mface = result->getFaceArray(result);
 -                                                      int numOfFaces = result->getNumFaces(result);
                                                        int i;
 -                                                      MCol *col = result->getFaceDataArray(result, CD_WEIGHT_MCOL);
 -                                                      if (!col) col = CustomData_add_layer(&result->faceData, CD_WEIGHT_MCOL, CD_CALLOC, NULL, numOfFaces);
 +                                                      MLoopCol *col = CustomData_get_layer(&dm->loopData, CD_WEIGHT_MLOOPCOL);
 +                                                      if (!col) col = CustomData_add_layer(&dm->loopData, CD_WEIGHT_MLOOPCOL, CD_CALLOC, NULL, totloop);
  
                                                        if (col) {
 +                                                              printf("doint weight preview\n");
                                                                #pragma omp parallel for schedule(static)
 -                                                              for (i=0; i<numOfFaces; i++) {
 +                                                              for (i=0; i<totloop; i++) {
                                                                        float temp_color[3];
 -                                                                      int j=0;
 -                                                                      for (; j<((mface[i].v4)?4:3); j++) {
 -                                                                              int index = (j==0)?mface[i].v1: (j==1)?mface[i].v2: (j==2)?mface[i].v3: mface[i].v4;
 -
 -                                                                              weight_to_rgb(temp_color, weight[index]);
 -                                                                              col[i*4+j].r = FTOCHAR(temp_color[2]);
 -                                                                              col[i*4+j].g = FTOCHAR(temp_color[1]);
 -                                                                              col[i*4+j].b = FTOCHAR(temp_color[0]);
 -                                                                              col[i*4+j].a = 255;
 -                                                                      }
 +                                                                      weight_to_rgb(temp_color, weight[mloop[i].v]);
 +
 +                                                                      col[i].a = 255;
 +                                                                      col[i].r = FTOCHAR(temp_color[2]);
 +                                                                      col[i].g = FTOCHAR(temp_color[1]);
 +                                                                      col[i].b = FTOCHAR(temp_color[0]);
                                                                }
                                                                pmd->canvas->flags |= MOD_DPAINT_PREVIEW_READY;
                                                        }
                                                        normal_short_to_float_v3(normal, mvert[i].no);
                                                        madd_v3_v3fl(mvert[i].co, normal, wPoint[i].height);
                                                }
-                                               CDDM_calc_normals_mapping(result);
+                                               update_normals = 1;
                                        }
  
                                        /* displace */
-                                       dynamicPaint_applySurfaceDisplace(surface, result, 1);
+                                       if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) {
+                                               dynamicPaint_applySurfaceDisplace(surface, result);
+                                               update_normals = 1;
+                                       }
                                }
                        }
                }
 -                      CDDM_calc_normals(result);
+               if (update_normals)
++                      CDDM_calc_normals_mapping(result);
        }
        /* 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);
        }
  
        return result;
@@@ -1772,7 -1808,7 +1802,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);
  }
  
  /*
@@@ -1926,8 -1962,8 +1956,8 @@@ static int dynamicPaint_findNeighbourPi
        *       TODO: Implement something more accurate / optimized?
        */
        {
 -              int numOfFaces = dm->getNumFaces(dm);
 -              MFace *mface = dm->getFaceArray(dm);
 +              int numOfFaces = dm->getNumTessFaces(dm);
 +              MFace *mface = dm->getTessFaceArray(dm);
                MTFace *tface =  CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
  
                /* Get closest edge to that subpixel on UV map  */
@@@ -2093,8 -2129,8 +2123,8 @@@ int dynamicPaint_createUVSurface(Dynami
        if (!dm) return setError(canvas, "Canvas mesh not updated.");
        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);
 +      numOfFaces = dm->getNumPolys(dm);
 +      mface = dm->getTessFaceArray(dm);
  
        /* get uv map */
        CustomData_validate_layer_name(&dm->faceData, CD_MTFACE, surface->uvlayer_name, uvname);
@@@ -2568,14 -2604,8 +2598,8 @@@ void dynamicPaint_outputSurfaceImage(Dy
                        if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
                                PaintPoint *point = &((PaintPoint*)sData->type_data)[index];
  
-                               ibuf->rect_float[pos]   = point->color[0];
-                               ibuf->rect_float[pos+1] = point->color[1];
-                               ibuf->rect_float[pos+2] = point->color[2];
-                               /* mix wet layer */
-                               if (point->e_alpha) mixColors(&ibuf->rect_float[pos], point->alpha, point->e_color, point->e_alpha);
-                               /* use highest alpha    */
-                               ibuf->rect_float[pos+3] = (point->e_alpha > point->alpha) ? point->e_alpha : point->alpha;
+                               /* blend wet and dry layers */
+                               blendColors(point->color, point->alpha, point->e_color, point->e_alpha, &ibuf->rect_float[pos]);
  
                                /* Multiply color by alpha if enabled   */
                                if (surface->flags & MOD_DPAINT_MULALPHA) {
@@@ -2692,7 -2722,7 +2716,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) {
@@@ -2906,7 -2936,13 +2930,13 @@@ static void dynamicPaint_updatePointDat
                                                                                 float paint[3], float influence, float depth, float vel_factor, float timescale)
  {
                PaintSurfaceData *sData = surface->data;
-               float strength = influence * brush->alpha;
+               float strength;
+               /* apply influence scale */
+               influence *= surface->influence_scale;
+               depth *= surface->influence_scale;
+               strength = influence * brush->alpha;
                CLAMP(strength, 0.0f, 1.0f);
  
                /* Sample velocity colorband if required */
  }
  
  /* checks whether surface and brush bounds intersect depending on brush type */
- static int meshBrush_boundsIntersect(Bounds3D *b1, Bounds3D *b2, DynamicPaintBrushSettings *brush)
+ static int meshBrush_boundsIntersect(Bounds3D *b1, Bounds3D *b2, DynamicPaintBrushSettings *brush, float brush_radius)
  {
        if (brush->collision == MOD_DPAINT_COL_VOLUME)
                return boundsIntersect(b1, b2);
        else if (brush->collision == MOD_DPAINT_COL_DIST || brush->collision == MOD_DPAINT_COL_VOLDIST)
-               return boundsIntersectDist(b1, b2, brush->paint_distance);
+               return boundsIntersectDist(b1, b2, brush_radius);
        else return 1;
  }
  
@@@ -3018,7 -3054,7 +3048,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);
        numOfVerts_p = dm_p->getNumVerts(dm_p);
        mvert_p = dm_p->getVertArray(dm_p);
        copy_m4_m4(prev_obmat, ob->obmat);
@@@ -3117,14 -3153,15 +3147,15 @@@ static int dynamicPaint_paintMesh(Dynam
        {
                BVHTreeFromMesh treeData = {0};
                float avg_brushNor[3] = {0.0f};
+               float brush_radius = brush->paint_distance * surface->radius_scale;
                int numOfVerts;
                int ii;
                Bounds3D mesh_bb = {0};
                VolumeGrid *grid = bData->grid;
  
 -              dm = CDDM_copy(brush->dm);
 +              dm = CDDM_copy(brush->dm, 0);
                mvert = dm->getVertArray(dm);
 -              mface = dm->getFaceArray(dm);
 +              mface = dm->getTessFaceArray(dm);
                numOfVerts = dm->getNumVerts(dm);
  
                /*      Transform collider vertices to global space
                }
  
                /* check bounding box collision */
-               if(grid && meshBrush_boundsIntersect(&grid->grid_bounds, &mesh_bb, brush))
+               if(grid && meshBrush_boundsIntersect(&grid->grid_bounds, &mesh_bb, brush, brush_radius))
                /* Build a bvh tree from transformed vertices   */
                if (bvhtree_from_mesh_faces(&treeData, dm, 0.0f, 4, 8))
                {
                                int id;
  
                                /* check grid cell bounding box */
-                               if (!grid->s_num[c_index] || !meshBrush_boundsIntersect(&grid->bounds[c_index], &mesh_bb, brush))
+                               if (!grid->s_num[c_index] || !meshBrush_boundsIntersect(&grid->bounds[c_index], &mesh_bb, brush, brush_radius))
                                        continue;
  
                                /* loop through cell points and process brush */
                                                hit.index = -1;
                                                hit.dist = 9999;
                                                nearest.index = -1;
-                                               nearest.dist = brush->paint_distance * brush->paint_distance; /* find_nearest uses squared distance */
+                                               nearest.dist = brush_radius * brush_radius; /* find_nearest uses squared distance */
  
                                                /* Check volume collision       */
                                                if (brush->collision == MOD_DPAINT_COL_VOLUME || brush->collision == MOD_DPAINT_COL_VOLDIST)
                                                        /* If pure distance proximity, find the nearest point on the mesh */
                                                        if (brush->collision != MOD_DPAINT_COL_DIST || !(brush->flags & MOD_DPAINT_PROX_PROJECT)) {
                                                                if (BLI_bvhtree_find_nearest(treeData.tree, ray_start, &nearest, mesh_faces_nearest_point_dp, &treeData) != -1) {
-                                                                       proxDist = sqrt(nearest.dist);
+                                                                       proxDist = sqrtf(nearest.dist);
                                                                        copy_v3_v3(hitCo, nearest.co);
                                                                        hQuad = (nearest.no[0] == 1.0f);
                                                                        face = nearest.index;
                                                                        proj_ray[2] = 1.0f;
                                                                }
                                                                hit.index = -1;
-                                                               hit.dist = brush->paint_distance;
+                                                               hit.dist = brush_radius;
  
                                                                /* Do a face normal directional raycast, and use that distance  */
                                                                if(BLI_bvhtree_ray_cast(treeData.tree, ray_start, proj_ray, 0.0f, &hit, mesh_faces_spherecast_dp, &treeData) != -1)
                                                        }
  
                                                        /* If a hit was found, calculate required values        */
-                                                       if (proxDist >= 0.0f && proxDist <= brush->paint_distance) {
-                                                               proximity_factor = proxDist / brush->paint_distance;
+                                                       if (proxDist >= 0.0f && proxDist <= brush_radius) {
+                                                               proximity_factor = proxDist / brush_radius;
                                                                CLAMP(proximity_factor, 0.0f, 1.0f);
                                                                if (!inner_proximity)
                                                                        proximity_factor = 1.0f - proximity_factor;
@@@ -3508,8 -3545,8 +3539,8 @@@ static int dynamicPaint_paintParticles(
        int invalidParticles = 0;
        int p = 0;
  
-       float solidradius = (brush->flags & MOD_DPAINT_PART_RAD) ? psys->part->size : brush->particle_radius;
-       float smooth = brush->particle_smooth;
+       float solidradius = surface->radius_scale*((brush->flags & MOD_DPAINT_PART_RAD) ? psys->part->size : brush->particle_radius);
+       float smooth = brush->particle_smooth*surface->radius_scale;
  
        float range = solidradius + smooth;
        float particle_timestep = 0.04f * part->timetweak;
@@@ -3738,6 -3775,7 +3769,7 @@@ static int dynamicPaint_paintSinglePoin
                                           Object *brushOb, BrushMaterials *bMats, Scene *scene, float timescale)
  {
        int index;
+       float brush_radius = brush->paint_distance * surface->radius_scale;
        PaintSurfaceData *sData = surface->data;
        PaintBakeData *bData = sData->bData;
        Vec3f brushVel;
                float colorband[4] = {0.0f};
                float strength;
  
-               if (distance>brush->paint_distance) continue;
+               if (distance > brush_radius) continue;
  
                /* Smooth range or color ramp   */
                if (brush->proximity_falloff == MOD_DPAINT_PRFALL_SMOOTH ||
                        brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP) {
                        
-                       strength = 1.0f - distance / brush->paint_distance;
+                       strength = 1.0f - distance / brush_radius;
                        CLAMP(strength, 0.0f, 1.0f);
                }
                else strength = 1.0f;
                        else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
                                         surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
                                 /* get displace depth  */
-                               float disp_intersect = (1.0f - sqrtf((brush->paint_distance-distance) / brush->paint_distance)) * brush->paint_distance;
-                               depth = (brush->paint_distance - disp_intersect) / bData->bNormal[index].normal_scale;
+                               float disp_intersect = (1.0f - sqrtf((brush_radius-distance) / brush_radius)) * brush_radius;
+                               depth = (brush_radius - disp_intersect) / bData->bNormal[index].normal_scale;
                                if (depth<0.0f) depth = 0.0f;
                        }
                        dynamicPaint_updatePointData(surface, index, brush, paintColor, strength, depth, velocity_val, timescale);
@@@ -3930,7 -3968,7 +3962,7 @@@ void surface_determineForceTargetPoints
        if (closest_id[1] != -1) {
                float force_proj[3];
                float tangent[3];
-               float neigh_diff = acos(dot_v3v3(bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir));
+               float neigh_diff = acosf(dot_v3v3(bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir));
                float force_intersect;
                float temp;
  
@@@ -4002,7 -4040,6 +4034,6 @@@ static void dynamicPaint_doSmudge(Dynam
                                if (n_index != -1 && closest_d[i]>0.0f) {
                                        float dir_dot = closest_d[i], dir_factor;
                                        float speed_scale = eff_scale*smudge_str/bNeighs[n_index].dist;
-                                       float mix;
                                        PaintPoint *ePoint = &((PaintPoint*)sData->type_data)[sData->adj_data->n_target[n_index]];
  
                                        /* just skip if angle is too extreme */
                                        if (dir_factor > brush->smudge_strength) dir_factor = brush->smudge_strength;
  
                                        /* mix new color and alpha */
-                                       mix = dir_factor*pPoint->alpha;
-                                       if (mix) mixColors(ePoint->color, ePoint->alpha, pPoint->color, mix);
+                                       mixColors(ePoint->color, ePoint->alpha, pPoint->color, pPoint->alpha, dir_factor);
                                        ePoint->alpha = ePoint->alpha*(1.0f-dir_factor) + pPoint->alpha*dir_factor;
  
                                        /* smudge "wet layer" */
-                                       mix = dir_factor*pPoint->e_alpha;
-                                       if (mix) mixColors(ePoint->e_color, ePoint->e_alpha, pPoint->e_color, mix);
+                                       mixColors(ePoint->e_color, ePoint->e_alpha, pPoint->e_color, pPoint->e_alpha, dir_factor);
                                        ePoint->e_alpha = ePoint->e_alpha*(1.0f-dir_factor) + pPoint->e_alpha*dir_factor;
                                        pPoint->wetness *= (1.0f-dir_factor);
                                }
@@@ -4035,7 -4070,7 +4064,7 @@@ static int dynamicPaint_prepareEffectSt
  {
        double average_force = 0.0f;
        float shrink_speed=0.0f, spread_speed=0.0f;
-       float fastest_effect;
+       float fastest_effect, avg_dist;
        int steps;
        PaintSurfaceData *sData = surface->data;
        PaintBakeData *bData = sData->bData;
                shrink_speed = surface->shrink_speed;
  
        fastest_effect = MAX3(spread_speed, shrink_speed, average_force);
+       avg_dist = bData->average_dist*CANVAS_REL_SIZE/getSurfaceDimension(sData);
  
-       steps = (int)ceil(1.5f*EFF_MOVEMENT_PER_FRAME*fastest_effect/bData->average_dist*timescale);
-       CLAMP(steps, 1, 14);
+       steps = (int)ceil(1.5f*EFF_MOVEMENT_PER_FRAME*fastest_effect/avg_dist*timescale);
+       CLAMP(steps, 1, 20);
  
        return steps;
  }
@@@ -4126,6 -4162,7 +4156,7 @@@ static void dynamicPaint_doEffectStep(D
  {
        PaintSurfaceData *sData = surface->data;
        BakeNeighPoint *bNeighs = sData->bData->bNeighs;
+       float distance_scale = getSurfaceDimension(sData)/CANVAS_REL_SIZE;
        int index;
        timescale /= steps;
  
        *       Spread Effect
        */
        if (surface->effect & MOD_DPAINT_EFFECT_DO_SPREAD)  {
-               float eff_scale = EFF_MOVEMENT_PER_FRAME*surface->spread_speed*timescale;
+               float eff_scale = distance_scale*EFF_MOVEMENT_PER_FRAME*surface->spread_speed*timescale;
  
                /* Copy current surface to the previous points array to read unmodified values  */
                memcpy(prevPoint, sData->type_data, sData->total_points*sizeof(struct PaintPoint));
                {
                        int i;
                        int numOfNeighs = sData->adj_data->n_num[index];
-                       float totalAlpha = 0.0f;
                        PaintPoint *pPoint = &((PaintPoint*)sData->type_data)[index];
  
                        /*  Only reads values from the surface copy (prevPoint[]),
                        /*      Loop through neighbouring points        */
                        for (i=0; i<numOfNeighs; i++) {
                                int n_index = sData->adj_data->n_index[index]+i;
-                               float w_factor, alphaAdd = 0.0f;
+                               float w_factor /* , p_alpha = pPoint->e_alpha */ /* UNUSED */;
                                PaintPoint *ePoint = &prevPoint[sData->adj_data->n_target[n_index]];
                                float speed_scale = (bNeighs[n_index].dist<eff_scale) ? 1.0f : eff_scale/bNeighs[n_index].dist;
-                               float color_mix = (MIN2(ePoint->wetness, pPoint->wetness))*0.25f*surface->color_spread_speed;
-                               totalAlpha += ePoint->e_alpha;
+                               float color_mix = (MIN3(ePoint->wetness, pPoint->wetness, 1.0f))*0.25f*surface->color_spread_speed;
  
                                /* do color mixing */
-                               if (color_mix > MIN_WETNESS) mixColors(pPoint->e_color, pPoint->e_alpha, ePoint->e_color, color_mix);
-                               /* Check if neighbouring point has higher wetness,
-                               *  if so, add it's wetness to this point as well*/
-                               if (ePoint->wetness <= pPoint->wetness) continue;
-                               w_factor = ePoint->wetness/numOfNeighs * (ePoint->wetness - pPoint->wetness) * speed_scale;
-                               if (w_factor <= MIN_WETNESS) continue;
-                               if (ePoint->e_alpha > pPoint->e_alpha) {
-                                       alphaAdd = ePoint->e_alpha/numOfNeighs * (ePoint->wetness*ePoint->e_alpha - pPoint->wetness*pPoint->e_alpha) * speed_scale;
-                               }
-                               /* mix new color */
-                               mixColors(pPoint->e_color, pPoint->e_alpha, ePoint->e_color, w_factor);
+                               if (color_mix) mixColors(pPoint->e_color, pPoint->e_alpha, ePoint->e_color, ePoint->e_alpha, color_mix);
  
-                               pPoint->e_alpha += alphaAdd;
-                               pPoint->wetness += w_factor;
+                               /* Only continue if surrounding point has higher wetness */
+                               if (ePoint->wetness<pPoint->wetness || ePoint->wetness<MIN_WETNESS) continue;
  
-                               if (pPoint->e_alpha > 1.0f) pPoint->e_alpha = 1.0f;
-                       }
+                               w_factor = 1.0f/numOfNeighs * MIN2(ePoint->wetness, 1.0f) * speed_scale;
+                               CLAMP(w_factor, 0.0f, 1.0f);
  
-                       /* For antialiasing sake, don't let alpha go much higher than average alpha of neighbours       */
-                       if (pPoint->e_alpha > (totalAlpha/numOfNeighs+0.25f)) {
-                               pPoint->e_alpha = (totalAlpha/numOfNeighs+0.25f);
-                               if (pPoint->e_alpha>1.0f) pPoint->e_alpha = 1.0f;
+                               /* mix new wetness and color */
+                               pPoint->wetness = (1.0f-w_factor)*pPoint->wetness + w_factor*ePoint->wetness;
+                               pPoint->e_alpha = mixColors(pPoint->e_color, pPoint->e_alpha, ePoint->e_color, ePoint->e_alpha, w_factor);
                        }
                }
        }
        *       Shrink Effect
        */
        if (surface->effect & MOD_DPAINT_EFFECT_DO_SHRINK)  {
-               float eff_scale = EFF_MOVEMENT_PER_FRAME*surface->shrink_speed*timescale;
+               float eff_scale = distance_scale*EFF_MOVEMENT_PER_FRAME*surface->shrink_speed*timescale;
  
                /* Copy current surface to the previous points array to read unmodified values  */
                memcpy(prevPoint, sData->type_data, sData->total_points*sizeof(struct PaintPoint));
        */
        if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP && force) 
        {
-               float eff_scale = EFF_MOVEMENT_PER_FRAME*timescale/2.0f;
+               float eff_scale = distance_scale*EFF_MOVEMENT_PER_FRAME*timescale/2.0f;
                /* Copy current surface to the previous points array to read unmodified values  */
                memcpy(prevPoint, sData->type_data, sData->total_points*sizeof(struct PaintPoint));
  
                        float closest_d[2];
  
                        /* adjust drip speed depending on wetness */
-                       float w_factor = pPoint_prev->wetness*0.5f - 0.025f;
+                       float w_factor = pPoint_prev->wetness - 0.025f;
                        if (w_factor <= 0) continue;
+                       CLAMP(w_factor, 0.0f, 1.0f);
  
                        /* get force affect points */
                        surface_determineForceTargetPoints(sData, index, &force[index*4], closest_d, closest_id);
                        for (i=0; i<2; i++) {
                                int n_index = closest_id[i];
                                if (n_index != -1 && closest_d[i]>0.0f) {
-                                       float dir_dot = closest_d[i], dir_factor;
+                                       float dir_dot = closest_d[i], dir_factor, a_factor;
                                        float speed_scale = eff_scale*force[index*4+3]/bNeighs[n_index].dist;
                                        PaintPoint *ePoint = &((PaintPoint*)sData->type_data)[sData->adj_data->n_target[n_index]];
+                                       float e_wet = ePoint->wetness;
  
                                        /* just skip if angle is too extreme */
                                        if (dir_dot <= 0.0f) continue;
  
-                                       dir_factor = dir_dot * speed_scale * w_factor;
-                                       if (dir_factor > (0.5f/steps)) dir_factor = (0.5f/steps);
-                                       /* mix new color */
-                                       if (dir_factor) mixColors(ePoint->e_color, ePoint->e_alpha, pPoint->e_color, dir_factor);
+                                       dir_factor = dir_dot * MIN2(speed_scale, 1.0f) * w_factor;
+                                       if (dir_factor > 0.5f) dir_factor = 0.5f;
  
-                                       ePoint->e_alpha += dir_factor;
+                                       /* mix new wetness*/
                                        ePoint->wetness += dir_factor;
-                                       if (ePoint->e_alpha > 1.0f) ePoint->e_alpha = 1.0f;
+                                       CLAMP(ePoint->wetness, 0.0f, MAX_WETNESS);
+                                       /* mix new color */
+                                       a_factor = dir_factor / pPoint_prev->wetness;
+                                       CLAMP(a_factor, 0.0f, 1.0f);
+                                       mixColors(ePoint->e_color, ePoint->e_alpha, pPoint_prev->e_color, pPoint_prev->e_alpha, a_factor);
+                                       /* dripping is supposed to preserve alpha level */
+                                       if (pPoint_prev->e_alpha > ePoint->e_alpha) {
+                                               ePoint->e_alpha += a_factor * pPoint_prev->e_alpha;
+                                               if (ePoint->e_alpha > pPoint_prev->e_alpha)
+                                                       ePoint->e_alpha = pPoint_prev->e_alpha;
+                                       }
  
-                                       /* and decrease paint wetness on current point */
-                                       pPoint->wetness -= dir_factor;
+                                       /* decrease paint wetness on current point */
+                                       pPoint->wetness -= (ePoint->wetness - e_wet);
+                                       CLAMP(pPoint->wetness, 0.0f, MAX_WETNESS);
                                }
                        }
                }
-               /* Keep values within acceptable range */
-               #pragma omp parallel for schedule(static)
-               for (index = 0; index < sData->total_points; index++)
-               {
-                       PaintPoint *cPoint = &((PaintPoint*)sData->type_data)[index];
-                       if (cPoint->e_alpha > 1.0f) cPoint->e_alpha=1.0f;
-                       if (cPoint->wetness > 2.0f) cPoint->wetness=2.0f;
-                       if (cPoint->e_alpha < 0.0f) cPoint->e_alpha=0.0f;
-                       if (cPoint->wetness < 0.0f) cPoint->wetness=0.0f;
-               }
        }
  }
  
@@@ -4317,7 -4335,7 +4329,7 @@@ void dynamicPaint_doWaveStep(DynamicPai
        double average_dist = 0.0f;
        Bounds3D *mb = &sData->bData->mesh_bounds;
        float canvas_size = MAX3((mb->max[0]-mb->min[0]), (mb->max[1]-mb->min[1]), (mb->max[2]-mb->min[2]));
-       float wave_scale = WAVE_INIT_SIZE/canvas_size;
+       float wave_scale = CANVAS_REL_SIZE/canvas_size;
  
        /* allocate memory */
        PaintWavePoint *prevPoint = MEM_mallocN(sData->total_points*sizeof(PaintWavePoint), "Temp previous points for wave simulation");
@@@ -4430,48 -4448,53 +4442,53 @@@ static void dynamicPaint_surfacePreStep
                if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
                        PaintPoint *pPoint = &((PaintPoint*)sData->type_data)[index];
                        /* drying */
-                       if (pPoint->wetness >= MIN_WETNESS) {
-                               int i;
-                               float dry_ratio, f_color[4];
-                               float p_wetness = pPoint->wetness;
-                               VALUE_DISSOLVE(pPoint->wetness, surface->dry_speed, timescale, (surface->flags & MOD_DPAINT_DRY_LOG));
-                               if (pPoint->wetness<0.0f) pPoint->wetness=0.0f;
-                               dry_ratio = pPoint->wetness/p_wetness;
+                       if (surface->flags & MOD_DPAINT_USE_DRYING) {
+                               if (pPoint->wetness >= MIN_WETNESS) {
+                                       int i;
+                                       float dry_ratio, f_color[4];
+                                       float p_wetness = pPoint->wetness;
+                                       VALUE_DISSOLVE(pPoint->wetness, surface->dry_speed, timescale, (surface->flags & MOD_DPAINT_DRY_LOG));
+                                       if (pPoint->wetness<0.0f) pPoint->wetness=0.0f;
  
-                               /*
-                               *       Slowly "shift" paint from wet layer to dry layer as it drys:
-                               */
-                               /* make sure alpha values are within proper range */
-                               CLAMP(pPoint->alpha, 0.0f, 1.0f);
-                               CLAMP(pPoint->e_alpha, 0.0f, 1.0f);
-                               /* get current final blended color of these layers */
-                               blendColors(pPoint->color, pPoint->alpha, pPoint->e_color, pPoint->e_alpha, f_color);
-                               /* reduce wet layer alpha by dry factor */
-                               pPoint->e_alpha *= dry_ratio;
-                               /* now calculate new alpha for dry layer that keeps final blended color unchanged */
-                               pPoint->alpha = (f_color[3] - pPoint->e_alpha)/(1.0f-pPoint->e_alpha);
-                               /* for each rgb component, calculate a new dry layer color that keeps the final blend color
-                               *  with these new alpha values. (wet layer color doesnt change)*/
-                               if (pPoint->alpha) {
-                                       for (i=0; i<3; i++) {
-                                               pPoint->color[i] = (f_color[i]*f_color[3] - pPoint->e_color[i]*pPoint->e_alpha)/(pPoint->alpha*(1.0f-pPoint->e_alpha));
+                                       if (pPoint->wetness < surface->color_dry_threshold) {
+                                               dry_ratio = pPoint->wetness/p_wetness;
+                                               /*
+                                               *       Slowly "shift" paint from wet layer to dry layer as it drys:
+                                               */
+                                               /* make sure alpha values are within proper range */
+                                               CLAMP(pPoint->alpha, 0.0f, 1.0f);
+                                               CLAMP(pPoint->e_alpha, 0.0f, 1.0f);
+                                               /* get current final blended color of these layers */
+                                               blendColors(pPoint->color, pPoint->alpha, pPoint->e_color, pPoint->e_alpha, f_color);
+                                               /* reduce wet layer alpha by dry factor */
+                                               pPoint->e_alpha *= dry_ratio;
+                                               /* now calculate new alpha for dry layer that keeps final blended color unchanged */
+                                               pPoint->alpha = (f_color[3] - pPoint->e_alpha)/(1.0f-pPoint->e_alpha);
+                                               /* for each rgb component, calculate a new dry layer color that keeps the final blend color
+                                               *  with these new alpha values. (wet layer color doesnt change)*/
+                                               if (pPoint->alpha) {
+                                                       for (i=0; i<3; i++) {
+                                                               pPoint->color[i] = (f_color[i]*f_color[3] - pPoint->e_color[i]*pPoint->e_alpha)/(pPoint->alpha*(1.0f-pPoint->e_alpha));
+                                                       }
+                                               }
                                        }
-                               }
  
-                               pPoint->state = DPAINT_PAINT_WET;
-                       }
-                       /* in case of just dryed paint, just mix it to the dry layer and mark it empty */
-                       else if (pPoint->state > 0) {
-                               float f_color[4];
-                               blendColors(pPoint->color, pPoint->alpha, pPoint->e_color, pPoint->e_alpha, f_color);
-                               copy_v3_v3(pPoint->color, f_color);
-                               pPoint->alpha = f_color[3];
-                               /* clear wet layer */
-                               pPoint->wetness = 0.0f;
-                               pPoint->e_alpha = 0.0f;
-                               pPoint->state = DPAINT_PAINT_DRY;
+                                       pPoint->state = DPAINT_PAINT_WET;
+                               }
+                               /* in case of just dryed paint, just mix it to the dry layer and mark it empty */
+                               else if (pPoint->state > 0) {
+                                       float f_color[4];
+                                       blendColors(pPoint->color, pPoint->alpha, pPoint->e_color, pPoint->e_alpha, f_color);
+                                       copy_v3_v3(pPoint->color, f_color);
+                                       pPoint->alpha = f_color[3];
+                                       /* clear wet layer */
+                                       pPoint->wetness = 0.0f;
+                                       pPoint->e_alpha = 0.0f;
+                                       pPoint->state = DPAINT_PAINT_DRY;
+                               }
                        }
  
                        if (surface->flags & MOD_DPAINT_DISSOLVE) {
@@@ -4919,7 -4942,7 +4936,7 @@@ int dynamicPaint_calculateFrame(Dynamic
  
        /* apply previous displace on derivedmesh if incremental surface */
        if (surface->flags & MOD_DPAINT_DISP_INCREMENTAL)
-               dynamicPaint_applySurfaceDisplace(surface, surface->canvas->dm, 0);
+               dynamicPaint_applySurfaceDisplace(surface, surface->canvas->dm);
  
        /* update bake data */
        dynamicPaint_generateBakeData(surface, scene, cObject); 
index 7e1634d6eca50790b101a36c93a42c459b4ad61f,6855ece8cd7fa54fcf45c9fde873f2315f8df309..978cb4d00e332299333898313c68c3a0a029d403
  
  #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"
  #include "BKE_scene.h"
  #include "BKE_screen.h"
  #include "BKE_sequencer.h"
+ #include "BKE_text.h" // for txt_extended_ascii_as_utf8
  #include "BKE_texture.h" // for open_plugin_tex
  #include "BKE_tracking.h"
  #include "BKE_utildefines.h" // SWITCH_INT DATA ENDB DNA1 O_BINARY GLOB USER TEST REND
@@@ -2704,16 -2703,6 +2705,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);
                        
@@@ -3636,26 -3625,6 +3637,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, TRUE);
 +
                        me->id.flag -= LIB_NEEDLINK;
                }
                me= me->id.next;
@@@ -3727,17 -3674,10 +3728,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;
                }
        }
@@@ -3750,18 -3690,7 +3751,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 */
@@@ -3811,17 -3740,12 +3812,17 @@@ static void direct_link_mesh(FileData *
        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->totvert);
        direct_link_customdata(fd, &mesh->edata, mesh->totedge);
        direct_link_customdata(fd, &mesh->fdata, mesh->totface);
 -
 +      direct_link_customdata(fd, &mesh->ldata, mesh->totloop);
 +      direct_link_customdata(fd, &mesh->pdata, mesh->totpoly);
 +      
  
  #ifdef USE_BMESH_FORWARD_COMPAT
        /* NEVER ENABLE THIS CODE INTO BMESH!
  
        mesh->bb= NULL;
        mesh->mselect = NULL;
 -      mesh->edit_mesh= NULL;
 +      mesh->edit_btmesh= NULL;
        
        /* Multires data */
        mesh->mr= newdataadr(fd, mesh->mr);
@@@ -6651,7 -6573,7 +6652,7 @@@ static void customdata_version_242(Mes
                }
        }
  
 -      mesh_update_customdata_pointers(me);
 +      mesh_update_customdata_pointers(me, TRUE);
  }
  
  /*only copy render texface layer from active*/
@@@ -12353,7 -12275,7 +12354,7 @@@ static void do_versions(FileData *fd, L
                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_normals_tessface(me->mvert, me->totvert, me->mface, me->totface, NULL);
        }
  
        if (main->versionfile < 256 || (main->versionfile == 256 && main->subversionfile < 2)){
                        }
                }
        }
+       if (main->versionfile < 261 || (main->versionfile == 261 && main->subversionfile < 3))
+       {
+               {
+                       /* convert extended ascii to utf-8 for text editor */
+                       Text *text;
+                       for (text= main->text.first; text; text= text->id.next)
+                               if(!(text->flags & TXT_ISEXT)) {
+                                       TextLine *tl;
+                                       
+                                       for (tl= text->lines.first; tl; tl= tl->next) {
+                                               int added= txt_extended_ascii_as_utf8(&tl->line);
+                                               tl->len+= added;
+                                               
+                                               /* reset cursor position if line was changed */
+                                               if (added && tl == text->curl)
+                                                       text->curc = 0;
+                                       }
+                               }
+               }
+               {
+                       /* set new dynamic paint values */
+                       Object *ob;
+                       for(ob = main->object.first; ob; ob = ob->id.next) {
+                               ModifierData *md;
+                               for(md= ob->modifiers.first; md; md= md->next) {
+                                       if (md->type == eModifierType_DynamicPaint) {
+                                               DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
+                                               if(pmd->canvas)
+                                               {
+                                                       DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
+                                                       for (; surface; surface=surface->next) {
+                                                               surface->color_dry_threshold = 1.0f;
+                                                               surface->influence_scale = 1.0f;
+                                                               surface->radius_scale = 1.0f;
+                                                               surface->flags |= MOD_DPAINT_USE_DRYING;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
        
        /* put compatibility code here until next subversion bump */
        {
index 9cf93980c2c9cc0a448942e7aa2889c7be556e61,0862af2756aa0ff9fd0ffdd37aa299c823161ff2..730254bba79a4099c84ee7472a14b3da8cc48d93
@@@ -1957,10 -1957,10 +1957,10 @@@ static void handle_layer_buttons(bConte
                tot= RNA_property_array_length(&but->rnapoin, but->rnaprop);
                
                /* Normally clicking only selects one layer */
-               RNA_property_boolean_set_index(&but->rnapoin, but->rnaprop, cur, 1);
+               RNA_property_boolean_set_index(&but->rnapoin, but->rnaprop, cur, TRUE);
                for(i = 0; i < tot; ++i) {
                        if(i != cur)
-                               RNA_property_boolean_set_index(&but->rnapoin, but->rnaprop, i, 0);
+                               RNA_property_boolean_set_index(&but->rnapoin, but->rnaprop, i, FALSE);
                }
        }
        
@@@ -2107,7 -2107,7 +2107,7 @@@ static void list_item_row(bContext *C, 
        name= (namebuf)? namebuf: "";
  
        /* hardcoded types */
 -      if(itemptr->type == &RNA_MeshTextureFaceLayer || itemptr->type == &RNA_MeshColorLayer) {
 +      if(itemptr->type == &RNA_MeshTexturePolyLayer || itemptr->type == &RNA_MeshLoopColorLayer) {
                uiItemL(sub, name, icon);
                uiBlockSetEmboss(block, UI_EMBOSSN);
                uiDefIconButR(block, TOG, 0, ICON_SCENE, 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "active_render", 0, 0, 0, 0, 0, NULL);
index ffceaf1c6989e5cf4529cccbdeeff9b840b96c7b,90b3d45deb7df75adac511978306f5754dc32332..1e14fcdd580b69adfb44b16a0af1c2ba60112997
@@@ -57,7 -57,6 +57,7 @@@
  
  /**************************** registration **********************************/
  
 +void EXPORT_MESH_OT_wavefront(wmOperatorType *ot);
  void ED_operatortypes_mesh(void)
  {
        WM_operatortype_append(MESH_OT_select_all);
@@@ -70,7 -69,6 +70,7 @@@
        WM_operatortype_append(MESH_OT_hide);
        WM_operatortype_append(MESH_OT_reveal);
        WM_operatortype_append(MESH_OT_select_by_number_vertices);
 +      WM_operatortype_append(MESH_OT_select_loose_verts);
        WM_operatortype_append(MESH_OT_select_mirror);
        WM_operatortype_append(MESH_OT_normals_make_consistent);
        WM_operatortype_append(MESH_OT_merge);
        WM_operatortype_append(MESH_OT_primitive_monkey_add);
        WM_operatortype_append(MESH_OT_primitive_uv_sphere_add);
        WM_operatortype_append(MESH_OT_primitive_ico_sphere_add);
 -      WM_operatortype_append(MESH_OT_fgon_clear);
 -      WM_operatortype_append(MESH_OT_fgon_make);
        WM_operatortype_append(MESH_OT_duplicate);
        WM_operatortype_append(MESH_OT_remove_doubles);
        WM_operatortype_append(MESH_OT_vertices_sort);
        WM_operatortype_append(MESH_OT_vertices_randomize);
 -      WM_operatortype_append(MESH_OT_extrude);
        WM_operatortype_append(MESH_OT_spin);
        WM_operatortype_append(MESH_OT_screw);
 -      
 +
 +      WM_operatortype_append(MESH_OT_extrude_region);
 +      WM_operatortype_append(MESH_OT_extrude_faces_indiv);
 +      WM_operatortype_append(MESH_OT_extrude_edges_indiv);
 +      WM_operatortype_append(MESH_OT_extrude_verts_indiv);
 +
        WM_operatortype_append(MESH_OT_split);
        WM_operatortype_append(MESH_OT_extrude_repeat);
        WM_operatortype_append(MESH_OT_edge_rotate);
        WM_operatortype_append(MESH_OT_select_axis);
        
        WM_operatortype_append(MESH_OT_uvs_rotate);
 -      WM_operatortype_append(MESH_OT_uvs_mirror);
 +      WM_operatortype_append(MESH_OT_uvs_reverse);
        WM_operatortype_append(MESH_OT_colors_rotate);
 -      WM_operatortype_append(MESH_OT_colors_mirror);
 +      WM_operatortype_append(MESH_OT_colors_reverse);
        
        WM_operatortype_append(MESH_OT_fill);
        WM_operatortype_append(MESH_OT_beautify_fill);
        WM_operatortype_append(MESH_OT_vertices_smooth);
        WM_operatortype_append(MESH_OT_noise);
        WM_operatortype_append(MESH_OT_flip_normals);
 -      WM_operatortype_append(MESH_OT_knife_cut);
 +      //WM_operatortype_append(MESH_OT_knife_cut);
        WM_operatortype_append(MESH_OT_rip);
        WM_operatortype_append(MESH_OT_blend_from_shape);
        WM_operatortype_append(MESH_OT_shape_propagate_to_all);
  
        WM_operatortype_append(MESH_OT_solidify);
        WM_operatortype_append(MESH_OT_select_nth);
 +      WM_operatortype_append(MESH_OT_vert_connect);
 +      WM_operatortype_append(MESH_OT_knifetool);
 +
 +      WM_operatortype_append(MESH_OT_bevel);
 +
 +      WM_operatortype_append(MESH_OT_select_next_loop);
 +      
 +      WM_operatortype_append(EXPORT_MESH_OT_wavefront);
 +      WM_operatortype_append(MESH_OT_bridge_edge_loops);
  
  #ifdef WITH_GAMEENGINE
        WM_operatortype_append(MESH_OT_navmesh_make);
@@@ -176,7 -163,7 +176,7 @@@ static int ED_operator_editmesh_face_se
  {
        Object *obedit= CTX_data_edit_object(C);
        if(obedit && obedit->type==OB_MESH) {
 -              EditMesh *em = ((Mesh *)obedit->data)->edit_mesh;
 +              BMEditMesh *em = ((Mesh *)obedit->data)->edit_btmesh;
                if (em && em->selectmode & SCE_SELECT_FACE) {
                        return 1;
                }
@@@ -201,43 -188,46 +201,43 @@@ void ED_operatormacros_mesh(void
        WM_operatortype_macro_define(ot, "MESH_OT_duplicate");
        otmacro= WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
        RNA_enum_set(otmacro->ptr, "proportional", 0);
-       RNA_boolean_set(otmacro->ptr, "mirror", 0);
+       RNA_boolean_set(otmacro->ptr, "mirror", FALSE);
  
        ot= WM_operatortype_append_macro("MESH_OT_rip_move", "Rip", OPTYPE_UNDO|OPTYPE_REGISTER);
        ot->description = "Rip polygons and move the result";
        WM_operatortype_macro_define(ot, "MESH_OT_rip");
        otmacro= WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
        RNA_enum_set(otmacro->ptr, "proportional", 0);
-       RNA_boolean_set(otmacro->ptr, "mirror", 0);
+       RNA_boolean_set(otmacro->ptr, "mirror", FALSE);
  
        ot= WM_operatortype_append_macro("MESH_OT_extrude_region_move", "Extrude Region and Move", OPTYPE_UNDO|OPTYPE_REGISTER);
        ot->description = "Extrude region and move result";
 -      otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude");
 -      RNA_enum_set(otmacro->ptr, "type", 1);
 +      otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude_region");
        otmacro= WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
        RNA_enum_set(otmacro->ptr, "proportional", 0);
-       RNA_boolean_set(otmacro->ptr, "mirror", 0);
+       RNA_boolean_set(otmacro->ptr, "mirror", FALSE);
  
        ot= WM_operatortype_append_macro("MESH_OT_extrude_faces_move", "Extrude Individual Faces and Move", OPTYPE_UNDO|OPTYPE_REGISTER);
        ot->description = "Extrude faces and move result";
 -      otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude");
 -      RNA_enum_set(otmacro->ptr, "type", 2);
 +      otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude_faces_indiv");
        otmacro= WM_operatortype_macro_define(ot, "TRANSFORM_OT_shrink_fatten");
        RNA_enum_set(otmacro->ptr, "proportional", 0);
-       RNA_boolean_set(otmacro->ptr, "mirror", 0);
+       RNA_boolean_set(otmacro->ptr, "mirror", FALSE);
  
        ot= WM_operatortype_append_macro("MESH_OT_extrude_edges_move", "Extrude Only Edges and Move", OPTYPE_UNDO|OPTYPE_REGISTER);
        ot->description = "Extrude edges and move result";
 -      otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude");
 -      RNA_enum_set(otmacro->ptr, "type", 3);
 +      otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude_edges_indiv");
        otmacro= WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
        RNA_enum_set(otmacro->ptr, "proportional", 0);
-       RNA_boolean_set(otmacro->ptr, "mirror", 0);
+       RNA_boolean_set(otmacro->ptr, "mirror", FALSE);
  
        ot= WM_operatortype_append_macro("MESH_OT_extrude_vertices_move", "Extrude Only Vertices and Move", OPTYPE_UNDO|OPTYPE_REGISTER);
        ot->description = "Extrude vertices and move result";
 -      otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude");
 +      otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude_verts_indiv");
        RNA_enum_set(otmacro->ptr, "type", 4);
        otmacro= WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
        RNA_enum_set(otmacro->ptr, "proportional", 0);
-       RNA_boolean_set(otmacro->ptr, "mirror", 0);
+       RNA_boolean_set(otmacro->ptr, "mirror", FALSE);
  }
  
  /* note mesh keymap also for other space? */
@@@ -310,7 -300,6 +310,7 @@@ void ED_keymap_mesh(wmKeyConfig *keycon
        
        WM_keymap_add_item(keymap, "MESH_OT_fill", FKEY, KM_PRESS, KM_ALT, 0);
        WM_keymap_add_item(keymap, "MESH_OT_beautify_fill", FKEY, KM_PRESS, KM_SHIFT|KM_ALT, 0);
 +
        WM_keymap_add_item(keymap, "MESH_OT_quads_convert_to_tris", TKEY, KM_PRESS, KM_CTRL, 0);
        WM_keymap_add_item(keymap, "MESH_OT_tris_convert_to_quads", JKEY, KM_PRESS, KM_ALT, 0);
        WM_keymap_add_item(keymap, "MESH_OT_edge_flip", FKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0);
        WM_keymap_add_menu(keymap, "INFO_MT_mesh_add", AKEY, KM_PRESS, KM_SHIFT, 0);
        
        WM_keymap_add_item(keymap, "MESH_OT_separate", PKEY, KM_PRESS, 0, 0);
 -      WM_keymap_add_item(keymap, "MESH_OT_split", YKEY, KM_PRESS, 0, 0);
 +      WM_keymap_add_item(keymap, "MESH_OT_vert_connect", YKEY, KM_PRESS, 0, 0);
  
        /* use KM_CLICK because same key is used for tweaks */
        kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0);
        WM_keymap_add_item(keymap, "MESH_OT_delete", XKEY, KM_PRESS, 0, 0);
        WM_keymap_add_item(keymap, "MESH_OT_delete", DELKEY, KM_PRESS, 0, 0);
        
 -      WM_keymap_add_item(keymap, "MESH_OT_knife_cut", LEFTMOUSE, KM_PRESS, 0, KKEY);
 -      RNA_enum_set(WM_keymap_add_item(keymap, "MESH_OT_knife_cut", LEFTMOUSE, KM_PRESS, KM_SHIFT, KKEY)->ptr, "type", 2/*KNIFE_MIDPOINT*/);
 +      WM_keymap_add_item(keymap, "MESH_OT_knifetool", KKEY, KM_PRESS, 0, 0);
 +      //RNA_enum_set(WM_keymap_add_item(keymap, "MESH_OT_knife_cut", LEFTMOUSE, KM_PRESS, KM_SHIFT, KKEY)->ptr, "type", 2/*KNIFE_MIDPOINT*/);
        
        WM_keymap_add_item(keymap, "OBJECT_OT_vertex_parent_set", PKEY, KM_PRESS, KM_CTRL, 0);
  
        }
        
        ED_object_generic_keymap(keyconf, keymap, 3);
 +      knifetool_modal_keymap(keyconf);
  }
  
index 536b2f70c31f20eda93a9fde0837c10d517302d0,64bbf604f67b3768d33b5f209429d7aaae885a50..70a1aa73fc96232b1ba7e0c7ac5a36f2d01fdd31
@@@ -249,7 -249,7 +249,7 @@@ int ED_object_add_generic_invoke(bConte
  }
  
  int ED_object_add_generic_get_opts(bContext *C, wmOperator *op, float *loc,
 -      float *rot, int *enter_editmode, unsigned int *layer)
 +      float *rot, int *enter_editmode, unsigned int *layer, int *is_view_aligned)
  {
        View3D *v3d = CTX_wm_view3d(C);
        int a, layer_values[20];
        else
                RNA_float_get_array(op->ptr, "rotation", rot);
        
 -
 +      if (is_view_aligned)
 +              *is_view_aligned = view_align;
 +      
        RNA_float_get_array(op->ptr, "location", loc);
  
        if(*layer == 0) {
@@@ -353,7 -351,7 +353,7 @@@ static int object_add_exec(bContext *C
        unsigned int layer;
        float loc[3], rot[3];
        
 -      if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
 +      if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL))
                return OPERATOR_CANCELLED;
  
        ED_object_add_type(C, RNA_enum_get(op->ptr, "type"), loc, rot, enter_editmode, layer);
@@@ -410,7 -408,7 +410,7 @@@ static Object *effector_add_type(bConte
        
        object_add_generic_invoke_options(C, op);
  
 -      if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
 +      if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL))
                return NULL;
  
        if(type==PFIELD_GUIDE) {
@@@ -486,11 -484,11 +486,11 @@@ static int object_camera_add_exec(bCont
        float loc[3], rot[3];
        
        /* force view align for cameras */
-       RNA_boolean_set(op->ptr, "view_align", 1);
+       RNA_boolean_set(op->ptr, "view_align", TRUE);
        
        object_add_generic_invoke_options(C, op);
  
 -      if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
 +      if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL))
                return OPERATOR_CANCELLED;
  
        ob= ED_object_add_type(C, OB_CAMERA, loc, rot, FALSE, layer);
@@@ -544,7 -542,7 +544,7 @@@ static int object_metaball_add_exec(bCo
        
        object_add_generic_invoke_options(C, op); // XXX these props don't get set right when only exec() is called
  
 -      if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
 +      if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL))
                return OPERATOR_CANCELLED;
        
        if(obedit==NULL || obedit->type!=OB_MBALL) {
@@@ -613,7 -611,7 +613,7 @@@ static int object_add_text_exec(bContex
        float loc[3], rot[3];
        
        object_add_generic_invoke_options(C, op); // XXX these props don't get set right when only exec() is called
 -      if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
 +      if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL))
                return OPERATOR_CANCELLED;
        
        if(obedit && obedit->type==OB_FONT)
@@@ -654,7 -652,7 +654,7 @@@ static int object_armature_add_exec(bCo
        float loc[3], rot[3];
        
        object_add_generic_invoke_options(C, op); // XXX these props don't get set right when only exec() is called
 -      if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
 +      if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL))
                return OPERATOR_CANCELLED;
        
        if ((obedit==NULL) || (obedit->type != OB_ARMATURE)) {
@@@ -722,7 -720,7 +722,7 @@@ static int object_lamp_add_exec(bContex
        float loc[3], rot[3];
        
        object_add_generic_invoke_options(C, op);
 -      if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
 +      if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL))
                return OPERATOR_CANCELLED;
  
        ob= ED_object_add_type(C, OB_LAMP, loc, rot, FALSE, layer);
@@@ -778,7 -776,7 +778,7 @@@ static int group_instance_add_exec(bCon
        float loc[3], rot[3];
        
        object_add_generic_invoke_options(C, op);
 -      if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
 +      if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL))
                return OPERATOR_CANCELLED;
  
        if(group) {
@@@ -810,7 -808,7 +810,7 @@@ static int object_speaker_add_exec(bCon
        Scene *scene = CTX_data_scene(C);
  
        object_add_generic_invoke_options(C, op);
 -      if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
 +      if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL))
                return OPERATOR_CANCELLED;
  
        ob= ED_object_add_type(C, OB_SPEAKER, loc, rot, FALSE, layer);
@@@ -1369,11 -1367,7 +1369,11 @@@ static int convert_exec(bContext *C, wm
                        dm= mesh_get_derived_final(scene, newob, CD_MASK_MESH);
                        /* dm= mesh_create_derived_no_deform(ob1, NULL);        this was called original (instead of get_derived). man o man why! (ton) */
  
 -                      DM_to_mesh(dm, newob->data);
 +                      DM_to_mesh(dm, newob->data, newob);
 +
 +                      /* re-tesselation doesn't happen automatic, calling like this is  */
 +                      me= newob->data;
 +                      me->totface = mesh_recalcTesselation(&me->fdata, &me->ldata, &me->pdata, me->mvert, me->totface, me->totloop, me->totpoly);
  
                        dm->release(dm);
                        object_free_modifiers(newob);   /* after derivedmesh calls! */
index eba4dd1878a82f8ec7da4294dca9f83c7995b71a,09ae63653636e6794537f2101b625d2d68cdc571..542b75e1f19bdf113c29650dc831ce6534aeb6b9
@@@ -214,9 -214,8 +214,9 @@@ void ED_operatortypes_object(void
  
        WM_operatortype_append(OBJECT_OT_bake_image);
        WM_operatortype_append(OBJECT_OT_drop_named_material);
 -}
  
 +      WM_operatortype_append(OBJECT_OT_test_multires);
 +}
  
  void ED_operatormacros_object(void)
  {
        if(ot) {
                ot->description = "Duplicate selected objects and move them";
                otmacro= WM_operatortype_macro_define(ot, "OBJECT_OT_duplicate");
-               RNA_boolean_set(otmacro->ptr, "linked", 1);
+               RNA_boolean_set(otmacro->ptr, "linked", TRUE);
                otmacro= WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
                RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF);
        }
index a3874c9f28abe7f4cd61dc5719b91eb8bd095dea,0d724dc1b280143f12d7747e84ce15120b94d05f..e18851893bd9af7b804fc21d294d88c4c8fb3767
@@@ -54,7 -54,6 +54,7 @@@
  #include "BKE_report.h"
  #include "BKE_scene.h"
  #include "BKE_screen.h"
 +#include "BKE_tessmesh.h"
  #include "BKE_sound.h"
  
  #include "WM_api.h"
@@@ -314,7 -313,7 +314,7 @@@ int ED_operator_editmesh(bContext *C
  {
        Object *obedit= CTX_data_edit_object(C);
        if(obedit && obedit->type==OB_MESH)
 -              return NULL != ((Mesh *)obedit->data)->edit_mesh;
 +              return NULL != ((Mesh *)obedit->data)->edit_btmesh;
        return 0;
  }
  
@@@ -367,15 -366,18 +367,15 @@@ int ED_operator_uvedit(bContext *C
  int ED_operator_uvmap(bContext *C)
  {
        Object *obedit= CTX_data_edit_object(C);
 -      EditMesh *em= NULL;
 +      BMEditMesh *em= NULL;
        
        if(obedit && obedit->type==OB_MESH)
 -              em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
 +              em= ((Mesh *)obedit->data)->edit_btmesh;
        
 -      if(em && (em->faces.first)) {
 -              BKE_mesh_end_editmesh(obedit->data, em);
 +      if(em && (em->bm->totface)) {
                return 1;
        }
        
 -      if(obedit)
 -              BKE_mesh_end_editmesh(obedit->data, em);
        return 0;
  }
  
@@@ -3490,7 -3492,7 +3490,7 @@@ void ED_keymap_screen(wmKeyConfig *keyc
  {
        ListBase *lb;
        wmKeyMap *keymap;
-       //wmKeyMapItem *kmi;
+       wmKeyMapItem *kmi;
        
        /* Screen Editing ------------------------------------------------ */
        keymap= WM_keymap_find(keyconf, "Screen Editing", 0, 0);
        
        /* render */
        WM_keymap_add_item(keymap, "RENDER_OT_render", F12KEY, KM_PRESS, 0, 0);
-       RNA_boolean_set(WM_keymap_add_item(keymap, "RENDER_OT_render", F12KEY, KM_PRESS, KM_CTRL, 0)->ptr, "animation", 1);
+       kmi = WM_keymap_add_item(keymap, "RENDER_OT_render", F12KEY, KM_PRESS, KM_CTRL, 0);
+       RNA_boolean_set(kmi->ptr, "animation", TRUE);
        WM_keymap_add_item(keymap, "RENDER_OT_view_cancel", ESCKEY, KM_PRESS, 0, 0);
        WM_keymap_add_item(keymap, "RENDER_OT_view_show", F11KEY, KM_PRESS, 0, 0);
        WM_keymap_add_item(keymap, "RENDER_OT_play_rendered_anim", F11KEY, KM_PRESS, KM_CTRL, 0);
        RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", WHEELDOWNMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "delta", 1);
        RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", WHEELUPMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "delta", -1);
        
-       RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", UPARROWKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0)->ptr, "end", 1);
-       RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", DOWNARROWKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0)->ptr, "end", 0);
-       RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", RIGHTARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "end", 1);
-       RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", LEFTARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "end", 0);
+       RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", UPARROWKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0)->ptr, "end", TRUE);
+       RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", DOWNARROWKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0)->ptr, "end", FALSE);
+       RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", RIGHTARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "end", TRUE);
+       RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", LEFTARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "end", FALSE);
        
        WM_keymap_add_item(keymap, "SCREEN_OT_keyframe_jump", UPARROWKEY, KM_PRESS, 0, 0);
-       RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_keyframe_jump", DOWNARROWKEY, KM_PRESS, 0, 0)->ptr, "next", 0);
+       RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_keyframe_jump", DOWNARROWKEY, KM_PRESS, 0, 0)->ptr, "next", FALSE);
        
        WM_keymap_add_item(keymap, "SCREEN_OT_keyframe_jump", MEDIALAST, KM_PRESS, 0, 0);
-       RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_keyframe_jump", MEDIAFIRST, KM_PRESS, 0, 0)->ptr, "next", 0);
+       kmi = WM_keymap_add_item(keymap, "SCREEN_OT_keyframe_jump", MEDIAFIRST, KM_PRESS, 0, 0);
+       RNA_boolean_set(kmi->ptr, "next", FALSE);
        
        /* play (forward and backwards) */
        WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", AKEY, KM_PRESS, KM_ALT, 0);
-       RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", AKEY, KM_PRESS, KM_ALT|KM_SHIFT, 0)->ptr, "reverse", 1);
+       RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", AKEY, KM_PRESS, KM_ALT|KM_SHIFT, 0)->ptr, "reverse", TRUE);
        WM_keymap_add_item(keymap, "SCREEN_OT_animation_cancel", ESCKEY, KM_PRESS, 0, 0);
        
        WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", MEDIAPLAY, KM_PRESS, 0, 0);
index 597adcf4193437888fb5250338c9aae87df2c631,00bb8d169438661bd7886a38a10937848211b703..060e59265e0d095756070b019cbb7c236260681d
@@@ -55,7 -55,6 +55,7 @@@
  #include "BKE_modifier.h"
  #include "BKE_paint.h"
  #include "BKE_screen.h"
 +#include "BKE_tessmesh.h"
  
  #include "ED_mesh.h"
  #include "ED_util.h"
@@@ -231,7 -230,7 +231,7 @@@ static int view3d_layers_invoke(bContex
                return OPERATOR_PASS_THROUGH;
        
        if(event->shift)
-               RNA_boolean_set(op->ptr, "extend", 1);
+               RNA_boolean_set(op->ptr, "extend", TRUE);
        
        if(event->alt) {
                int nr= RNA_int_get(op->ptr, "nr") + 10;
@@@ -335,12 -334,12 +335,12 @@@ static void do_view3d_header_buttons(bC
        ScrArea *sa= CTX_wm_area(C);
        View3D *v3d= sa->spacedata.first;
        Object *obedit = CTX_data_edit_object(C);
 -      EditMesh *em= NULL;
 +      BMEditMesh *em= NULL;
        int ctrl= win->eventstate->ctrl, shift= win->eventstate->shift;
        PointerRNA props_ptr;
        
        if(obedit && obedit->type==OB_MESH) {
 -              em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
 +              em= ((Mesh *)obedit->data)->edit_btmesh;
        }
        /* watch it: if sa->win does not exist, check that when calling direct drawing routines */
  
                        if(shift==0 || em->selectmode==0)
                                em->selectmode= SCE_SELECT_VERTEX;
                        ts->selectmode= em->selectmode;
 -                      EM_selectmode_set(em);
 +                      EDBM_selectmode_set(em);
                        WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
                        ED_undo_push(C, "Selectmode Set: Vertex");
                }
                if(em) {
                        if(shift==0 || em->selectmode==0){
                                if( (em->selectmode ^ SCE_SELECT_EDGE) == SCE_SELECT_VERTEX){
 -                                      if(ctrl) EM_convertsel(em, SCE_SELECT_VERTEX,SCE_SELECT_EDGE); 
 +                                      if(ctrl) EDBM_convertsel(em, SCE_SELECT_VERTEX,SCE_SELECT_EDGE); 
                                }
                                em->selectmode = SCE_SELECT_EDGE;
                        }
                        ts->selectmode= em->selectmode;
 -                      EM_selectmode_set(em);
 +                      EDBM_selectmode_set(em);
                        WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
                        ED_undo_push(C, "Selectmode Set: Edge");
                }
        case B_SEL_FACE:
                if(em) {
                        if( shift==0 || em->selectmode==0){
 -                              if( ((em->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_VERTEX) || ((em->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_EDGE)){
 -                                      if(ctrl)
 -                                              EM_convertsel(em, (em->selectmode ^ SCE_SELECT_FACE),SCE_SELECT_FACE);
 +                              if( ((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_VERTEX) || ((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_EDGE)){
 +                                      if(ctrl) EDBM_convertsel(em, (ts->selectmode ^ SCE_SELECT_FACE),SCE_SELECT_FACE);
                                }
                                em->selectmode = SCE_SELECT_FACE;
                        }
                        ts->selectmode= em->selectmode;
 -                      EM_selectmode_set(em);
 +                      EDBM_selectmode_set(em);
                        WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
                        ED_undo_push(C, "Selectmode Set: Face");
                }
        default:
                break;
        }
 -
 -      if(obedit && obedit->type==OB_MESH)
 -              BKE_mesh_end_editmesh(obedit->data, em);
  }
  
  /* Returns the icon associated with an object mode */
@@@ -446,7 -449,7 +446,7 @@@ void uiTemplateEditModeSelection(uiLayo
        uiBlockSetHandleFunc(block, do_view3d_header_buttons, NULL);
  
        if(obedit && (obedit->type == OB_MESH)) {
 -              EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
 +              BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
                uiLayout *row;
  
                row= uiLayoutRow(layout, 1);
                uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL, 0,0,UI_UNIT_X,UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Vertex select mode");
                uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL, 0,0,UI_UNIT_X,UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Edge select mode");
                uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL, 0,0,UI_UNIT_X,UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Face select mode");
 -
 -              BKE_mesh_end_editmesh(obedit->data, em);
        }
  }
  
index f2c720ff4dce80056127f99b929bdf9c3f3f221e,98fef075940e93a7cc8daac77260741585ada192..a11d5935e220c8f67a834cb390768a6da619a758
@@@ -33,7 -33,6 +33,7 @@@
  #include <stdlib.h>
  #include <string.h>
  #include <math.h>
 +#include <string.h>
  
  #include "MEM_guardedalloc.h"
  
  #include "DNA_material_types.h"
  #include "DNA_meshdata_types.h"
  #include "DNA_node_types.h"
 +#include "DNA_image_types.h"
 +#include "DNA_space_types.h"
  #include "DNA_scene_types.h"
  
  #include "BLI_math.h"
  #include "BLI_blenlib.h"
  #include "BLI_editVert.h"
 +#include "BLI_array.h"
  #include "BLI_utildefines.h"
  
  #include "BKE_context.h"
@@@ -62,7 -58,6 +62,7 @@@
  #include "BKE_node.h"
  #include "BKE_report.h"
  #include "BKE_scene.h"
 +#include "BKE_tessmesh.h"
  
  #include "ED_image.h"
  #include "ED_mesh.h"
  
  #include "uvedit_intern.h"
  
 +#define EFA_F1_FLAG   2
 +
  /************************* state testing ************************/
  
  int ED_uvedit_test(Object *obedit)
  {
 -      EditMesh *em;
 +      BMEditMesh *em;
        int ret;
  
 -      if(!obedit || obedit->type != OB_MESH)
 +      if (!obedit)
 +              return 0;
 +      
 +      if(obedit->type != OB_MESH)
                return 0;
  
 -      em = BKE_mesh_get_editmesh(obedit->data);
 -      ret = EM_texFaceCheck(em);
 -      BKE_mesh_end_editmesh(obedit->data, em);
 +      em = ((Mesh*)obedit->data)->edit_btmesh;
 +      ret = EDBM_texFaceCheck(em);
        
        return ret;
  }
@@@ -144,10 -135,9 +144,10 @@@ void ED_object_assign_active_image(Mai
  
  void ED_uvedit_assign_image(Main *bmain, Scene *scene, Object *obedit, Image *ima, Image *previma)
  {
 -      EditMesh *em;
 -      EditFace *efa;
 -      MTFace *tf;
 +      BMEditMesh *em;
 +      BMFace *efa;
 +      BMIter iter;
 +      MTexPoly *tf;
        int update= 0;
        
        /* skip assigning these procedural images... */
        if(!obedit || (obedit->type != OB_MESH))
                return;
  
 -      em= BKE_mesh_get_editmesh(((Mesh*)obedit->data));
 -      if(!em || !em->faces.first) {
 -              BKE_mesh_end_editmesh(obedit->data, em);
 +      em= ((Mesh*)obedit->data)->edit_btmesh;
 +      if(!em || !em->bm->totface) {
                return;
        }
  
        if(scene_use_new_shading_nodes(scene)) {
                /* new shading system, assign image in material */
                int sloppy= 1;
 -              EditFace *efa= EM_get_actFace(em, sloppy);
 +              BMFace *efa= BM_get_actFace(em->bm, sloppy);
  
                if(efa)
                        ED_object_assign_active_image(bmain, obedit, efa->mat_nr, ima);
                /* old shading system, assign image to selected faces */
                
                /* ensure we have a uv map */
 -              if(!CustomData_has_layer(&em->fdata, CD_MTFACE)) {
 -                      EM_add_data_layer(em, &em->fdata, CD_MTFACE, NULL);
 +              if(!CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY)) {
 +                      BM_add_data_layer(em->bm, &em->bm->pdata, CD_MTEXPOLY);
 +                      BM_add_data_layer(em->bm, &em->bm->ldata, CD_MLOOPUV);
                        update= 1;
                }
  
                /* now assign to all visible faces */
 -              for(efa= em->faces.first; efa; efa= efa->next) {
 -                      tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 +              BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +                      tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
  
                        if(uvedit_face_visible(scene, previma, efa, tf)) {
                                if(ima) {
                                        if(ima->id.us==0) id_us_plus(&ima->id);
                                        else id_lib_extern(&ima->id);
                                }
 -                              else
 +                              else {
                                        tf->tpage= NULL;
 +                              }
  
                                update = 1;
                        }
                        DAG_id_tag_update(obedit->data, 0);
        }
  
 -      BKE_mesh_end_editmesh(obedit->data, em);
  }
  
  /* dotile -   1, set the tile flag (from the space image)
   *                    2, set the tile index for the faces. */
  static int uvedit_set_tile(Object *obedit, Image *ima, int curtile)
  {
 -      EditMesh *em;
 -      EditFace *efa;
 -      MTFace *tf;
 +      BMEditMesh *em;
 +      BMFace *efa;
 +      BMIter iter;
 +      MTexPoly *tf;
        
        /* verify if we have something to do */
        if(!ima || !ED_uvedit_test(obedit))
        if(ima->type==IMA_TYPE_R_RESULT || ima->type==IMA_TYPE_COMPOSITE)
                return 0;
        
 -      em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 +      em= ((Mesh*)obedit->data)->edit_btmesh;
  
 -      for(efa= em->faces.first; efa; efa= efa->next) {
 -              tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 +      BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +              tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
  
 -              if(efa->h==0 && efa->f & SELECT)
 +              if(!BM_TestHFlag(efa, BM_HIDDEN) && BM_TestHFlag(efa, BM_SELECT))
                        tf->tile= curtile; /* set tile index */
        }
  
        DAG_id_tag_update(obedit->data, 0);
 -      BKE_mesh_end_editmesh(obedit->data, em);
  
        return 1;
  }
@@@ -247,7 -237,13 +247,7 @@@ static void uvedit_pixel_to_float(Space
  {
        int width, height;
  
 -      if(sima) {
 -              ED_space_image_size(sima, &width, &height);
 -      }
 -      else {
 -              width= 256;
 -              height= 256;
 -      }
 +      ED_space_image_size(sima, &width, &height);
  
        dist[0]= pixeldist/width;
        dist[1]= pixeldist/height;
  
  /*************** visibility and selection utilities **************/
  
 -int uvedit_face_visible_nolocal(Scene *scene, EditFace *efa)
 +int uvedit_face_visible_nolocal(Scene *scene, BMFace *efa)
  {
        ToolSettings *ts= scene->toolsettings;
  
        if(ts->uv_flag & UV_SYNC_SELECTION)
 -              return (efa->h==0);
 +              return (BM_TestHFlag(efa, BM_HIDDEN)==0);
        else
 -              return (efa->h==0 && (efa->f & SELECT));
 +              return (BM_TestHFlag(efa, BM_HIDDEN)==0 && BM_TestHFlag(efa, BM_SELECT));
  }
  
 -int uvedit_face_visible(Scene *scene, Image *ima, EditFace *efa, MTFace *tf)
 -{
 +int uvedit_face_visible(Scene *scene, Image *ima, BMFace *efa, MTexPoly *tf) {
        ToolSettings *ts= scene->toolsettings;
  
        if(ts->uv_flag & UV_SHOW_SAME_IMAGE)
                return uvedit_face_visible_nolocal(scene, efa);
  }
  
 -int uvedit_face_selected(Scene *scene, EditFace *efa, MTFace *tf)
 +int uvedit_face_selected(Scene *scene, BMEditMesh *em, BMFace *efa)
  {
        ToolSettings *ts= scene->toolsettings;
  
        if(ts->uv_flag & UV_SYNC_SELECTION)
 -              return (efa->f & SELECT);
 -      else
 -              return (!(~tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) &&(!efa->v4 || tf->flag & TF_SEL4));
 +              return (BM_TestHFlag(efa, BM_SELECT));
 +      else {
 +              BMLoop *l;
 +              MLoopUV *luv;
 +              BMIter liter;
 +
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                      if (!(luv->flag & MLOOPUV_VERTSEL))
 +                              return 0;
 +              }
 +
 +              return 1;
 +      }
  }
  
 -void uvedit_face_select(Scene *scene, EditFace *efa, MTFace *tf)
 +int uvedit_face_select(Scene *scene, BMEditMesh *em, BMFace *efa)
  {
        ToolSettings *ts= scene->toolsettings;
  
        if(ts->uv_flag & UV_SYNC_SELECTION)
 -              EM_select_face(efa, 1);
 -      else
 -              tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
 +              BM_Select(em->bm, efa, TRUE);
 +      else {
 +              BMLoop *l;
 +              MLoopUV *luv;
 +              BMIter liter;
 +
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                      luv->flag |= MLOOPUV_VERTSEL;
 +              }
 +
 +              return 1;
 +      }
 +
 +      return 0;
  }
  
 -void uvedit_face_deselect(Scene *scene, EditFace *efa, MTFace *tf)
 +int uvedit_face_deselect(Scene *scene, BMEditMesh *em, BMFace *efa)
  {
        ToolSettings *ts= scene->toolsettings;
  
 -      if(ts->uv_flag & UV_SYNC_SELECTION)
 -              EM_select_face(efa, 0);
 -      else
 -              tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
 +      if(ts->uv_flag & UV_SYNC_SELECTION) {
 +              BM_Select(em->bm, efa, FALSE);
 +      }
 +      else {
 +              BMLoop *l;
 +              MLoopUV *luv;
 +              BMIter liter;
 +
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                      luv->flag &= ~MLOOPUV_VERTSEL;
 +              }
 +
 +              return 1;
 +      }
 +
 +      return 0;
  }
  
 -int uvedit_edge_selected(Scene *scene, EditFace *efa, MTFace *tf, int i)
 +int uvedit_edge_selected(BMEditMesh *em, Scene *scene, BMLoop *l)
  {
        ToolSettings *ts= scene->toolsettings;
 -      int nvert= (efa->v4)? 4: 3;
  
        if(ts->uv_flag & UV_SYNC_SELECTION) {
                if(ts->selectmode & SCE_SELECT_FACE)
 -                      return (efa->f & SELECT);
 -              else if(ts->selectmode & SCE_SELECT_EDGE)
 -                      return (*(&efa->e1 + i))->f & SELECT;
 -              else
 -                      return (((efa->v1 + i)->f & SELECT) && ((efa->v1 + (i+1)%nvert)->f & SELECT));
 +                      return BM_TestHFlag(l->f, BM_SELECT);
 +              else if(ts->selectmode == SCE_SELECT_EDGE) {
 +                      return BM_TestHFlag(l->e, BM_SELECT);
 +              } else
 +                      return BM_TestHFlag(l->v, BM_SELECT) && 
 +                             BM_TestHFlag(l->next->v, BM_SELECT);
 +      }
 +      else {
 +              MLoopUV *luv1, *luv2;
 +
 +              luv1 = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +              luv2 = CustomData_bmesh_get(&em->bm->ldata, l->next->head.data, CD_MLOOPUV);
 +
 +              return (luv1->flag & MLOOPUV_VERTSEL) && (luv2->flag & MLOOPUV_VERTSEL);
        }
 -      else
 -              return (tf->flag & TF_SEL_MASK(i)) && (tf->flag & TF_SEL_MASK((i+1)%nvert));
  }
  
 -void uvedit_edge_select(Scene *scene, EditFace *efa, MTFace *tf, int i)
 +void uvedit_edge_select(BMEditMesh *em, Scene *scene, BMLoop *l)
 +
  {
        ToolSettings *ts= scene->toolsettings;
 -      int nvert= (efa->v4)? 4: 3;
  
        if(ts->uv_flag & UV_SYNC_SELECTION) {
                if(ts->selectmode & SCE_SELECT_FACE)
 -                      EM_select_face(efa, 1);
 +                      BM_Select(em->bm, l->f, TRUE);
                else if(ts->selectmode & SCE_SELECT_EDGE)
 -                      EM_select_edge((*(&efa->e1 + i)), 1);
 +                      BM_Select(em->bm, l->e, TRUE);
                else {
 -                      (efa->v1 + i)->f |= SELECT;
 -                      (efa->v1 + (i+1)%nvert)->f |= SELECT;
 +                      BM_Select(em->bm, l->e->v1, TRUE);
 +                      BM_Select(em->bm, l->e->v2, TRUE);
                }
        }
 -      else
 -              tf->flag |= TF_SEL_MASK(i)|TF_SEL_MASK((i+1)%nvert);
 +      else {
 +              MLoopUV *luv1, *luv2;
 +
 +              luv1 = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +              luv2 = CustomData_bmesh_get(&em->bm->ldata, l->next->head.data, CD_MLOOPUV);
 +              
 +              luv1->flag |= MLOOPUV_VERTSEL;
 +              luv2->flag |= MLOOPUV_VERTSEL;
 +      }
  }
  
 -void uvedit_edge_deselect(Scene *scene, EditFace *efa, MTFace *tf, int i)
 +void uvedit_edge_deselect(BMEditMesh *em, Scene *scene, BMLoop *l)
 +
  {
        ToolSettings *ts= scene->toolsettings;
 -      int nvert= (efa->v4)? 4: 3;
  
        if(ts->uv_flag & UV_SYNC_SELECTION) {
                if(ts->selectmode & SCE_SELECT_FACE)
 -                      EM_select_face(efa, 0);
 +                      BM_Select(em->bm, l->f, FALSE);
                else if(ts->selectmode & SCE_SELECT_EDGE)
 -                      EM_select_edge((*(&efa->e1 + i)), 0);
 +                      BM_Select(em->bm, l->e, FALSE);
                else {
 -                      (efa->v1 + i)->f &= ~SELECT;
 -                      (efa->v1 + (i+1)%nvert)->f &= ~SELECT;
 +                      BM_Select(em->bm, l->e->v1, FALSE);
 +                      BM_Select(em->bm, l->e->v2, FALSE);
                }
        }
 -      else
 -              tf->flag &= ~(TF_SEL_MASK(i)|TF_SEL_MASK((i+1)%nvert));
 +      else {
 +              MLoopUV *luv1, *luv2;
 +
 +              luv1 = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +              luv2 = CustomData_bmesh_get(&em->bm->ldata, l->next->head.data, CD_MLOOPUV);
 +              
 +              luv1->flag &= ~MLOOPUV_VERTSEL;
 +              luv2->flag &= ~MLOOPUV_VERTSEL;
 +      }
  }
  
 -int uvedit_uv_selected(Scene *scene, EditFace *efa, MTFace *tf, int i)
 +int uvedit_uv_selected(BMEditMesh *em, Scene *scene, BMLoop *l)
  {
        ToolSettings *ts= scene->toolsettings;
  
        if(ts->uv_flag & UV_SYNC_SELECTION) {
                if(ts->selectmode & SCE_SELECT_FACE)
 -                      return (efa->f & SELECT);
 +                      return BM_TestHFlag(l->f, BM_SELECT);
                else
 -                      return (*(&efa->v1 + i))->f & SELECT;
 +                      return BM_TestHFlag(l->v, BM_SELECT);
 +      }
 +      else {
 +              MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +
 +              return luv->flag & MLOOPUV_VERTSEL;
        }
 -      else
 -              return tf->flag & TF_SEL_MASK(i);
  }
  
 -void uvedit_uv_select(Scene *scene, EditFace *efa, MTFace *tf, int i)
 +void uvedit_uv_select(BMEditMesh *em, Scene *scene, BMLoop *l)
  {
        ToolSettings *ts= scene->toolsettings;
  
        if(ts->uv_flag & UV_SYNC_SELECTION) {
                if(ts->selectmode & SCE_SELECT_FACE)
 -                      EM_select_face(efa, 1);
 +                      BM_Select(em->bm, l->f, TRUE);
                else
 -                      (*(&efa->v1 + i))->f |= SELECT;
 +                      BM_Select(em->bm, l->v, TRUE);
 +      }
 +      else {
 +              MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +              
 +              luv->flag |= MLOOPUV_VERTSEL;
        }
 -      else
 -              tf->flag |= TF_SEL_MASK(i);
  }
  
 -void uvedit_uv_deselect(Scene *scene, EditFace *efa, MTFace *tf, int i)
 +void uvedit_uv_deselect(BMEditMesh *em, Scene *scene, BMLoop *l)
  {
        ToolSettings *ts= scene->toolsettings;
  
        if(ts->uv_flag & UV_SYNC_SELECTION) {
                if(ts->selectmode & SCE_SELECT_FACE)
 -                      EM_select_face(efa, 0);
 +                      BM_Select(em->bm, l->f, FALSE);
                else
 -                      (*(&efa->v1 + i))->f &= ~SELECT;
 +                      BM_Select(em->bm, l->v, FALSE);
 +      }
 +      else {
 +              MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +              
 +              luv->flag &= ~MLOOPUV_VERTSEL;
        }
 -      else
 -              tf->flag &= ~TF_SEL_MASK(i);
  }
  
  /*********************** live unwrap utilities ***********************/
@@@ -478,24 -410,6 +478,24 @@@ static void uvedit_live_unwrap_update(S
  }
  
  /*********************** geometric utilities ***********************/
 +void poly_uv_center(BMEditMesh *em, BMFace *f, float cent[2])
 +{
 +      BMLoop *l;
 +      MLoopUV *luv;
 +      BMIter liter;
 +
 +      cent[0] = cent[1] = 0.0f;
 +
 +      BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, f) {
 +              luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +              cent[0] += luv->uv[0];
 +              cent[1] += luv->uv[1];
 +      }
 +
 +      cent[0] /= (float) f->len;
 +      cent[1] /= (float) f->len;
 +}
 +
  
  void uv_center(float uv[][2], float cent[2], int quad)
  {
@@@ -517,28 -431,6 +517,28 @@@ float uv_area(float uv[][2], int quad
                return area_tri_v2(uv[0], uv[1], uv[2]); 
  }
  
 +float poly_uv_area(float uv[][2], int len)
 +{
 +      //BMESH_TODO: make this not suck
 +      //maybe use scanfill? I dunno.
 +
 +      if(len >= 4)
 +              return area_tri_v2(uv[0], uv[1], uv[2]) + area_tri_v2(uv[0], uv[2], uv[3]); 
 +      else
 +              return area_tri_v2(uv[0], uv[1], uv[2]); 
 +
 +      return 1.0;
 +}
 +
 +void poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy, int len)
 +{
 +      int i;
 +      for (i=0; i<len; i++) {
 +              uv[i][0] = uv_orig[i][0]*aspx;
 +              uv[i][1] = uv_orig[i][1]*aspy;
 +      }
 +}
 +
  void uv_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy)
  {
        uv[0][0] = uv_orig[0][0]*aspx;
  
  int ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float *min, float *max)
  {
 -      EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 -      EditFace *efa;
 -      MTFace *tf;
 +      BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
 +      BMFace *efa;
 +      BMLoop *l;
 +      BMIter iter, liter;
 +      MTexPoly *tf;
 +      MLoopUV *luv;
        int sel;
  
        INIT_MINMAX2(min, max);
  
        sel= 0;
 -      for(efa= em->faces.first; efa; efa= efa->next) {
 -              tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -              if(uvedit_face_visible(scene, ima, efa, tf)) {
 -                      if(uvedit_uv_selected(scene, efa, tf, 0))                               { DO_MINMAX2(tf->uv[0], min, max); sel = 1; }
 -                      if(uvedit_uv_selected(scene, efa, tf, 1))                               { DO_MINMAX2(tf->uv[1], min, max); sel = 1; }
 -                      if(uvedit_uv_selected(scene, efa, tf, 2))                               { DO_MINMAX2(tf->uv[2], min, max); sel = 1; }
 -                      if(efa->v4 && (uvedit_uv_selected(scene, efa, tf, 3)))  { DO_MINMAX2(tf->uv[3], min, max); sel = 1; }
 +      BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +              tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +              if(!uvedit_face_visible(scene, ima, efa, tf))
 +                      continue;
 +              
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                      if (uvedit_uv_selected(em, scene, l)) {
 +                              luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                              DO_MINMAX2(luv->uv, min, max); 
 +                              sel = 1;
 +                      }
                }
        }
 -      
 -      BKE_mesh_end_editmesh(obedit->data, em);
 +
        return sel;
  }
  
  static int ED_uvedit_median(Scene *scene, Image *ima, Object *obedit, float co[3])
  {
 -      EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 -      EditFace *efa;
 -      MTFace *tf;
 +      BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
 +      BMFace *efa;
 +      BMLoop *l;
 +      BMIter iter, liter;
 +      MTexPoly *tf;
 +      MLoopUV *luv;
        unsigned int sel= 0;
  
        zero_v3(co);
 -
 -      for(efa= em->faces.first; efa; efa= efa->next) {
 -              tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -              if(uvedit_face_visible(scene, ima, efa, tf)) {
 -                      if(uvedit_uv_selected(scene, efa, tf, 0))                               { add_v3_v3(co, tf->uv[0]); sel++; }
 -                      if(uvedit_uv_selected(scene, efa, tf, 1))                               { add_v3_v3(co, tf->uv[1]); sel++; }
 -                      if(uvedit_uv_selected(scene, efa, tf, 2))                               { add_v3_v3(co, tf->uv[2]); sel++; }
 -                      if(efa->v4 && (uvedit_uv_selected(scene, efa, tf, 3)))  { add_v3_v3(co, tf->uv[3]); sel++; }
 +      BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +              tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +              if(!uvedit_face_visible(scene, ima, efa, tf))
 +                      continue;
 +              
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                      if (uvedit_uv_selected(em, scene, l)) {
 +                              add_v2_v2(co, luv->uv);
 +                              sel++;
 +                      }
                }
        }
  
        mul_v3_fl(co, 1.0f/(float)sel);
  
 -      BKE_mesh_end_editmesh(obedit->data, em);
        return (sel != 0);
  }
  
  static int uvedit_center(Scene *scene, Image *ima, Object *obedit, float *cent, char mode)
  {
 -      EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
        float min[2], max[2];
        int change= 0;
        
        }
  
        if(change) {
 -              BKE_mesh_end_editmesh(obedit->data, em);
                return 1;
        }
  
 -      BKE_mesh_end_editmesh(obedit->data, em);
        return 0;
  }
  
  /************************** find nearest ****************************/
  
  typedef struct NearestHit {
 -      EditFace *efa;
 -      MTFace *tf;
 -
 -      int vert, uv;
 -      int edge, vert2;
 +      BMFace *efa;
 +      MTexPoly *tf;
 +      BMLoop *l, *nextl;
 +      MLoopUV *luv, *nextluv;
 +      int lindex; //index of loop within face
 +      int vert1, vert2; //index in mesh of edge vertices
  } NearestHit;
  
 -static void find_nearest_uv_edge(Scene *scene, Image *ima, EditMesh *em, float co[2], NearestHit *hit)
 +static void find_nearest_uv_edge(Scene *scene, Image *ima, BMEditMesh *em, float co[2], NearestHit *hit)
  {
 -      MTFace *tf;
 -      EditFace *efa;
 -      EditVert *eve;
 +      MTexPoly *tf;
 +      BMFace *efa;
 +      BMLoop *l;
 +      BMIter iter, liter;
 +      MLoopUV *luv, *nextluv;
        float mindist, dist;
 -      int i, nverts;
 +      int i;
  
        mindist= 1e10f;
        memset(hit, 0, sizeof(*hit));
  
 -      for(i=0, eve=em->verts.first; eve; eve=eve->next, i++)
 -              eve->tmp.l = i;
 +      BM_ElemIndex_Ensure(em->bm, BM_VERT);
        
 -      for(efa= em->faces.first; efa; efa= efa->next) {
 -              tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -
 -              if(uvedit_face_visible(scene, ima, efa, tf)) {
 -                      nverts= efa->v4? 4: 3;
 -
 -                      for(i=0; i<nverts; i++) {
 -                              dist= dist_to_line_segment_v2(co, tf->uv[i], tf->uv[(i+1)%nverts]);
 +      BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +              tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +              if(!uvedit_face_visible(scene, ima, efa, tf))
 +                      continue;
 +              
 +              i = 0;
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                      nextluv = CustomData_bmesh_get(&em->bm->ldata, l->next->head.data, CD_MLOOPUV);
  
 -                              if(dist < mindist) {
 -                                      hit->tf= tf;
 -                                      hit->efa= efa;
 -                                      hit->edge= i;
 -                                      mindist= dist;
 +                      dist= dist_to_line_segment_v2(co, luv->uv, nextluv->uv);
  
 -                                      hit->vert= (*(&efa->v1 + i))->tmp.l;
 -                                      hit->vert2= (*(&efa->v1 + ((i+1)%nverts)))->tmp.l;
 -                              }
 +                      if(dist < mindist) {
 +                              hit->tf= tf;
 +                              hit->efa= efa;
 +                              
 +                              hit->l = l;
 +                              hit->nextl = l->next;
 +                              hit->luv = luv;
 +                              hit->nextluv = nextluv;
 +                              hit->lindex = i;
 +                              hit->vert1 = BM_GetIndex(hit->l->v);
 +                              hit->vert2 = BM_GetIndex(hit->l->next->v);
 +
 +                              mindist = dist;
                        }
 +
 +                      i++;
                }
        }
  }
  
 -static void find_nearest_uv_face(Scene *scene, Image *ima, EditMesh *em, float co[2], NearestHit *hit)
 +static void find_nearest_uv_face(Scene *scene, Image *ima, BMEditMesh *em, float co[2], NearestHit *hit)
  {
 -      MTFace *tf;
 -      EditFace *efa;
 +      MTexPoly *tf;
 +      BMFace *efa;
 +      BMLoop *l;
 +      BMIter iter, liter;
 +      MLoopUV *luv;
        float mindist, dist, cent[2];
 -      int i, nverts;
  
        mindist= 1e10f;
        memset(hit, 0, sizeof(*hit));
 -      
 -      for(efa= em->faces.first; efa; efa= efa->next) {
 -              tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
  
 -              if(uvedit_face_visible(scene, ima, efa, tf)) {
 -                      nverts= efa->v4? 4: 3;
 -                      cent[0]= cent[1]= 0.0f;
 +      /*this will fill in hit.vert1 and hit.vert2*/
 +      find_nearest_uv_edge(scene, ima, em, co, hit);
 +      hit->l = hit->nextl = NULL;
 +      hit->luv = hit->nextluv = NULL;
  
 -                      for(i=0; i<nverts; i++) {
 -                              add_v2_v2(cent, tf->uv[i]);
 -                      }
 +      BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +              tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +              if(!uvedit_face_visible(scene, ima, efa, tf))
 +                      continue;
 +              
 +              cent[0]= cent[1]= 0.0f;
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  
 -                      cent[0] /= nverts;
 -                      cent[1] /= nverts;
 -                      dist= fabs(co[0]- cent[0]) + fabs(co[1]- cent[1]);
 +                      add_v2_v2(cent, luv->uv);
 +              }
  
 -                      if(dist < mindist) {
 -                              hit->tf= tf;
 -                              hit->efa= efa;
 -                              mindist= dist;
 -                      }
 +              cent[0] /= efa->len;
 +              cent[1] /= efa->len;
 +              dist= fabs(co[0]- cent[0]) + fabs(co[1]- cent[1]);
 +
 +              if(dist < mindist) {
 +                      hit->tf= tf;
 +                      hit->efa= efa;
 +                      mindist= dist;
                }
        }
  }
  
 -static int nearest_uv_between(MTFace *tf, int nverts, int id, float co[2], float uv[2])
 +static int nearest_uv_between(BMEditMesh *em, BMFace *efa, int UNUSED(nverts), int id,
 +                            float co[2], float uv[2])
  {
 -      float m[3], v1[3], v2[3], c1, c2;
 -      int id1, id2;
 +      BMLoop *l;
 +      MLoopUV *luv;
 +      BMIter iter;
 +      float m[3], v1[3], v2[3], c1, c2, *uv1, *uv2, *uv3;
 +      int id1, id2, i;
  
 -      id1= (id+nverts-1)%nverts;
 -      id2= (id+nverts+1)%nverts;
 +      id1= (id+efa->len-1)%efa->len;
 +      id2= (id+efa->len+1)%efa->len;
  
        m[0]= co[0]-uv[0];
        m[1]= co[1]-uv[1];
 -      sub_v2_v2v2(v1, tf->uv[id1], tf->uv[id]);
 -      sub_v2_v2v2(v2, tf->uv[id2], tf->uv[id]);
 +
 +      i = 0;
 +      BM_ITER(l, &iter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +              luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +              
 +              if (i == id1)
 +                      uv1 = luv->uv;
 +              else if (i == id)
 +                      uv2 = luv->uv;
 +              else if (i == id2)
 +                      uv3 = luv->uv;
 +
 +              i++;
 +      }
 +
 +      sub_v3_v3v3(v1, uv1, uv);
 +      sub_v3_v3v3(v2, uv3, uv);
  
        /* m and v2 on same side of v-v1? */
        c1= v1[0]*m[1] - v1[1]*m[0];
        return (c1*c2 >= 0.0f);
  }
  
 -static void find_nearest_uv_vert(Scene *scene, Image *ima, EditMesh *em, float co[2], float penalty[2], NearestHit *hit)
 +static void find_nearest_uv_vert(Scene *scene, Image *ima, BMEditMesh *em,
 +                               float co[2], float penalty[2], NearestHit *hit)
  {
 -      EditFace *efa;
 -      EditVert *eve;
 -      MTFace *tf;
 +      BMFace *efa;
 +      BMLoop *l;
 +      BMIter iter, liter;
 +      MTexPoly *tf;
 +      MLoopUV *luv;
        float mindist, dist;
 -      int i, nverts;
 +      int i;
 +
 +      /*this will fill in hit.vert1 and hit.vert2*/
 +      find_nearest_uv_edge(scene, ima, em, co, hit);
 +      hit->l = hit->nextl = NULL;
 +      hit->luv = hit->nextluv = NULL;
  
        mindist= 1e10f;
        memset(hit, 0, sizeof(*hit));
        
 -      for(i=0, eve=em->verts.first; eve; eve=eve->next, i++)
 -              eve->tmp.l = i;
 -      
 -      for(efa= em->faces.first; efa; efa= efa->next) {
 -              tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -
 -              if(uvedit_face_visible(scene, ima, efa, tf)) {
 -                      nverts= efa->v4? 4: 3;
 +      BM_ElemIndex_Ensure(em->bm, BM_VERT);
  
 -                      for(i=0; i<nverts; i++) {
 -                              if(penalty && uvedit_uv_selected(scene, efa, tf, i))
 -                                      dist= fabsf(co[0]-tf->uv[i][0])+penalty[0] + fabsf(co[1]-tf->uv[i][1]) + penalty[1];
 -                              else
 -                                      dist= fabsf(co[0]-tf->uv[i][0]) + fabsf(co[1]-tf->uv[i][1]);
 +      BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +              tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +              if(!uvedit_face_visible(scene, ima, efa, tf))
 +                      continue;
 +              
 +              i = 0;
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  
 -                              if(dist<=mindist) {
 -                                      if(dist==mindist)
 -                                              if(!nearest_uv_between(tf, nverts, i, co, tf->uv[i]))
 -                                                      continue;
 +                      if(penalty && uvedit_uv_selected(em, scene, l))
 +                              dist= fabs(co[0]-luv->uv[0])+penalty[0] + fabs(co[1]-luv->uv[1])+penalty[1];
 +                      else
 +                              dist= fabs(co[0]-luv->uv[0]) + fabs(co[1]-luv->uv[1]);
  
 -                                      mindist= dist;
 +                      if(dist<=mindist) {
 +                              if(dist==mindist)
 +                                      if(!nearest_uv_between(em, efa, efa->len, i, co, luv->uv)) {
 +                                              i++;
 +                                              continue;
 +                                      }
  
 -                                      hit->uv= i;
 -                                      hit->tf= tf;
 -                                      hit->efa= efa;
 +                              mindist= dist;
  
 -                                      hit->vert= (*(&efa->v1 + i))->tmp.l;
 -                              }
 +                              hit->l = l;
 +                              hit->nextl = l->next;
 +                              hit->luv = luv;
 +                              hit->nextluv = CustomData_bmesh_get(&em->bm->ldata, l->next->head.data, CD_MLOOPUV);
 +                              hit->tf= tf;
 +                              hit->efa= efa;
 +                              hit->lindex = i;
 +                              hit->vert1 = BM_GetIndex(hit->l->v);
                        }
 +
 +                      i++;
                }
        }
  }
  
  int ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, float co[2], float uv[2])
  {
 -      EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 -      EditFace *efa;
 -      MTFace *tf;
 +      BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
 +      BMFace *efa;
 +      BMLoop *l;
 +      BMIter iter, liter;
 +      MTexPoly *tf;
 +      MLoopUV *luv;
        float mindist, dist;
 -      int i, nverts, found= 0;
 +      int found= 0;
  
        mindist= 1e10f;
        uv[0]= co[0];
        uv[1]= co[1];
        
 -      for(efa= em->faces.first; efa; efa= efa->next) {
 -              tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -
 -              if(uvedit_face_visible(scene, ima, efa, tf)) {
 -                      nverts= efa->v4? 4: 3;
 -
 -                      for(i=0; i<nverts; i++) {
 -                              if(uvedit_uv_selected(scene, efa, tf, i))
 -                                      continue;
 -
 -                              dist= fabs(co[0]-tf->uv[i][0]) + fabs(co[1]-tf->uv[i][1]);
 +      BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +              tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +              if(!uvedit_face_visible(scene, ima, efa, tf))
 +                      continue;
 +              
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                      dist= fabs(co[0]-luv->uv[0]) + fabs(co[1]-luv->uv[1]);
  
 -                              if(dist<=mindist) {
 -                                      mindist= dist;
 +                      if(dist<=mindist) {
 +                              mindist= dist;
  
 -                                      uv[0]= tf->uv[i][0];
 -                                      uv[1]= tf->uv[i][1];
 -                                      found= 1;
 -                              }
 +                              uv[0]= luv->uv[0];
 +                              uv[1]= luv->uv[1];
 +                              found= 1;
                        }
                }
        }
  
 -      BKE_mesh_end_editmesh(obedit->data, em);
        return found;
  }
  
@@@ -900,28 -734,26 +900,28 @@@ static void uv_vertex_loop_flag(UvMapVe
                first->flag= 1;
  }
  
 -static UvMapVert *uv_vertex_map_get(UvVertMap *vmap, EditFace *efa, int a)
 +static UvMapVert *uv_vertex_map_get(UvVertMap *vmap, BMFace *efa, int a)
  {
        UvMapVert *iterv, *first;
 -      
 -      first= EM_get_uv_map_vert(vmap, (*(&efa->v1 + a))->tmp.l);
 +      BMLoop *l;
 +
 +      l = BMIter_AtIndex(NULL, BM_LOOPS_OF_FACE, efa, a);
 +      first= EDBM_get_uv_map_vert(vmap,  BM_GetIndex(l->v));
  
        for(iterv=first; iterv; iterv=iterv->next) {
                if(iterv->separate)
                        first= iterv;
 -              if(iterv->f == efa->tmp.l)
 +              if(iterv->f == BM_GetIndex(efa))
                        return first;
        }
        
        return NULL;
  }
  
 -static int uv_edge_tag_faces(UvMapVert *first1, UvMapVert *first2, int *totface)
 +static int uv_edge_tag_faces(BMEditMesh *em, UvMapVert *first1, UvMapVert *first2, int *totface)
  {
        UvMapVert *iterv1, *iterv2;
 -      EditFace *efa;
 +      BMFace *efa;
        int tot = 0;
  
        /* count number of faces this edge has */
  
                        if(iterv1->f == iterv2->f) {
                                /* if face already tagged, don't do this edge */
 -                              efa= EM_get_face_for_index(iterv1->f);
 -                              if(efa->f1)
 +                              efa= EDBM_get_face_for_index(em, iterv1->f);
 +                              if(BMO_TestFlag(em->bm, efa, EFA_F1_FLAG))
                                        return 0;
  
                                tot++;
                                break;
  
                        if(iterv1->f == iterv2->f) {
 -                              efa= EM_get_face_for_index(iterv1->f);
 -                              efa->f1= 1;
 +                              efa= EDBM_get_face_for_index(em, iterv1->f);
 +                              BMO_SetFlag(em->bm, efa, EFA_F1_FLAG);
                                break;
                        }
                }
        return 1;
  }
  
 -static int select_edgeloop(Scene *scene, Image *ima, EditMesh *em, NearestHit *hit, float limit[2], int extend)
 +static int select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestHit *hit, float limit[2], int extend)
  {
 -      EditVert *eve;
 -      EditFace *efa;
 -      MTFace *tf;
 +      BMFace *efa;
 +      BMIter iter, liter;
 +      BMLoop *l;
 +      MTexPoly *tf;
        UvVertMap *vmap;
        UvMapVert *iterv1, *iterv2;
        int a, count, looking, nverts, starttotf, select;
  
        /* setup */
 -      EM_init_index_arrays(em, 0, 0, 1);
 -      vmap= EM_make_uv_vert_map(em, 0, 0, limit);
 +      EDBM_init_index_arrays(em, 0, 0, 1);
 +      vmap= EDBM_make_uv_vert_map(em, 0, 0, limit);
  
 -      for(count=0, eve=em->verts.first; eve; count++, eve= eve->next)
 -              eve->tmp.l = count;
 +      BM_ElemIndex_Ensure(em->bm, BM_VERT);
  
 -      for(count=0, efa= em->faces.first; efa; count++, efa= efa->next) {
 +      count = 0;
 +      BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
                if(!extend) {
 -                      tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -                      uvedit_face_deselect(scene, efa, tf);
 +                      uvedit_face_deselect(scene, em, efa);
                }
 +              
 +              BMO_ClearFlag(em->bm, efa, EFA_F1_FLAG);
  
 -              efa->tmp.l= count;
 -              efa->f1= 0;
 +              BM_SetIndex(efa, count); /* set_inline */
 +
 +              count++;
        }
 -      
 +      em->bm->elem_index_dirty &= ~BM_FACE;
 +
        /* set flags for first face and verts */
 -      nverts= (hit->efa->v4)? 4: 3;
 -      iterv1= uv_vertex_map_get(vmap, hit->efa, hit->edge);
 -      iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->edge+1)%nverts);
 +      nverts= hit->efa->len;
 +      iterv1= uv_vertex_map_get(vmap, hit->efa, hit->lindex);
 +      iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->lindex+1)%nverts);
        uv_vertex_loop_flag(iterv1);
        uv_vertex_loop_flag(iterv2);
  
        starttotf= 0;
 -      uv_edge_tag_faces(iterv1, iterv2, &starttotf);
 +      uv_edge_tag_faces(em, iterv1, iterv2, &starttotf);
  
        /* sorry, first edge isnt even ok */
        if(iterv1->flag==0 && iterv2->flag==0) looking= 0;
                looking= 0;
  
                /* find correct valence edges which are not tagged yet, but connect to tagged one */
 -              for(efa= em->faces.first; efa; efa=efa->next) {
 -                      tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
  
 -                      if(!efa->f1 && uvedit_face_visible(scene, ima, efa, tf)) {
 -                              nverts= (efa->v4)? 4: 3;
 +              BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +                      tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +
 +                      if(!BMO_TestFlag(em->bm, efa, EFA_F1_FLAG) && uvedit_face_visible(scene, ima, efa, tf)) {
 +                              nverts= efa->len;
                                for(a=0; a<nverts; a++) {
                                        /* check face not hidden and not tagged */
                                        iterv1= uv_vertex_map_get(vmap, efa, a);
                                        iterv2= uv_vertex_map_get(vmap, efa, (a+1)%nverts);
 +                                      
 +                                      if (!iterv1 || !iterv2)
 +                                              continue;
  
                                        /* check if vertex is tagged and has right valence */
                                        if(iterv1->flag || iterv2->flag) {
 -                                              if(uv_edge_tag_faces(iterv1, iterv2, &starttotf)) {
 +                                              if(uv_edge_tag_faces(em, iterv1, iterv2, &starttotf)) {
                                                        looking= 1;
 -                                                      efa->f1= 1;
 +                                                      BMO_SetFlag(em->bm, efa, EFA_F1_FLAG);
  
                                                        uv_vertex_loop_flag(iterv1);
                                                        uv_vertex_loop_flag(iterv2);
        }
  
        /* do the actual select/deselect */
 -      nverts= (hit->efa->v4)? 4: 3;
 -      iterv1= uv_vertex_map_get(vmap, hit->efa, hit->edge);
 -      iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->edge+1)%nverts);
 +      nverts= hit->efa->len;
 +      iterv1= uv_vertex_map_get(vmap, hit->efa, hit->lindex);
 +      iterv2= uv_vertex_map_get(vmap, hit->efa, (hit->lindex+1)%nverts);
        iterv1->flag= 1;
        iterv2->flag= 1;
  
        if(extend) {
 -              tf= CustomData_em_get(&em->fdata, hit->efa->data, CD_MTFACE);
 -
 -              if(uvedit_uv_selected(scene, hit->efa, tf, hit->edge))
 +              if(uvedit_uv_selected(em, scene, hit->l))
                        select= 0;
                else
                        select= 1;
        else
                select= 1;
        
 -      for(efa= em->faces.first; efa; efa=efa->next) {
 -              tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 +      BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +              tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
  
 -              nverts= (efa->v4)? 4: 3;
 -              for(a=0; a<nverts; a++) {
 +              a = 0;
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
                        iterv1= uv_vertex_map_get(vmap, efa, a);
  
                        if(iterv1->flag) {
 -                              if(select) uvedit_uv_select(scene, efa, tf, a);
 -                              else uvedit_uv_deselect(scene, efa, tf, a);
 +                              if(select) uvedit_uv_select(em, scene, l);
 +                              else uvedit_uv_deselect(em, scene, l);
                        }
 +
 +                      a++;
                }
        }
  
        /* cleanup */
 -      EM_free_uv_vert_map(vmap);
 -      EM_free_index_arrays();
 +      EDBM_free_uv_vert_map(vmap);
 +      EDBM_free_index_arrays(em);
  
        return (select)? 1: -1;
  }
  
  /*********************** linked select ***********************/
  
 -static void select_linked(Scene *scene, Image *ima, EditMesh *em, float limit[2], NearestHit *hit, int extend)
 +static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, float limit[2], NearestHit *hit, int extend)
  {
 -      EditFace *efa;
 -      MTFace *tf;
 +      BMFace *efa;
 +      BMLoop *l;
 +      BMIter iter, liter;
 +      MTexPoly *tf;
 +      MLoopUV *luv;
        UvVertMap *vmap;
        UvMapVert *vlist, *iterv, *startv;
        int i, nverts, stacksize= 0, *stack;
        unsigned int a;
        char *flag;
  
 -      EM_init_index_arrays(em, 0, 0, 1); /* we can use this too */
 -      vmap= EM_make_uv_vert_map(em, 1, 0, limit);
 +      EDBM_init_index_arrays(em, 0, 0, 1); /* we can use this too */
 +      vmap= EDBM_make_uv_vert_map(em, 1, 1, limit);
 +
        if(vmap == NULL)
                return;
  
 -      stack= MEM_mallocN(sizeof(*stack) * em->totface, "UvLinkStack");
 -      flag= MEM_callocN(sizeof(*flag) * em->totface, "UvLinkFlag");
 +      stack= MEM_mallocN(sizeof(*stack)*(em->bm->totface+1), "UvLinkStack");
 +      flag= MEM_callocN(sizeof(*flag)*em->bm->totface, "UvLinkFlag");
  
        if(!hit) {
 -              for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
 -                      tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 +              a = 0;
 +              BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +                      tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
  
 -                      if(uvedit_face_visible(scene, ima, efa, tf)) {
 -                              const char select_flag= efa->v4 ? (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3);
 -                              if(tf->flag & select_flag) {
 -                                      stack[stacksize]= a;
 -                                      stacksize++;
 -                                      flag[a]= 1;
 +                      if(uvedit_face_visible(scene, ima, efa, tf)) { 
 +                              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +
 +                                      if (luv->flag & MLOOPUV_VERTSEL) {
 +                                              stack[stacksize]= a;
 +                                              stacksize++;
 +                                              flag[a]= 1;
 +
 +                                              break;
 +                                      }
                                }
                        }
                }
 +              a++;
        }
        else {
 -              for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
 +              a = 0;
 +              BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
                        if(efa == hit->efa) {
                                stack[stacksize]= a;
                                stacksize++;
                                flag[a]= 1;
                                break;
                        }
 +
 +                      a++;
                }
        }
  
        while(stacksize > 0) {
 +              int j;
 +
                stacksize--;
                a= stack[stacksize];
 +              
 +              j = 0;
 +              BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +                      if(j==a)
 +                              break;
 +
 +                      j++;
 +              }
  
 -              efa = EM_get_face_for_index(a);
 +              nverts= efa->len;
  
 -              nverts= efa->v4? 4: 3;
 +              i = 0;
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
  
 -              for(i=0; i<nverts; i++) {
                        /* make_uv_vert_map_EM sets verts tmp.l to the indices */
 -                      vlist= EM_get_uv_map_vert(vmap, (*(&efa->v1 + i))->tmp.l);
 +                      vlist= EDBM_get_uv_map_vert(vmap, BM_GetIndex(l->v));
                        
                        startv= vlist;
  
                                        stacksize++;
                                }
                        }
 +
 +                      i++;
                }
        }
  
 -      if(!extend) {
 -              for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
 -                      tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -                      if(flag[a])
 -                              tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
 -                      else
 -                              tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
 +      if(!extend) {           
 +              a = 0;
 +              BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +                      BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                              luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                              
 +                              if (flag[a])
 +                                      luv->flag |= MLOOPUV_VERTSEL;
 +                              else
 +                                      luv->flag &= ~MLOOPUV_VERTSEL;
 +                      }
 +                      a++;
                }
        }
        else {
 -              for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
 -                      if(flag[a]) {
 -                              const char select_flag= efa->v4 ? (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3);
 -                              tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -                              if((tf->flag & select_flag))
 +              a = 0;
 +              BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +                      if (!flag[a]) {
 +                              a++;
 +                              continue;
 +                      }
 +                      
 +                      BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                              luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                                              
 +                              if (luv->flag & MLOOPUV_VERTSEL)
                                        break;
                        }
 +                      
 +                      if (l)
 +                              break;
 +                      
 +                      a++;
                }
  
                if(efa) {
 -                      for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
 -                              if(flag[a]) {
 -                                      tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -                                      tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
 +                      a = 0;
 +                      BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +                              if (!flag[a]) {
 +                                      a++;
 +                                      continue;
 +                              }
 +
 +                              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                                      
 +                                      luv->flag &= ~MLOOPUV_VERTSEL;
                                }
 +
 +                              a++;
                        }
                }
                else {
 -                      for(a=0, efa= em->faces.first; efa; efa= efa->next, a++) {
 -                              if(flag[a]) {
 -                                      tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -                                      tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
 +                      a = 0;
 +                      BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +                              if (!flag[a]) {
 +                                      a++;
 +                                      continue;
 +                              }
 +
 +                              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                                      
 +                                      luv->flag |= MLOOPUV_VERTSEL;
                                }
 +
 +                              a++;
                        }
                }
        }
        
        MEM_freeN(stack);
        MEM_freeN(flag);
 -      EM_free_uv_vert_map(vmap);
 -      EM_free_index_arrays();
 +      EDBM_free_uv_vert_map(vmap);
 +      EDBM_free_index_arrays(em);
  }
  
  /* ******************** align operator **************** */
@@@ -1277,34 -1041,32 +1277,34 @@@ static void weld_align_uv(bContext *C, 
        Scene *scene;
        Object *obedit;
        Image *ima;
 -      EditMesh *em;
 -      EditFace *efa;
 -      MTFace *tf;
 +      BMEditMesh *em;
 +      BMFace *efa;
 +      BMLoop *l;
 +      BMIter iter, liter;
 +      MTexPoly *tf;
 +      MLoopUV *luv;
        float cent[2], min[2], max[2];
        
        scene= CTX_data_scene(C);
        obedit= CTX_data_edit_object(C);
 -      em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 +      em= ((Mesh*)obedit->data)->edit_btmesh;
        ima= CTX_data_edit_image(C);
        sima= CTX_wm_space_image(C);
  
        INIT_MINMAX2(min, max);
  
        if(tool == 'a') {
 -              for(efa= em->faces.first; efa; efa= efa->next) {
 -                      tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 +              BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +                      tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
  
 -                      if(uvedit_face_visible(scene, ima, efa, tf)) {
 -                              if(uvedit_uv_selected(scene, efa, tf, 0))
 -                                      DO_MINMAX2(tf->uv[0], min, max)
 -                              if(uvedit_uv_selected(scene, efa, tf, 1))
 -                                      DO_MINMAX2(tf->uv[1], min, max)
 -                              if(uvedit_uv_selected(scene, efa, tf, 2))
 -                                      DO_MINMAX2(tf->uv[2], min, max)
 -                              if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3))
 -                                      DO_MINMAX2(tf->uv[3], min, max)
 +                      if(!uvedit_face_visible(scene, ima, efa, tf))
 +                              continue;
 +
 +                      BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                              if (uvedit_uv_selected(em, scene, l)) {
 +                                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                                      DO_MINMAX2(luv->uv, min, max)
 +                              }
                        }
                }
  
        uvedit_center(scene, ima, obedit, cent, 0);
  
        if(tool == 'x' || tool == 'w') {
 -              for(efa= em->faces.first; efa; efa= efa->next) {
 -                      tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -                      if(uvedit_face_visible(scene, ima, efa, tf)) {
 -                              if(uvedit_uv_selected(scene, efa, tf, 0))
 -                                      tf->uv[0][0]= cent[0];
 -                              if(uvedit_uv_selected(scene, efa, tf, 1))
 -                                      tf->uv[1][0]= cent[0];
 -                              if(uvedit_uv_selected(scene, efa, tf, 2))
 -                                      tf->uv[2][0]= cent[0];
 -                              if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3))
 -                                      tf->uv[3][0]= cent[0];
 +              BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +                      tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +                      if(!uvedit_face_visible(scene, ima, efa, tf))
 +                              continue;
 +
 +                      BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                              if (uvedit_uv_selected(em, scene, l)) {
 +                                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                                      luv->uv[0] = cent[0];
 +                              }
 +
                        }
                }
        }
  
        if(tool == 'y' || tool == 'w') {
 -              for(efa= em->faces.first; efa; efa= efa->next) {
 -                      tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -                      if(uvedit_face_visible(scene, ima, efa, tf)) {
 -                              if(uvedit_uv_selected(scene, efa, tf, 0))
 -                                      tf->uv[0][1]= cent[1];
 -                              if(uvedit_uv_selected(scene, efa, tf, 1))
 -                                      tf->uv[1][1]= cent[1];
 -                              if(uvedit_uv_selected(scene, efa, tf, 2))
 -                                      tf->uv[2][1]= cent[1];
 -                              if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3))
 -                                      tf->uv[3][1]= cent[1];
 +              BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +                      tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +                      if(!uvedit_face_visible(scene, ima, efa, tf))
 +                              continue;
 +
 +                      BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                              if (uvedit_uv_selected(em, scene, l)) {
 +                                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                                      luv->uv[1] = cent[1];
 +                              }
 +
                        }
                }
        }
  
 +#if 0 // BMESH_TODO
 +
        if(tool == 's' || tool == 't' || tool == 'u') {
                 /* pass 1&2 variables */
                int i, j;
                }
        }
  
 +#endif
 +
        uvedit_live_unwrap_update(sima, scene, obedit);
        DAG_id_tag_update(obedit->data, 0);
        WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
 -
 -      BKE_mesh_end_editmesh(obedit->data, em);
  }
  
  static int align_exec(bContext *C, wmOperator *op)
@@@ -1546,43 -1306,40 +1546,43 @@@ typedef struct UVVertAverage 
  
  static int stitch_exec(bContext *C, wmOperator *op)
  {
 -      SpaceImage *sima;
        Scene *scene;
        Object *obedit;
 -      EditMesh *em;
 -      EditFace *efa;
 -      EditVert *eve;
 +      BMEditMesh *em;
 +      BMFace *efa;
 +      BMLoop *l;
 +      BMIter iter, liter;
 +      BMVert *eve;
        Image *ima;
 -      MTFace *tf;
 +      SpaceImage *sima= CTX_wm_space_image(C);
 +      MTexPoly *tf;
 +      MLoopUV *luv;
  
        scene= CTX_data_scene(C);
        obedit= CTX_data_edit_object(C);
 -      em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 +      em= ((Mesh*)obedit->data)->edit_btmesh;
        ima= CTX_data_edit_image(C);
        sima= CTX_wm_space_image(C);
        
        if(RNA_boolean_get(op->ptr, "use_limit")) {
                UvVertMap *vmap;
                UvMapVert *vlist, *iterv;
 -              float newuv[2], limit[2];
 +              float newuv[2], limit[2], pixels;
                int a, vtot;
  
 -              limit[0]= RNA_float_get(op->ptr, "limit");
 -              limit[1]= limit[0];
 +              pixels= RNA_float_get(op->ptr, "limit");
 +              uvedit_pixel_to_float(sima, limit, pixels);
  
 -              EM_init_index_arrays(em, 0, 0, 1);
 -              vmap= EM_make_uv_vert_map(em, 1, 0, limit);
 +              EDBM_init_index_arrays(em, 0, 0, 1);
 +              vmap= EDBM_make_uv_vert_map(em, 1, 0, limit);
  
                if(vmap == NULL) {
 -                      BKE_mesh_end_editmesh(obedit->data, em);
                        return OPERATOR_CANCELLED;
                }
 -
 -              for(a=0, eve= em->verts.first; eve; a++, eve= eve->next) {
 -                      vlist= EM_get_uv_map_vert(vmap, a);
 +              
 +              a = 0;
 +              BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
 +                      vlist= EDBM_get_uv_map_vert(vmap, a);
  
                        while(vlist) {
                                newuv[0]= 0; newuv[1]= 0;
                                        if((iterv != vlist) && iterv->separate)
                                                break;
  
 -                                      efa = EM_get_face_for_index(iterv->f);
 -                                      tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 +                                      efa = EDBM_get_face_for_index(em, iterv->f);
 +                                      tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
                                        
 -                                      if(uvedit_uv_selected(scene, efa, tf, iterv->tfindex)) {
 -                                              newuv[0] += tf->uv[iterv->tfindex][0];
 -                                              newuv[1] += tf->uv[iterv->tfindex][1];
 +                                      l = BMIter_AtIndex(em->bm, BM_LOOPS_OF_FACE, efa, iterv->tfindex);
 +                                      if (uvedit_uv_selected(em, scene, l)) {
 +                                              luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +
 +                                              newuv[0] += luv->uv[0];
 +                                              newuv[1] += luv->uv[1];
                                                vtot++;
                                        }
                                }
                                                if((iterv != vlist) && iterv->separate)
                                                        break;
  
 -                                              efa = EM_get_face_for_index(iterv->f);
 -                                              tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 +                                              efa = EDBM_get_face_for_index(em, iterv->f);
 +                                              tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +                                              
 +                                              l = BMIter_AtIndex(em->bm, BM_LOOPS_OF_FACE, efa, iterv->tfindex);
 +                                              if (uvedit_uv_selected(em, scene, l)) {
 +                                                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  
 -                                              if(uvedit_uv_selected(scene, efa, tf, iterv->tfindex)) {
 -                                                      tf->uv[iterv->tfindex][0]= newuv[0];
 -                                                      tf->uv[iterv->tfindex][1]= newuv[1];
 +                                                      luv->uv[0] = newuv[0];
 +                                                      luv->uv[1] = newuv[1];
 +                                                      vtot++;
                                                }
                                        }
                                }
  
                                vlist= iterv;
                        }
 +
 +                      a++;
                }
  
 -              EM_free_uv_vert_map(vmap);
 -              EM_free_index_arrays();
 +              EDBM_free_uv_vert_map(vmap);
 +              EDBM_free_index_arrays(em);
        }
        else {
                UVVertAverage *uv_average, *uvav;
 -              int count;
  
 -              // index and count verts
 -              for(count=0, eve=em->verts.first; eve; count++, eve= eve->next)
 -                      eve->tmp.l = count;
 -              
 -              uv_average= MEM_callocN(sizeof(UVVertAverage)*count, "Stitch");
 +              BM_ElemIndex_Ensure(em->bm, BM_VERT);
 +
 +              uv_average= MEM_callocN(sizeof(UVVertAverage)*em->bm->totvert, "Stitch");
                
                // gather uv averages per vert
 -              for(efa= em->faces.first; efa; efa= efa->next) {
 -                      tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -
 -                      if(uvedit_face_visible(scene, ima, efa, tf)) {
 -                              if(uvedit_uv_selected(scene, efa, tf, 0)) {
 -                                      uvav = uv_average + efa->v1->tmp.l;
 -                                      uvav->count++;
 -                                      uvav->uv[0] += tf->uv[0][0];
 -                                      uvav->uv[1] += tf->uv[0][1];
 -                              }
 -
 -                              if(uvedit_uv_selected(scene, efa, tf, 1)) {
 -                                      uvav = uv_average + efa->v2->tmp.l;
 -                                      uvav->count++;
 -                                      uvav->uv[0] += tf->uv[1][0];
 -                                      uvav->uv[1] += tf->uv[1][1];
 -                              }
 -
 -                              if(uvedit_uv_selected(scene, efa, tf, 2)) {
 -                                      uvav = uv_average + efa->v3->tmp.l;
 -                                      uvav->count++;
 -                                      uvav->uv[0] += tf->uv[2][0];
 -                                      uvav->uv[1] += tf->uv[2][1];
 -                              }
 +              BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +                      tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +                      if(!uvedit_face_visible(scene, ima, efa, tf))
 +                              continue;
 +                      
 +                      BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                              if(uvedit_uv_selected(em, scene, l)) {
 +                                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                                      uvav = uv_average + BM_GetIndex(l->v);
  
 -                              if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) {
 -                                      uvav = uv_average + efa->v4->tmp.l;
                                        uvav->count++;
 -                                      uvav->uv[0] += tf->uv[3][0];
 -                                      uvav->uv[1] += tf->uv[3][1];
 +                                      uvav->uv[0] += luv->uv[0];
 +                                      uvav->uv[1] += luv->uv[1];
                                }
                        }
                }
                
                // apply uv welding
 -              for(efa= em->faces.first; efa; efa= efa->next) {
 -                      tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -
 -                      if(uvedit_face_visible(scene, ima, efa, tf)) {
 -                              if(uvedit_uv_selected(scene, efa, tf, 0)) {
 -                                      uvav = uv_average + efa->v1->tmp.l;
 -                                      tf->uv[0][0] = uvav->uv[0]/uvav->count;
 -                                      tf->uv[0][1] = uvav->uv[1]/uvav->count;
 -                              }
 -
 -                              if(uvedit_uv_selected(scene, efa, tf, 1)) {
 -                                      uvav = uv_average + efa->v2->tmp.l;
 -                                      tf->uv[1][0] = uvav->uv[0]/uvav->count;
 -                                      tf->uv[1][1] = uvav->uv[1]/uvav->count;
 -                              }
 -
 -                              if(uvedit_uv_selected(scene, efa, tf, 2)) {
 -                                      uvav = uv_average + efa->v3->tmp.l;
 -                                      tf->uv[2][0] = uvav->uv[0]/uvav->count;
 -                                      tf->uv[2][1] = uvav->uv[1]/uvav->count;
 -                              }
 -
 -                              if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) {
 -                                      uvav = uv_average + efa->v4->tmp.l;
 -                                      tf->uv[3][0] = uvav->uv[0]/uvav->count;
 -                                      tf->uv[3][1] = uvav->uv[1]/uvav->count;
 +              BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +                      tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +                      if(!uvedit_face_visible(scene, ima, efa, tf))
 +                              continue;
 +                      
 +                      BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                              if(uvedit_uv_selected(em, scene, l)) {
 +                                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                                      uvav = uv_average + BM_GetIndex(l->v);
 +                                      luv->uv[0] = uvav->uv[0]/uvav->count;
 +                                      luv->uv[1] = uvav->uv[1]/uvav->count;
                                }
                        }
                }
        DAG_id_tag_update(obedit->data, 0);
        WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
  
 -      BKE_mesh_end_editmesh(obedit->data, em);
        return OPERATOR_FINISHED;
  }
  
@@@ -1700,7 -1484,7 +1700,7 @@@ static void UV_OT_stitch(wmOperatorTyp
  
        /* properties */
        RNA_def_boolean(ot->srna, "use_limit", 1, "Use Limit", "Stitch UVs within a specified limit distance");
 -      RNA_def_float(ot->srna, "limit", 0.01f, 0.0f, FLT_MAX, "Limit", "Limit distance in normalized coordinates", -FLT_MAX, FLT_MAX);
 +      RNA_def_float(ot->srna, "limit", 20.0, 0.0f, FLT_MAX, "Limit", "Limit distance in image pixels", -FLT_MAX, FLT_MAX);
  }
  
  /* ******************** (de)select all operator **************** */
@@@ -1710,50 -1494,43 +1710,50 @@@ static void select_all_perform(bContex
        Scene *scene;
        ToolSettings *ts;
        Object *obedit;
 -      EditMesh *em;
 -      EditFace *efa;
 +      BMEditMesh *em;
 +      BMFace *efa;
 +      BMLoop *l;
 +      BMIter iter, liter;
        Image *ima;
 -      MTFace *tf;
 +      MTexPoly *tf;
 +      MLoopUV *luv;
        
        scene= CTX_data_scene(C);
        ts= CTX_data_tool_settings(C);
        obedit= CTX_data_edit_object(C);
 -      em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 +      em= ((Mesh*)obedit->data)->edit_btmesh;
        ima= CTX_data_edit_image(C);
        
        if(ts->uv_flag & UV_SYNC_SELECTION) {
 +
                switch (action) {
                case SEL_TOGGLE:
 -                      EM_toggle_select_all(em);
 +                      EDBM_toggle_select_all(((Mesh*)obedit->data)->edit_btmesh);
                        break;
                case SEL_SELECT:
 -                      EM_select_all(em);
 +                      EDBM_set_flag_all(em, BM_SELECT);
                        break;
                case SEL_DESELECT:
 -                      EM_deselect_all(em);
 +                      EDBM_clear_flag_all(em, BM_SELECT);
                        break;
                case SEL_INVERT:
 -                      EM_select_swap(em);
 +                      EDBM_select_swap(em);
                        break;
                }
        }
        else {
 -
                if (action == SEL_TOGGLE) {
                        action = SEL_SELECT;
 -                      for(efa= em->faces.first; efa; efa= efa->next) {
 -                              const char select_flag= efa->v4 ? (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3);
 -                              tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 +                      BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +                              tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +      
 +                              if(!uvedit_face_visible(scene, ima, efa, tf))
 +                                      continue;
 +
 +                              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  
 -                              if(uvedit_face_visible(scene, ima, efa, tf)) {
 -                                      if(tf->flag & select_flag) {
 +                                      if (luv->flag & MLOOPUV_VERTSEL) {
                                                action = SEL_DESELECT;
                                                break;
                                        }
                        }
                }
        
 -              for(efa= em->faces.first; efa; efa= efa->next) {
 -                      tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 +              
 +              BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +                      tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
  
 -                      if(uvedit_face_visible(scene, ima, efa, tf)) {
 -                              const char select_flag= efa->v4 ? (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3);
 +                      if(!uvedit_face_visible(scene, ima, efa, tf))
 +                              continue;
 +
 +                      BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                              luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  
                                switch (action) {
                                case SEL_SELECT:
 -                                      tf->flag |= select_flag;
 +                                      luv->flag |= MLOOPUV_VERTSEL;
                                        break;
                                case SEL_DESELECT:
 -                                      tf->flag &= ~select_flag;
 +                                      luv->flag &= ~MLOOPUV_VERTSEL;
                                        break;
                                case SEL_INVERT:
 -                                      tf->flag ^= select_flag;
 +                                      luv->flag ^= MLOOPUV_VERTSEL;
                                        break;
                                }
                        }
  static int select_all_exec(bContext *C, wmOperator *op)
  {
        Object *obedit= CTX_data_edit_object(C);
 -      EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
        int action= RNA_enum_get(op->ptr, "action");
  
        select_all_perform(C, action);
  
        WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
  
 -      BKE_mesh_end_editmesh(obedit->data, em);
        return OPERATOR_FINISHED;
  }
  
@@@ -1816,7 -1591,7 +1816,7 @@@ static void UV_OT_select_all(wmOperator
  
  /* ******************** mouse select operator **************** */
  
 -static int sticky_select(float *limit, int hitv[4], int v, float *hituv[4], float *uv, int sticky)
 +static int sticky_select(float *limit, int hitv[4], int v, float *hituv[4], float *uv, int sticky, int hitlen)
  {
        int i;
  
        if(sticky == SI_STICKY_DISABLE)
                return 0;
  
 -      for(i=0; i<4; i++) {
 +      for(i=0; i<hitlen; i++) {
                if(hitv[i] == v) {
                        if(sticky == SI_STICKY_LOC) {
                                if(fabsf(hituv[i][0]-uv[0]) < limit[0] && fabsf(hituv[i][1]-uv[1]) < limit[1])
@@@ -1846,19 -1621,13 +1846,19 @@@ static int mouse_select(bContext *C, fl
        ToolSettings *ts= CTX_data_tool_settings(C);
        Object *obedit= CTX_data_edit_object(C);
        Image *ima= CTX_data_edit_image(C);
 -      EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 -      EditFace *efa;
 -      MTFace *tf;
 +      BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
 +      BMFace *efa;
 +      BMLoop *l;
 +      BMIter iter, liter;
 +      MTexPoly *tf;
 +      MLoopUV *luv;
        NearestHit hit;
 -      int a, i, select = 1, selectmode, sticky, sync, hitv[4], nvert;
 -      int flush = 0; /* 0 == dont flush, 1 == sel, -1 == desel;  only use when selection sync is enabled */
 -      float limit[2], *hituv[4], penalty[2];
 +      int i, select = 1, selectmode, sticky, sync, *hitv=NULL, nvert;
 +      BLI_array_declare(hitv);
 +      int flush = 0, hitlen=0; /* 0 == dont flush, 1 == sel, -1 == desel;  only use when selection sync is enabled */
 +      float limit[2], **hituv = NULL;
 +      BLI_array_declare(hituv);
 +      float penalty[2];
  
        /* notice 'limit' is the same no matter the zoom level, since this is like
         * remove doubles and could annoying if it joined points when zoomed out.
                /* find edge */
                find_nearest_uv_edge(scene, ima, em, co, &hit);
                if(hit.efa == NULL) {
 -                      BKE_mesh_end_editmesh(obedit->data, em);
 +                      BLI_array_free(hitv);
 +                      BLI_array_free(hituv);
                        return OPERATOR_CANCELLED;
                }
 +
 +              hitlen = 0;
        }
        else if(selectmode == UV_SELECT_VERTEX) {
                /* find vertex */
                find_nearest_uv_vert(scene, ima, em, co, penalty, &hit);
                if(hit.efa == NULL) {
 -                      BKE_mesh_end_editmesh(obedit->data, em);
 +                      BLI_array_free(hitv);
 +                      BLI_array_free(hituv);
                        return OPERATOR_CANCELLED;
                }
  
                /* mark 1 vertex as being hit */
 -              for(i=0; i<4; i++)
 +              for(i=0; i<hit.efa->len; i++) {
 +                      BLI_array_growone(hitv);
 +                      BLI_array_growone(hituv);
                        hitv[i]= 0xFFFFFFFF;
 +              }
 +
 +              hitv[hit.lindex]= hit.vert1;
 +              hituv[hit.lindex]= hit.luv->uv;
  
 -              hitv[hit.uv]= hit.vert;
 -              hituv[hit.uv]= hit.tf->uv[hit.uv];
 +              hitlen = hit.efa->len;
        }
        else if(selectmode == UV_SELECT_EDGE) {
                /* find edge */
                find_nearest_uv_edge(scene, ima, em, co, &hit);
                if(hit.efa == NULL) {
 -                      BKE_mesh_end_editmesh(obedit->data, em);
 +                      BLI_array_free(hitv);
 +                      BLI_array_free(hituv);
                        return OPERATOR_CANCELLED;
                }
  
                /* mark 2 edge vertices as being hit */
 -              for(i=0; i<4; i++)
 +              for(i=0; i<hit.efa->len; i++) {
 +                      BLI_array_growone(hitv);
 +                      BLI_array_growone(hituv);
                        hitv[i]= 0xFFFFFFFF;
 +              }
 +
 +              nvert= hit.efa->len;
  
 -              nvert= (hit.efa->v4)? 4: 3;
 +              hitv[hit.lindex]= hit.vert1;
 +              hitv[(hit.lindex+1)%nvert]= hit.vert2;
 +              hituv[hit.lindex]= hit.luv->uv;
 +              hituv[(hit.lindex+1)%nvert]= hit.nextluv->uv;
  
 -              hitv[hit.edge]= hit.vert;
 -              hitv[(hit.edge+1)%nvert]= hit.vert2;
 -              hituv[hit.edge]= hit.tf->uv[hit.edge];
 -              hituv[(hit.edge+1)%nvert]= hit.tf->uv[(hit.edge+1)%nvert];
 +              hitlen = hit.efa->len;
        }
        else if(selectmode == UV_SELECT_FACE) {
                /* find face */
                find_nearest_uv_face(scene, ima, em, co, &hit);
                if(hit.efa == NULL) {
 -                      BKE_mesh_end_editmesh(obedit->data, em);
 +                      BLI_array_free(hitv);
 +                      BLI_array_free(hituv);
                        return OPERATOR_CANCELLED;
                }
                
                /* make active */
 -              EM_set_actFace(em, hit.efa);
 +              BM_set_actFace(em->bm, hit.efa);
  
                /* mark all face vertices as being hit */
 -              for(i=0; i<4; i++)
 -                      hituv[i]= hit.tf->uv[i];
 +              i = 0;
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, hit.efa) {
 +                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  
 -              hitv[0]= hit.efa->v1->tmp.l;
 -              hitv[1]= hit.efa->v2->tmp.l;
 -              hitv[2]= hit.efa->v3->tmp.l;
 +                      BLI_array_growone(hitv);
 +                      BLI_array_growone(hituv);
 +                      hituv[i]= luv->uv;
 +                      hitv[i] = BM_GetIndex(l->v);
 +                      i++;
 +              }
                
 -              if(hit.efa->v4) hitv[3]= hit.efa->v4->tmp.l;
 -              else hitv[3]= 0xFFFFFFFF;
 +              hitlen = hit.efa->len;
        }
        else if(selectmode == UV_SELECT_ISLAND) {
                find_nearest_uv_vert(scene, ima, em, co, NULL, &hit);
  
                if(hit.efa==NULL) {
 -                      BKE_mesh_end_editmesh(obedit->data, em);
 +                      BLI_array_free(hitv);
 +                      BLI_array_free(hituv);
                        return OPERATOR_CANCELLED;
                }
 +
 +              hitlen = 0;
        }
        else {
 -              BKE_mesh_end_editmesh(obedit->data, em);
 +              hitlen = 0;
 +              BLI_array_free(hitv);
 +              BLI_array_free(hituv);
                return OPERATOR_CANCELLED;
        }
  
        else if(extend) {
                if(selectmode == UV_SELECT_VERTEX) {
                        /* (de)select uv vertex */
 -                      if(uvedit_uv_selected(scene, hit.efa, hit.tf, hit.uv)) {
 -                              uvedit_uv_deselect(scene, hit.efa, hit.tf, hit.uv);
 +                      if(uvedit_uv_selected(em, scene, hit.l)) {
 +                              uvedit_uv_deselect(em, scene, hit.l);
                                select= 0;
                        }
                        else {
 -                              uvedit_uv_select(scene, hit.efa, hit.tf, hit.uv);
 +                              uvedit_uv_select(em, scene, hit.l);
                                select= 1;
                        }
                        flush = 1;
                }
                else if(selectmode == UV_SELECT_EDGE) {
                        /* (de)select edge */
 -                      if(uvedit_edge_selected(scene, hit.efa, hit.tf, hit.edge)) {
 -                              uvedit_edge_deselect(scene, hit.efa, hit.tf, hit.edge);
 +                      if(uvedit_edge_selected(em, scene, hit.l)) {
 +                              uvedit_edge_deselect(em, scene, hit.l);
                                select= 0;
                        }
                        else {
 -                              uvedit_edge_select(scene, hit.efa, hit.tf, hit.edge);
 +                              uvedit_edge_select(em, scene, hit.l);
                                select= 1;
                        }
                        flush = 1;
                }
                else if(selectmode == UV_SELECT_FACE) {
                        /* (de)select face */
 -                      if(uvedit_face_selected(scene, hit.efa, hit.tf)) {
 -                              uvedit_face_deselect(scene, hit.efa, hit.tf);
 +                      if(uvedit_face_selected(scene, em, hit.efa)) {
 +                              uvedit_face_deselect(scene, em, hit.efa);
                                select= 0;
                        }
                        else {
 -                              uvedit_face_select(scene, hit.efa, hit.tf);
 +                              uvedit_face_select(scene, em, hit.efa);
                                select= 1;
                        }
                        flush = -1;
  
                /* (de)select sticky uv nodes */
                if(sticky != SI_STICKY_DISABLE) {
 -                      EditVert *ev;
 -                      
 -                      for(a=0, ev=em->verts.first; ev; ev = ev->next, a++)
 -                              ev->tmp.l = a;
 -                      
 +
 +                      BM_ElemIndex_Ensure(em->bm, BM_VERT);
 +
                        /* deselect */
                        if(select==0) {
 -                              for(efa= em->faces.first; efa; efa= efa->next) {
 -                                      tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -
 -                                      if(uvedit_face_visible(scene, ima, efa, tf)) {
 -                                              if(sticky_select(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
 -                                                      uvedit_uv_deselect(scene, efa, tf, 0);
 -                                              if(sticky_select(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
 -                                                      uvedit_uv_deselect(scene, efa, tf, 1);
 -                                              if(sticky_select(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
 -                                                      uvedit_uv_deselect(scene, efa, tf, 2);
 -                                              if(efa->v4)
 -                                                      if(sticky_select(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
 -                                                              uvedit_uv_deselect(scene, efa, tf, 3);
 +                              BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +                                      tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +                                      if(!uvedit_face_visible(scene, ima, efa, tf))
 +                                              continue;
 +
 +                                      BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                                              luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                                              if(sticky_select(limit, hitv, BM_GetIndex(l->v), hituv, luv->uv, sticky, hitlen))
 +                                                      uvedit_uv_deselect(em, scene, l);
                                        }
                                }
                                flush = -1;
                        }
                        /* select */
                        else {
 -                              for(efa= em->faces.first; efa; efa= efa->next) {
 -                                      tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -
 -                                      if(uvedit_face_visible(scene, ima, efa, tf)) {
 -                                              if(sticky_select(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
 -                                                      uvedit_uv_select(scene, efa, tf, 0);
 -                                              if(sticky_select(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
 -                                                      uvedit_uv_select(scene, efa, tf, 1);
 -                                              if(sticky_select(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
 -                                                      uvedit_uv_select(scene, efa, tf, 2);
 -                                              if(efa->v4)
 -                                                      if(sticky_select(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
 -                                                              uvedit_uv_select(scene, efa, tf, 3);
 +                              BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +                                      tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +                                      if(!uvedit_face_visible(scene, ima, efa, tf))
 +                                              continue;
 +
 +                                      BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                                              luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                                              if(sticky_select(limit, hitv, BM_GetIndex(l->v), hituv, luv->uv, sticky, hitlen))
 +                                                      uvedit_uv_select(em, scene, l);
                                        }
                                }
 -                              
 +
                                flush = 1;
                        }                       
                }
        }
        else {
                /* deselect all */
 -              for(efa= em->faces.first; efa; efa= efa->next) {
 -                      tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -                      uvedit_face_deselect(scene, efa, tf);
 +              BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +                      uvedit_face_deselect(scene, em, efa);
                }
  
                if(selectmode == UV_SELECT_VERTEX) {
                        /* select vertex */
 -                      uvedit_uv_select(scene, hit.efa, hit.tf, hit.uv);
 +                      uvedit_uv_select(em, scene, hit.l);
                        flush= 1;
                }
                else if(selectmode == UV_SELECT_EDGE) {
                        /* select edge */
 -                      uvedit_edge_select(scene, hit.efa, hit.tf, hit.edge);
 +                      uvedit_edge_select(em, scene, hit.l);
                        flush= 1;
                }
                else if(selectmode == UV_SELECT_FACE) {
                        /* select face */
 -                      uvedit_face_select(scene, hit.efa, hit.tf);
 +                      uvedit_face_select(scene, em, hit.efa);
                }
  
                /* select sticky uvs */
                if(sticky != SI_STICKY_DISABLE) {
 -                      for(efa= em->faces.first; efa; efa= efa->next) {
 -                              tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -                              if(uvedit_face_visible(scene, ima, efa, tf)) {
 +                      BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +                              tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +                              if(!uvedit_face_visible(scene, ima, efa, tf))
 +                                      continue;
 +                              
 +                              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
                                        if(sticky == SI_STICKY_DISABLE) continue;
 +                                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  
 -                                      if(sticky_select(limit, hitv, efa->v1->tmp.l, hituv, tf->uv[0], sticky))
 -                                              uvedit_uv_select(scene, efa, tf, 0);
 -                                      if(sticky_select(limit, hitv, efa->v2->tmp.l, hituv, tf->uv[1], sticky))
 -                                              uvedit_uv_select(scene, efa, tf, 1);
 -                                      if(sticky_select(limit, hitv, efa->v3->tmp.l, hituv, tf->uv[2], sticky))
 -                                              uvedit_uv_select(scene, efa, tf, 2);
 -                                      if(efa->v4)
 -                                              if(sticky_select(limit, hitv, efa->v4->tmp.l, hituv, tf->uv[3], sticky))
 -                                                      uvedit_uv_select(scene, efa, tf, 3);
 +                                      if(sticky_select(limit, hitv, BM_GetIndex(l->v), hituv, luv->uv, sticky, hitlen))
 +                                              uvedit_uv_select(em, scene, l);
  
                                        flush= 1;
                                }
                        }
                }
        }
 -      
 +
        if(sync) {
                /* flush for mesh selection */
                if(ts->selectmode != SCE_SELECT_FACE) {
 -                      if(flush==1)            EM_select_flush(em);
 -                      else if(flush==-1)      EM_deselect_flush(em);
 +                      if(flush==1)            EDBM_select_flush(em, ts->selectmode);
 +                      //else if(flush==-1)    EDBM_deselect_flush(em); <-- I think this takes care of itself. . .
                }
        }
 -      
 +
        DAG_id_tag_update(obedit->data, 0);
        WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
 -      
 -      BKE_mesh_end_editmesh(obedit->data, em);
 +
 +      BLI_array_free(hitv);
 +      BLI_array_free(hituv);
 +
        return OPERATOR_PASS_THROUGH|OPERATOR_FINISHED;
  }
  
@@@ -2228,7 -1985,7 +2228,7 @@@ static int select_linked_internal(bCont
        ToolSettings *ts= CTX_data_tool_settings(C);
        Object *obedit= CTX_data_edit_object(C);
        Image *ima= CTX_data_edit_image(C);
 -      EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 +      BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
        float limit[2];
        int extend;
  
  
        if(ts->uv_flag & UV_SYNC_SELECTION) {
                BKE_report(op->reports, RPT_ERROR, "Can't select linked when sync selection is enabled");
 -              BKE_mesh_end_editmesh(obedit->data, em);
                return OPERATOR_CANCELLED;
        }
  
        DAG_id_tag_update(obedit->data, 0);
        WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
  
 -      BKE_mesh_end_editmesh(obedit->data, em);
        return OPERATOR_FINISHED;
  }
  
@@@ -2330,45 -2089,31 +2330,45 @@@ static int unlink_selection_exec(bConte
        ToolSettings *ts= CTX_data_tool_settings(C);
        Object *obedit= CTX_data_edit_object(C);
        Image *ima= CTX_data_edit_image(C);
 -      EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 -      EditFace *efa;
 -      MTFace *tf;
 +      BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
 +      BMFace *efa;
 +      BMLoop *l;
 +      BMIter iter, liter;
 +      MTexPoly *tf;
 +      MLoopUV *luv;
  
        if(ts->uv_flag & UV_SYNC_SELECTION) {
                BKE_report(op->reports, RPT_ERROR, "Can't unlink selection when sync selection is enabled");
 -              BKE_mesh_end_editmesh(obedit->data, em);
                return OPERATOR_CANCELLED;
        }
        
 -      for(efa= em->faces.first; efa; efa= efa->next) {
 -              tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 +      BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +              int desel = 0;
 +
 +              tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +              if(!uvedit_face_visible(scene, ima, efa, tf))
 +                      continue;
  
 -              if(uvedit_face_visible(scene, ima, efa, tf)) {
 -                      const char select_flag= efa->v4 ? (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3);
 -                      if(~tf->flag & select_flag)
 -                              tf->flag &= ~select_flag;
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                      
 +                      if (!(luv->flag & MLOOPUV_VERTSEL)) {
 +                              desel = 1;
 +                              break;
 +                      }
 +              }
  
 +              if (desel) {
 +                      BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                              luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                              luv->flag &= ~MLOOPUV_VERTSEL;
 +                      }
                }
        }
        
        DAG_id_tag_update(obedit->data, 0);
        WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
  
 -      BKE_mesh_end_editmesh(obedit->data, em);
        return OPERATOR_FINISHED;
  }
  
@@@ -2403,78 -2148,78 +2403,78 @@@ static void uv_faces_do_sticky(bContex
         * selection (so for sticky modes, vertex or location based). */
        
        ToolSettings *ts= CTX_data_tool_settings(C);
 -      EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 -      EditFace *efa;
 -      MTFace *tf;
 -      int nverts, i;
 +      BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
 +      BMFace *efa;
 +      BMLoop *l;
 +      BMIter iter, liter;
 +      /* MTexPoly *tf; */
        
        if((ts->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_VERTEX) {
                /* Tag all verts as untouched, then touch the ones that have a face center
 -               * in the loop and select all MTFace UV's that use a touched vert. */
 -              EditVert *eve;
 +               * in the loop and select all MLoopUV's that use a touched vert. */
 +              BMVert *eve;
                
 -              for(eve= em->verts.first; eve; eve= eve->next)
 -                      eve->tmp.l = 0;
 +              BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
 +                      BM_ClearHFlag(eve, BM_TMP_TAG);
 +              }
                
 -              for(efa= em->faces.first; efa; efa= efa->next) {
 -                      if(efa->tmp.l) {
 -                              if(efa->v4)
 -                                      efa->v1->tmp.l= efa->v2->tmp.l= efa->v3->tmp.l= efa->v4->tmp.l=1;
 -                              else
 -                                      efa->v1->tmp.l= efa->v2->tmp.l= efa->v3->tmp.l= 1;
 +              BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +                      if (BM_TestHFlag(efa, BM_TMP_TAG)) {
 +                              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                                      BM_SetHFlag(l->v, BM_TMP_TAG);
 +                              }
                        }
                }
  
                /* now select tagged verts */
 -              for(efa= em->faces.first; efa; efa= efa->next) {
 -                      tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);               
 -                      nverts= efa->v4? 4: 3;
 -                      for(i=0; i<nverts; i++) {
 -                              if((*(&efa->v1 + i))->tmp.l) {
 -                                      if(select)
 -                                              uvedit_uv_select(scene, efa, tf, i);
 +              BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +                      /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
 +
 +                      BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                              if (BM_TestHFlag(l->v, BM_TMP_TAG)) {
 +                                      if (select)
 +                                              uvedit_uv_select(em, scene, l);
                                        else
 -                                              uvedit_uv_deselect(scene, efa, tf, i);
 +                                              uvedit_uv_deselect(em, scene, l);
                                }
                        }
                }
        }
        else if((ts->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_LOC) {
 -              EditFace *efa_vlist;
 -              MTFace *tf_vlist;
 +              BMFace *efa_vlist;
 +              /* MTexPoly *tf_vlist; */ /* UNUSED */
                UvMapVert *start_vlist=NULL, *vlist_iter;
                struct UvVertMap *vmap;
                float limit[2];
                unsigned int efa_index;
 -              //EditVert *eve; /* removed vert counting for now */ 
 +              //BMVert *eve; /* removed vert counting for now */ 
                //int a;
                
                uvedit_pixel_to_float(sima, limit, 0.05);
                
 -              EM_init_index_arrays(em, 0, 0, 1);
 -              vmap= EM_make_uv_vert_map(em, 0, 0, limit);
 +              EDBM_init_index_arrays(em, 0, 0, 1);
 +              vmap= EDBM_make_uv_vert_map(em, 0, 0, limit);
                
                /* verts are numbered above in make_uv_vert_map_EM, make sure this stays true! */
                /*for(a=0, eve= em->verts.first; eve; a++, eve= eve->next)
                        eve->tmp.l = a; */
                
                if(vmap == NULL) {
 -                      BKE_mesh_end_editmesh(obedit->data, em);
                        return;
                }
                
 -              for(efa_index=0, efa= em->faces.first; efa; efa_index++, efa= efa->next) {
 -                      if(efa->tmp.l) {
 -                              tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -                              nverts= efa->v4? 4: 3;
 -
 -                              for(i=0; i<nverts; i++) {
 +              efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
 +              for (efa_index=0; efa; efa=BMIter_Step(&iter), efa_index++) {
 +                      if (BM_TestHFlag(efa, BM_TMP_TAG)) {
 +                              /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
 +                              
 +                              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
                                        if(select)
 -                                              uvedit_uv_select(scene, efa, tf, i);
 +                                              uvedit_uv_select(em, scene, l);
                                        else
 -                                              uvedit_uv_deselect(scene, efa, tf, i);
 +                                              uvedit_uv_deselect(em, scene, l);
                                        
 -                                      vlist_iter= EM_get_uv_map_vert(vmap, (*(&efa->v1 + i))->tmp.l);
 +                                      vlist_iter= EDBM_get_uv_map_vert(vmap, BM_GetIndex(l->v));
                                        
                                        while (vlist_iter) {
                                                if(vlist_iter->separate)
                                                        break;
                                                
                                                if(efa_index != vlist_iter->f) {
 -                                                      efa_vlist = EM_get_face_for_index(vlist_iter->f);
 -                                                      tf_vlist = CustomData_em_get(&em->fdata, efa_vlist->data, CD_MTFACE);
 +                                                      efa_vlist = EDBM_get_face_for_index(em, vlist_iter->f);
 +                                                      /* tf_vlist = CustomData_bmesh_get(&em->bm->pdata, efa_vlist->head.data, CD_MTEXPOLY); */ /* UNUSED */
                                                        
                                                        if(select)
 -                                                              uvedit_uv_select(scene, efa_vlist, tf_vlist, vlist_iter->tfindex);
 +                                                              uvedit_uv_select(em, scene, BMIter_AtIndex(em->bm, BM_LOOPS_OF_FACE, efa_vlist, vlist_iter->tfindex));
                                                        else
 -                                                              uvedit_uv_deselect(scene, efa_vlist, tf_vlist, vlist_iter->tfindex);
 +                                                              uvedit_uv_deselect(em, scene, BMIter_AtIndex(em->bm, BM_LOOPS_OF_FACE, efa_vlist, vlist_iter->tfindex));
                                                }
                                                vlist_iter = vlist_iter->next;
                                        }
                                }
                        }
                }
 -              EM_free_index_arrays();
 -              EM_free_uv_vert_map(vmap);
 +              EDBM_free_index_arrays(em);
 +              EDBM_free_uv_vert_map(vmap);
                
        }
        else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */
 -              for(efa= em->faces.first; efa; efa= efa->next) {
 -                      if(efa->tmp.l) {
 -                              tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 +              BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +                      if (BM_TestHFlag(efa, BM_TMP_TAG)) {
                                if(select)
 -                                      uvedit_face_select(scene, efa, tf);
 +                                      uvedit_face_select(scene, em, efa);
                                else
 -                                      uvedit_face_deselect(scene, efa, tf);
 +                                      uvedit_face_deselect(scene, em, efa);
                        }
                }
        }
 -      BKE_mesh_end_editmesh(obedit->data, em);
  }
  
  static int border_select_exec(bContext *C, wmOperator *op)
        Object *obedit= CTX_data_edit_object(C);
        Image *ima= CTX_data_edit_image(C);
        ARegion *ar= CTX_wm_region(C);
 -      EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 -      EditFace *efa;
 -      MTFace *tface;
 +      BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
 +      BMFace *efa;
 +      BMLoop *l;
 +      BMIter iter, liter;
 +      MTexPoly *tf;
 +      MLoopUV *luv;
        rcti rect;
        rctf rectf;
        int change, pinned, select, faces, extend;
  
                change= 0;
  
 -              for(efa= em->faces.first; efa; efa= efa->next) {
 +              BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
                        /* assume not touched */
 -                      efa->tmp.l = 0;
 -                      tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -                      if(uvedit_face_visible(scene, ima, efa, tface)) {
 -                              uv_center(tface->uv, cent, efa->v4 != NULL);
 +                      BM_ClearHFlag(efa, BM_TMP_TAG);
 +
 +                      tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +                      if(uvedit_face_visible(scene, ima, efa, tf)) {
 +                              poly_uv_center(em, efa, cent);
                                if(BLI_in_rctf(&rectf, cent[0], cent[1])) {
 -                                      efa->tmp.l = change = 1;
 +                                      BM_SetHFlag(efa, BM_TMP_TAG);
 +                                      change = 1;
                                }
                        }
                }
        else {
                /* other selection modes */
                change= 1;
 +              
 +              BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +                      tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +                      if(!uvedit_face_visible(scene, ima, efa, tf))
 +                              continue;
 +                      BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                              luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
  
 -              for(efa= em->faces.first; efa; efa= efa->next) {
 -                      tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -                      if(uvedit_face_visible(scene, ima, efa, tface)) {
                                if(!pinned || (ts->uv_flag & UV_SYNC_SELECTION) ) {
 +
                                        /* UV_SYNC_SELECTION - can't do pinned selection */
 -                                      if(BLI_in_rctf(&rectf, tface->uv[0][0], tface->uv[0][1])) {
 -                                              if(select)      uvedit_uv_select(scene, efa, tface, 0);
 -                                              else            uvedit_uv_deselect(scene, efa, tface, 0);
 -                                      }
 -                                      if(BLI_in_rctf(&rectf, tface->uv[1][0], tface->uv[1][1])) {
 -                                              if(select)      uvedit_uv_select(scene, efa, tface, 1);
 -                                              else            uvedit_uv_deselect(scene, efa, tface, 1);
 +                                      if(BLI_in_rctf(&rectf, luv->uv[0], luv->uv[1])) {
 +                                              if(select)      uvedit_uv_select(em, scene, l);
 +                                              else            uvedit_uv_deselect(em, scene, l);
                                        }
 -                                      if(BLI_in_rctf(&rectf, tface->uv[2][0], tface->uv[2][1])) {
 -                                              if(select)      uvedit_uv_select(scene, efa, tface, 2);
 -                                              else            uvedit_uv_deselect(scene, efa, tface, 2);
 -                                      }
 -                                      if(efa->v4 && BLI_in_rctf(&rectf, tface->uv[3][0], tface->uv[3][1])) {
 -                                              if(select)      uvedit_uv_select(scene, efa, tface, 3);
 -                                              else            uvedit_uv_deselect(scene, efa, tface, 3);
 -                                      }
 -                              }
 -                              else if(pinned) {
 -                                      if((tface->unwrap & TF_PIN1) && 
 -                                              BLI_in_rctf(&rectf, tface->uv[0][0], tface->uv[0][1])) {
 -                                              
 -                                              if(select)      uvedit_uv_select(scene, efa, tface, 0);
 -                                              else            uvedit_uv_deselect(scene, efa, tface, 0);
 -                                      }
 -                                      if((tface->unwrap & TF_PIN2) && 
 -                                              BLI_in_rctf(&rectf, tface->uv[1][0], tface->uv[1][1])) {
 -                                              
 -                                              if(select)      uvedit_uv_select(scene, efa, tface, 1);
 -                                              else            uvedit_uv_deselect(scene, efa, tface, 1);
 -                                      }
 -                                      if((tface->unwrap & TF_PIN3) && 
 -                                              BLI_in_rctf(&rectf, tface->uv[2][0], tface->uv[2][1])) {
 -                                              
 -                                              if(select)      uvedit_uv_select(scene, efa, tface, 2);
 -                                              else            uvedit_uv_deselect(scene, efa, tface, 2);
 -                                      }
 -                                      if((efa->v4) && (tface->unwrap & TF_PIN4) && BLI_in_rctf(&rectf, tface->uv[3][0], tface->uv[3][1])) {
 -                                              if(select)      uvedit_uv_select(scene, efa, tface, 3);
 -                                              else            uvedit_uv_deselect(scene, efa, tface, 3);
 +                              } else if(pinned) {
 +                                      if ((luv->flag & MLOOPUV_PINNED) && 
 +                                          BLI_in_rctf(&rectf, luv->uv[0], luv->uv[1])) {
 +                                              if(select)      uvedit_uv_select(em, scene, l);
 +                                              else            uvedit_uv_deselect(em, scene, l);
                                        }
                                }
                        }
  
        if(change) {
                /* make sure newly selected vert selection is updated*/
 +#if 0 //ok, I think the BM_Select API handles all of this?
                if(ts->uv_flag & UV_SYNC_SELECTION) {
                        if(ts->selectmode != SCE_SELECT_FACE) {
                                if(select)      EM_select_flush(em);
                                else            EM_deselect_flush(em);
                        }
                }
 +#endif
  
                WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
                
 -              BKE_mesh_end_editmesh(obedit->data, em);
                return OPERATOR_FINISHED;
        }
 -      
 -      BKE_mesh_end_editmesh(obedit->data, em);
 +
        return OPERATOR_CANCELLED;
  } 
  
@@@ -2660,22 -2427,20 +2660,22 @@@ static void UV_OT_select_border(wmOpera
  
  /* ******************** circle select operator **************** */
  
 -static void select_uv_inside_ellipse(Scene *scene, int select, EditFace *efa, MTFace *tface, int index, float *offset, float *ell, int select_index)
 +static void select_uv_inside_ellipse(BMEditMesh *em, SpaceImage *UNUSED(sima), Scene *scene, int select,
 +                                                                       float *offset, float *ell, BMLoop *l, MLoopUV *luv)
  {
        /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */
        float x, y, r2, *uv;
        
 -      uv= tface->uv[index];
 +      
 +      uv= luv->uv;
  
        x= (uv[0] - offset[0])*ell[0];
        y= (uv[1] - offset[1])*ell[1];
  
        r2 = x*x + y*y;
        if(r2 < 1.0f) {
 -              if(select)      uvedit_uv_select(scene, efa, tface, select_index);
 -              else uvedit_uv_deselect(scene, efa, tface, select_index);
 +              if(select) uvedit_uv_select(em, scene, l);
 +              else uvedit_uv_deselect(em, scene, l);
        }
  }
  
@@@ -2684,12 -2449,10 +2684,12 @@@ static int circle_select_exec(bContext 
        SpaceImage *sima= CTX_wm_space_image(C);
        Scene *scene= CTX_data_scene(C);
        Object *obedit= CTX_data_edit_object(C);
 -      EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 +      BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
        ARegion *ar= CTX_wm_region(C);
 -      EditFace *efa;
 -      MTFace *tface;
 +      BMFace *efa;
 +      BMLoop *l;
 +      BMIter iter, liter;
 +      MLoopUV *luv;
        int x, y, radius, width, height, select;
        float zoomx, zoomy, offset[2], ellipse[2];
        int gesture_mode= RNA_int_get(op->ptr, "gesture_mode");
        UI_view2d_region_to_view(&ar->v2d, x, y, &offset[0], &offset[1]);
        
        /* do selection */
 -      for(efa= em->faces.first; efa; efa= efa->next) {
 -              tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -              select_uv_inside_ellipse(scene, select, efa, tface, 0, offset, ellipse, 0);
 -              select_uv_inside_ellipse(scene, select, efa, tface, 1, offset, ellipse, 1);
 -              select_uv_inside_ellipse(scene, select, efa, tface, 2, offset, ellipse, 2);
 -              if(efa->v4)
 -                      select_uv_inside_ellipse(scene, select, efa, tface, 3, offset, ellipse, 3);
 +      BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                      select_uv_inside_ellipse(em, sima, scene, select, offset, ellipse, l, luv);
 +              }
        }
  
 +#if 0 //I think the BM_Select api stuff handles all this as necassary?
        if(select) EM_select_flush(em);
        else EM_deselect_flush(em);
 -
 +#endif
        WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
  
 -      BKE_mesh_end_editmesh(obedit->data, em);
        return OPERATOR_FINISHED;
  }
  
@@@ -2823,94 -2588,97 +2823,94 @@@ static void UV_OT_snap_cursor(wmOperato
  
  static int snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, SpaceImage *sima)
  {
 -      EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 -      EditFace *efa;
 -      MTFace *tface;
 +      BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
 +      BMFace *efa;
 +      BMLoop *l;
 +      BMIter iter, liter;
 +      MTexPoly *tface;
 +      MLoopUV *luv;
        short change= 0;
  
 -      for(efa= em->faces.first; efa; efa= efa->next) {
 -              tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -              if(uvedit_face_visible(scene, ima, efa, tface)) {
 -                      if(uvedit_uv_selected(scene, efa, tface, 0))            copy_v2_v2(tface->uv[0], sima->cursor);
 -                      if(uvedit_uv_selected(scene, efa, tface, 1))            copy_v2_v2(tface->uv[1], sima->cursor);
 -                      if(uvedit_uv_selected(scene, efa, tface, 2))            copy_v2_v2(tface->uv[2], sima->cursor);
 -                      if(efa->v4)
 -                              if(uvedit_uv_selected(scene, efa, tface, 3))    copy_v2_v2(tface->uv[3], sima->cursor);
 +      BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +              tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +              if(!uvedit_face_visible(scene, ima, efa, tface))
 +                      continue;
  
 -                      change= 1;
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                      if(uvedit_uv_selected(em, scene, l)) {
 +                              luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                              copy_v2_v2(luv->uv, sima->cursor);
 +                              change= 1;
 +                      }
                }
        }
  
 -      BKE_mesh_end_editmesh(obedit->data, em);
        return change;
  }
  
  static int snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obedit)
  {
 -      EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 -      EditFace *efa;
 -      EditVert *eve;
 -      MTFace *tface;
 +      BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
 +      BMFace *efa;
 +      BMLoop *l;
 +      BMIter iter, liter;
 +      BMVert *eve;
 +      MTexPoly *tface;
 +      MLoopUV *luv;
        short change = 0;
        int count = 0;
        float *coords;
        short *usercount, users;
 -      
 +
 +      /* BMESH_TODO - stop setting the index, bad juju
 +       * not totally simple because 3 states and because the count is not
 +       * based on the global vertex index :S - campbell */
 +
        /* set all verts to -1 : an unused index*/
 -      for(eve= em->verts.first; eve; eve= eve->next)
 -              eve->tmp.l=-1;
 +      BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL)
 +              BM_SetIndex(eve, -1); /* set_dirty! */
 +      em->bm->elem_index_dirty |= BM_VERT;
        
        /* index every vert that has a selected UV using it, but only once so as to
         * get unique indices and to count how much to malloc */
 -      for(efa= em->faces.first; efa; efa= efa->next) {
 -              tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -
 -              if(uvedit_face_visible(scene, ima, efa, tface)) {
 -                      if(uvedit_uv_selected(scene, efa, tface, 0) && efa->v1->tmp.l==-1)              efa->v1->tmp.l= count++;
 -                      if(uvedit_uv_selected(scene, efa, tface, 1) && efa->v2->tmp.l==-1)              efa->v2->tmp.l= count++;
 -                      if(uvedit_uv_selected(scene, efa, tface, 2) && efa->v3->tmp.l==-1)              efa->v3->tmp.l= count++;
 -                      if(efa->v4)
 -                              if(uvedit_uv_selected(scene, efa, tface, 3) && efa->v4->tmp.l==-1)      efa->v4->tmp.l= count++;
 -
 -                      change = 1;
 -                      
 -                      /* optional speedup */
 -                      efa->tmp.p = tface;
 +      BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +              tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +              if(!uvedit_face_visible(scene, ima, efa, tface)) {
 +                      BM_ClearHFlag(efa, BM_TMP_TAG);
 +                      continue;
 +              } else {
 +                      BM_SetHFlag(efa, BM_TMP_TAG);
 +              }
 +
 +              change = 1;
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                      if (uvedit_uv_selected(em, scene, l) && BM_GetIndex(l->v) == -1) {
 +                              BM_SetIndex(l->v, count); /* set_dirty! */
 +                              count++;
 +                      }
                }
 -              else
 -                      efa->tmp.p = NULL;
        }
 +      em->bm->elem_index_dirty |= BM_VERT; /* set above but include for completeness since they are made dirty again */
        
        coords = MEM_callocN(sizeof(float)*count*2, "snap to adjacent coords");
        usercount = MEM_callocN(sizeof(short)*count, "snap to adjacent counts");
        
        /* add all UV coords from visible, unselected UV coords as well as counting them to average later */
 -      for(efa= em->faces.first; efa; efa= efa->next) {
 -              if((tface=(MTFace *)efa->tmp.p)) {
 -                      /* is this an unselected UV we can snap to? */
 -                      if(efa->v1->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 0))) {
 -                              coords[efa->v1->tmp.l*2] +=             tface->uv[0][0];
 -                              coords[(efa->v1->tmp.l*2)+1] += tface->uv[0][1];
 -                              usercount[efa->v1->tmp.l]++;
 -                              change = 1;
 -                      }
 -                      if(efa->v2->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 1))) {
 -                              coords[efa->v2->tmp.l*2] +=             tface->uv[1][0];
 -                              coords[(efa->v2->tmp.l*2)+1] += tface->uv[1][1];
 -                              usercount[efa->v2->tmp.l]++;
 -                              change = 1;
 -                      }
 -                      if(efa->v3->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 2))) {
 -                              coords[efa->v3->tmp.l*2] +=             tface->uv[2][0];
 -                              coords[(efa->v3->tmp.l*2)+1] += tface->uv[2][1];
 -                              usercount[efa->v3->tmp.l]++;
 -                              change = 1;
 -                      }
 -                      
 -                      if(efa->v4) {
 -                              if(efa->v4->tmp.l >= 0 && (!uvedit_uv_selected(scene, efa, tface, 3))) {
 -                                      coords[efa->v4->tmp.l*2] +=             tface->uv[3][0];
 -                                      coords[(efa->v4->tmp.l*2)+1] += tface->uv[3][1];
 -                                      usercount[efa->v4->tmp.l]++;
 -                                      change = 1;
 -                              }
 +      BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +              if (!BM_TestHFlag(efa, BM_TMP_TAG))
 +                      continue;
 +
 +              tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +              if(!uvedit_face_visible(scene, ima, efa, tface))
 +                      continue;
 +
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                      if (BM_GetIndex(l->v) >= 0 && 
 +                          (!uvedit_uv_selected(em, scene, l))) {
 +                                  luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                                  coords[BM_GetIndex(l->v)*2] += luv->uv[0];
 +                                  coords[BM_GetIndex(l->v)*2+1] += luv->uv[1];
 +                                  change = 1;
                        }
                }
        }
        if(!change) {
                MEM_freeN(coords);
                MEM_freeN(usercount);
 -              BKE_mesh_end_editmesh(obedit->data, em);
                return change;
        }
        
        /* copy the averaged unselected UVs back to the selected UVs */
 -      for(efa= em->faces.first; efa; efa= efa->next) {
 -              if((tface=(MTFace *)efa->tmp.p)) {
 -                      
 -                      if(     uvedit_uv_selected(scene, efa, tface, 0) &&
 -                                      efa->v1->tmp.l >= 0 &&
 -                                      (users = usercount[efa->v1->tmp.l])
 -                      ) {
 -                              tface->uv[0][0] = coords[efa->v1->tmp.l*2]              / users;
 -                              tface->uv[0][1] = coords[(efa->v1->tmp.l*2)+1]  / users;
 -                      }
 -
 -                      if(     uvedit_uv_selected(scene, efa, tface, 1) &&
 -                                      efa->v2->tmp.l >= 0 &&
 -                                      (users = usercount[efa->v2->tmp.l])
 -                      ) {
 -                              tface->uv[1][0] = coords[efa->v2->tmp.l*2]              / users;
 -                              tface->uv[1][1] = coords[(efa->v2->tmp.l*2)+1]  / users;
 -                      }
 -                      
 -                      if(     uvedit_uv_selected(scene, efa, tface, 2) &&
 -                                      efa->v3->tmp.l >= 0 &&
 -                                      (users = usercount[efa->v3->tmp.l])
 -                      ) {
 -                              tface->uv[2][0] = coords[efa->v3->tmp.l*2]              / users;
 -                              tface->uv[2][1] = coords[(efa->v3->tmp.l*2)+1]  / users;
 -                      }
 -                      
 -                      if(efa->v4) {
 -                              if(     uvedit_uv_selected(scene, efa, tface, 3) &&
 -                                              efa->v4->tmp.l >= 0 &&
 -                                              (users = usercount[efa->v4->tmp.l])
 -                              ) {
 -                                      tface->uv[3][0] = coords[efa->v4->tmp.l*2]              / users;
 -                                      tface->uv[3][1] = coords[(efa->v4->tmp.l*2)+1]  / users;
 -                              }
 +      BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +              if (!BM_TestHFlag(efa, BM_TMP_TAG))
 +                      continue;
 +
 +              tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +              if(!uvedit_face_visible(scene, ima, efa, tface))
 +                      continue;
 +
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                      if (uvedit_uv_selected(em, scene, l) && BM_GetIndex(l->v) >= 0
 +                          && (users = usercount[BM_GetIndex(l->v)])) {
 +                              luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                              luv->uv[0] = coords[BM_GetIndex(l->v)*2];
 +                              luv->uv[1] = coords[BM_GetIndex(l->v)*2+1];
                        }
                }
        }
        MEM_freeN(coords);
        MEM_freeN(usercount);
  
 -      BKE_mesh_end_editmesh(obedit->data, em);
        return change;
  }
  
  static int snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit)
  {
 -      EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 -      Image *ima;
 -      EditFace *efa;
 -      MTFace *tface;
 +      BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
 +      Image *ima= sima->image;
 +      BMFace *efa;
 +      BMLoop *l;
 +      BMIter iter, liter;
 +      MTexPoly *tface;
 +      MLoopUV *luv;
        int width= 0, height= 0;
        float w, h;
        short change = 0;
  
 -      if(!sima)
 -              return 0;
 -      
 -      ima= sima->image;
 -      
        ED_space_image_size(sima, &width, &height);
        w = (float)width;
        h = (float)height;
        
 -      for(efa= em->faces.first; efa; efa= efa->next) {
 -              tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -              if(uvedit_face_visible(scene, ima, efa, tface)) {
 -                      if(uvedit_uv_selected(scene, efa, tface, 0)) snap_uv_to_pixel(tface->uv[0], w, h);
 -                      if(uvedit_uv_selected(scene, efa, tface, 1)) snap_uv_to_pixel(tface->uv[1], w, h);
 -                      if(uvedit_uv_selected(scene, efa, tface, 2)) snap_uv_to_pixel(tface->uv[2], w, h);
 -                      if(efa->v4)
 -                              if(uvedit_uv_selected(scene, efa, tface, 3)) snap_uv_to_pixel(tface->uv[3], w, h);
 +      BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +              tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +              if(!uvedit_face_visible(scene, ima, efa, tface))
 +                      continue;
  
 -                      change = 1;
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                      if (uvedit_uv_selected(em, scene, l)) {
 +                              luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                              snap_uv_to_pixel(luv->uv, w, h);
 +                      }
                }
 +
 +              change = 1;
        }
  
 -      BKE_mesh_end_editmesh(obedit->data, em);
        return change;
  }
  
@@@ -3041,34 -2833,35 +3041,34 @@@ static int pin_exec(bContext *C, wmOper
        Scene *scene= CTX_data_scene(C);
        Object *obedit= CTX_data_edit_object(C);
        Image *ima= CTX_data_edit_image(C);
 -      EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 -      EditFace *efa;
 -      MTFace *tface;
 +      BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
 +      BMFace *efa;
 +      BMLoop *l;
 +      BMIter iter, liter;
 +      MTexPoly *tface;
 +      MLoopUV *luv;
        int clear= RNA_boolean_get(op->ptr, "clear");
        
 -      for(efa= em->faces.first; efa; efa= efa->next) {
 -              tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 +      BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +              tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +              if(!uvedit_face_visible(scene, ima, efa, tface))
 +                      continue;
  
 -              if(uvedit_face_visible(scene, ima, efa, tface)) {
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                      
                        if(!clear) {
 -                              if(uvedit_uv_selected(scene, efa, tface, 0)) tface->unwrap |= TF_PIN1;
 -                              if(uvedit_uv_selected(scene, efa, tface, 1)) tface->unwrap |= TF_PIN2;
 -                              if(uvedit_uv_selected(scene, efa, tface, 2)) tface->unwrap |= TF_PIN3;
 -                              if(efa->v4)
 -                                      if(uvedit_uv_selected(scene, efa, tface, 3)) tface->unwrap |= TF_PIN4;
 -                      }
 -                      else {
 -                              if(uvedit_uv_selected(scene, efa, tface, 0)) tface->unwrap &= ~TF_PIN1;
 -                              if(uvedit_uv_selected(scene, efa, tface, 1)) tface->unwrap &= ~TF_PIN2;
 -                              if(uvedit_uv_selected(scene, efa, tface, 2)) tface->unwrap &= ~TF_PIN3;
 -                              if(efa->v4)
 -                                      if(uvedit_uv_selected(scene, efa, tface, 3)) tface->unwrap &= ~TF_PIN4;
 +                              if (uvedit_uv_selected(em, scene, l))
 +                                      luv->flag |= MLOOPUV_PINNED;
 +                      } else {
 +                              if (uvedit_uv_selected(em, scene, l))
 +                                      luv->flag &= ~MLOOPUV_PINNED;
                        }
                }
        }
        
        WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
  
 -      BKE_mesh_end_editmesh(obedit->data, em);
        return OPERATOR_FINISHED;
  }
  
@@@ -3095,28 -2888,26 +3095,28 @@@ static int select_pinned_exec(bContext 
        Scene *scene= CTX_data_scene(C);
        Object *obedit= CTX_data_edit_object(C);
        Image *ima= CTX_data_edit_image(C);
 -      EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 -      EditFace *efa;
 -      MTFace *tface;
 -      
 -      for(efa= em->faces.first; efa; efa= efa->next) {
 -              tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -
 -              if(uvedit_face_visible(scene, ima, efa, tface)) {
 -                      if(tface->unwrap & TF_PIN1) uvedit_uv_select(scene, efa, tface, 0);
 -                      if(tface->unwrap & TF_PIN2) uvedit_uv_select(scene, efa, tface, 1);
 -                      if(tface->unwrap & TF_PIN3) uvedit_uv_select(scene, efa, tface, 2);
 -                      if(efa->v4) {
 -                              if(tface->unwrap & TF_PIN4) uvedit_uv_select(scene, efa, tface, 3);
 -                      }
 +      BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
 +      BMFace *efa;
 +      BMLoop *l;
 +      BMIter iter, liter;
 +      MTexPoly *tface;
 +      MLoopUV *luv;
 +      
 +      BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +              tface= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +              if(!uvedit_face_visible(scene, ima, efa, tface))
 +                      continue;
 +
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                      
 +                      if (luv->flag & MLOOPUV_PINNED)
 +                              uvedit_uv_select(em, scene, l);
                }
        }
        
        WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
  
 -      BKE_mesh_end_editmesh(obedit->data, em);
        return OPERATOR_FINISHED;
  }
  
@@@ -3140,75 -2931,122 +3140,75 @@@ static int hide_exec(bContext *C, wmOpe
        SpaceImage *sima= CTX_wm_space_image(C);
        ToolSettings *ts= CTX_data_tool_settings(C);
        Object *obedit= CTX_data_edit_object(C);
 -      EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 -      EditFace *efa;
 -      MTFace *tf;
 +      Scene *scene = CTX_data_scene(C);
 +      BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
 +      BMFace *efa;
 +      BMLoop *l;
 +      BMIter iter, liter;
 +      MLoopUV *luv;
        int swap= RNA_boolean_get(op->ptr, "unselected");
        int facemode= sima ? sima->flag & SI_SELACTFACE : 0;
  
        if(ts->uv_flag & UV_SYNC_SELECTION) {
 -              EM_hide_mesh(em, swap);
 +              EDBM_hide_mesh(em, swap);
                WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
  
 -              BKE_mesh_end_editmesh(obedit->data, em);
                return OPERATOR_FINISHED;
        }
        
 -      if(swap) {
 -              for(efa= em->faces.first; efa; efa= efa->next) {
 -                      if(efa->f & SELECT) {
 -                              tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -                              if(facemode) {
 -                                      /* Pretend face mode */
 -                                      if((    (efa->v4==NULL && 
 -                                                      (       tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) ==                        (TF_SEL1|TF_SEL2|TF_SEL3) )                      ||
 -                                                      (       tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) ==        (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)       ) == 0) {
 -                                              
 -                                              if(em->selectmode == SCE_SELECT_FACE) {
 -                                                      efa->f &= ~SELECT;
 -                                                      /* must re-select after */
 -                                                      efa->e1->f &= ~SELECT;
 -                                                      efa->e2->f &= ~SELECT;
 -                                                      efa->e3->f &= ~SELECT;
 -                                                      if(efa->e4) efa->e4->f &= ~SELECT;
 -                                              }
 -                                              else
 -                                                      EM_select_face(efa, 0);
 -                                      }
 -                                      tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
 -                              }
 -                              else if(em->selectmode == SCE_SELECT_FACE) {
 -                                      const char select_flag= efa->v4 ? (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) : (TF_SEL1|TF_SEL2|TF_SEL3);
 -                                      if((tf->flag & select_flag)==0) {
 -                                              EM_select_face(efa, 0);
 -                                              tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
 -                                      }
 -                              }
 -                              else {
 -                                      /* EM_deselect_flush will deselect the face */
 -                                      if((tf->flag & TF_SEL1)==0)                             efa->v1->f &= ~SELECT;
 -                                      if((tf->flag & TF_SEL2)==0)                             efa->v2->f &= ~SELECT;
 -                                      if((tf->flag & TF_SEL3)==0)                             efa->v3->f &= ~SELECT;
 -                                      if((efa->v4) && (tf->flag & TF_SEL4)==0)        efa->v4->f &= ~SELECT;                  
 +      BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +              int hide = 0;
  
 -                                      tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
 -                              }
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +
 +                      if (luv->flag & MLOOPUV_VERTSEL) {
 +                              hide = 1;
 +                              break;
                        }
                }
 -      }
 -      else {
 -              for(efa= em->faces.first; efa; efa= efa->next) {
 -                      if(efa->f & SELECT) {
 -                              tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -
 -                              if(facemode) {
 -                                      if(     (efa->v4==NULL && 
 -                                                      (       tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) ==                        (TF_SEL1|TF_SEL2|TF_SEL3) )                      ||
 -                                                      (       tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) ==        (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)       ) {
 -                                              
 -                         &nbs