svn merge -r41655:41715 ^/trunk/blender --- this is the real cycles merge, needs...
authorCampbell Barton <ideasman42@gmail.com>
Thu, 10 Nov 2011 04:17:43 +0000 (04:17 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 10 Nov 2011 04:17:43 +0000 (04:17 +0000)
1  2 
CMakeLists.txt
source/blender/SConscript
source/blender/blenkernel/BKE_blender.h
source/blender/blenloader/intern/readfile.c
source/blender/editors/sculpt_paint/paint_vertex.c
source/blender/editors/transform/transform_conversions.c
source/blender/makesrna/RNA_access.h
source/blender/makesrna/SConscript
source/blender/makesrna/intern/rna_object_api.c
source/creator/CMakeLists.txt

diff --combined CMakeLists.txt
index dd3781f41e57b330b0b29e424c2dac9ecc430ff3,4bc6cab1dc5e047afb8cfdb2b782331d064262a7..e9f477cc31da6bc28a8f5edd3961b9876e90b186
@@@ -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
@@@ -213,6 -213,10 +213,10 @@@ if(UNIX AND NOT APPLE
  endif()
  option(WITH_PYTHON_INSTALL       "Copy system python into the blender install folder" ON)
  
+ # Cycles
+ option(WITH_CYCLES                    "Enable Cycles Render Engine" ON)
+ OPTION(WITH_CYCLES_TEST               "Build cycles test application" OFF)
  # disable for now, but plan to support on all platforms eventually
  option(WITH_MEM_JEMALLOC   "Enable malloc replacement (http://www.canonware.com/jemalloc)" OFF)
  mark_as_advanced(WITH_MEM_JEMALLOC)
@@@ -284,6 -288,12 +288,12 @@@ if(WITH_PYTHON_MODULE
        set(WITH_HEADLESS ON)
  endif()
  
+ # auto enable openimageio and boost for cycles
+ if(WITH_CYCLES)
+       set(WITH_OPENIMAGEIO ON)
+       set(WITH_BOOST ON)
+ endif()
  TEST_SSE_SUPPORT(COMPILER_SSE_FLAG COMPILER_SSE2_FLAG)
  
  # don't store paths to libs for portable distrobution
@@@ -492,12 -502,12 +502,12 @@@ if(UNIX AND NOT APPLE
        endif()
  
        if(WITH_BOOST)
-               set(BOOST "/usr" CACHE PATH "Boost Directory")
+               
+               # uses in build instructions to override include and library variables
                if(NOT BOOST_CUSTOM)
-                       set(BOOST_ROOT ${BOOST})
                        set(Boost_USE_MULTITHREADED ON)
-                       find_package(Boost 1.34 REQUIRED COMPONENTS filesystem regex system thread)
+                       find_package(Boost 1.34 COMPONENTS filesystem regex system thread)
+                       mark_as_advanced(Boost_DIR)  # why doesnt boost do this?
                endif()
  
                set(BOOST_INCLUDE_DIR ${Boost_INCLUDE_DIRS})
        endif()
  
        if(WITH_OPENIMAGEIO)
-               set(OPENIMAGEIO "/usr" CACHE PATH "OpenImageIO Directory")
-               set(OPENIMAGEIO_ROOT_DIR ${OPENIMAGEIO})
-               find_package(OpenImageIO REQUIRED)
+               find_package(OpenImageIO)
  
                set(OPENIMAGEIO_LIBRARIES ${OPENIMAGEIO_LIBRARIES} ${PNG_LIBRARIES} ${JPEG_LIBRARIES} ${TIFF_LIBRARY} ${OPENEXR_LIBRARIES} ${ZLIB_LIBRARIES} ${BOOST_LIBRARIES})
                set(OPENIMAGEIO_LIBPATH)  # TODO, remove and reference the absolute path everywhere
  
                if(NOT OPENIMAGEIO_FOUND)
                        set(WITH_OPENIMAGEIO OFF)
+                       set(WITH_CYCLES OFF)
+                       message(STATUS "OpenImageIO not found, disabling WITH_CYCLES")
                endif()
        endif()
  
@@@ -843,7 -852,7 +852,7 @@@ elseif(WIN32
        else()
                # keep GCC specific stuff here
                if(CMAKE_COMPILER_IS_GNUCC)
-                       set(PLATFORM_LINKLIBS "-lshell32 -lshfolder -lgdi32 -lmsvcrt -lwinmm -lmingw32 -lm -lws2_32 -lz -lstdc++ -lole32 -luuid -lwsock32")
+                       set(PLATFORM_LINKLIBS "-lshell32 -lshfolder -lgdi32 -lmsvcrt -lwinmm -lmingw32 -lm -lws2_32 -lz -lstdc++ -lole32 -luuid -lwsock32 -lpsapi")
                        set(PLATFORM_CFLAGS "-pipe -funsigned-char -fno-strict-aliasing")
  
                        add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE)
                if(WITH_BOOST)
                        set(BOOST ${LIBDIR}/boost)
                        set(BOOST_INCLUDE_DIR ${BOOST}/include)
-                       set(BOOST_POSTFIX "vc90-mt-s-1_46_1")
-                       set(BOOST_DEBUG_POSTFIX "vc90-mt-sgd-1_46_1")
+                       set(BOOST_POSTFIX "mgw45-mt-s-1_47")
+                       set(BOOST_DEBUG_POSTFIX "mgw45-mt-sd-1_47")
                        set(BOOST_LIBRARIES
-                               optimized libboost_date_time-${BOOST_POSTFIX} libboost_filesystem-${BOOST_POSTFIX}
-                               libboost_regex-${BOOST_POSTFIX} libboost_system-${BOOST_POSTFIX} libboost_thread-${BOOST_POSTFIX}
-                               debug libboost_date_time-${BOOST_DEBUG_POSTFIX} libboost_filesystem-${BOOST_DEBUG_POSTFIX}
-                               libboost_regex-${BOOST_DEBUG_POSTFIX} libboost_system-${BOOST_DEBUG_POSTFIX} libboost_thread-${BOOST_DEBUG_POSTFIX})
-                       set(BOOST_LIBPATH ${BOOST}/lib)
-                       set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB")
+                               optimized boost_date_time-${BOOST_POSTFIX} boost_filesystem-${BOOST_POSTFIX}
+                               boost_regex-${BOOST_POSTFIX} boost_system-${BOOST_POSTFIX} boost_thread-${BOOST_POSTFIX}
+                               debug boost_date_time-${BOOST_DEBUG_POSTFIX} boost_filesystem-${BOOST_DEBUG_POSTFIX}
+                               boost_regex-${BOOST_DEBUG_POSTFIX} boost_system-${BOOST_DEBUG_POSTFIX} boost_thread-${BOOST_DEBUG_POSTFIX})
+                       set(BOOST_LIBPATH ${BOOST}/lib/gcc)
+                       set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB -DBOOST_THREAD_USE_LIB ")
                endif()
                        
                if(WITH_OPENIMAGEIO)
-                       set(OPENIMAGEIO ${LIBDIR}/openimageio)
+                       set(OPENIMAGEIO ${LIBDIR}/gcc/openimageio)
                        set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include)
                        set(OPENIMAGEIO_LIBRARIES OpenImageIO)
                        set(OPENIMAGEIO_LIBPATH ${OPENIMAGEIO}/lib)
                        set(OPENIMAGEIO_DEFINITIONS)
                endif()
  
-               set(PLATFORM_LINKFLAGS "--stack,2097152")
+               set(PLATFORM_LINKFLAGS "-Xlinker --stack=2097152")
  
        endif()
  
@@@ -1480,6 -1489,7 +1489,7 @@@ if(FIRST_RUN
        info_cfg_option(WITH_FFTW3)
        info_cfg_option(WITH_INTERNATIONAL)
        info_cfg_option(WITH_INPUT_NDOF)
+       info_cfg_option(WITH_CYCLES)
  
        info_cfg_text("Compiler Options:")
        info_cfg_option(WITH_BUILDINFO)
index e6cd6b09c2084a8a9f7aa6f36cb074f42b75f80f,ea5101f811110ff08d48cff99a450243e8efe895..c3a7089f425659874bdd047c11b904d38bc2689f
@@@ -3,7 -3,6 +3,7 @@@ Import ('env'
  import sys
  
  SConscript(['avi/SConscript',
 +            'bmesh/SConscript',
              'blenkernel/SConscript',
              'blenlib/SConscript',
              'blenloader/SConscript',
@@@ -12,7 -11,6 +12,6 @@@
              'editors/SConscript',
              'imbuf/SConscript',
              'makesdna/SConscript',
-             'makesrna/SConscript',
              'render/SConscript',
              'nodes/SConscript',
              'modifiers/SConscript',
@@@ -20,7 -18,7 +19,7 @@@
              'windowmanager/SConscript',
              'blenfont/SConscript'])
  
+ makesrna = SConscript('makesrna/SConscript')
  
  if env['WITH_BF_PYTHON']:
      SConscript(['python/SConscript'])
index 6f9bea39ecc8eabde6df9ec15134701a9d44d4f8,b150c403b871f6bd721c8a42b387b0f9a99ead4e..76bb587dcd697dd96de46ccdcc6f4b0e9011a7c2
@@@ -42,7 -42,7 +42,7 @@@ extern "C" 
   * and keep comment above the defines.
   * Use STRINGIFY() rather than defining with quotes */
  #define BLENDER_VERSION                       260
- #define BLENDER_SUBVERSION            2
+ #define BLENDER_SUBVERSION            3
  
  #define BLENDER_MINVERSION            250
  #define BLENDER_MINSUBVERSION 0
@@@ -88,7 -88,6 +88,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 a4e71293177ae88cacc77038fd55a0ba32e2c2e5,74331b75a70bd5466f814ad40b0a6fdb5e1676cc..277c3d927a351302b7321b526650ac188ec360a3
  
  #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"
@@@ -2621,16 -2619,6 +2621,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);
                        
@@@ -3549,26 -3537,6 +3549,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);
 +                      }
 +                      
                        me->id.flag -= LIB_NEEDLINK;
                }
                me= me->id.next;
@@@ -3624,17 -3586,10 +3624,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;
                }
        }
@@@ -3647,18 -3602,7 +3647,18 @@@ static void direct_link_mdisps(FileDat
  
                for(i = 0; i < count; ++i) {
                        mdisps[i].disps = newdataadr(fd, mdisps[i].disps);
 -
 +                      
 +                      /*put .disps into cellalloc system*/
 +                      if (mdisps[i].disps) {
 +                              float *disp2;
 +                              
 +                              disp2 = BLI_cellalloc_malloc(MEM_allocN_len(mdisps[i].disps), "cellalloc .disps copy");
 +                              memcpy(disp2, mdisps[i].disps, MEM_allocN_len(mdisps[i].disps));
 +                              
 +                              MEM_freeN(mdisps[i].disps);
 +                              mdisps[i].disps = (float (*)[3])disp2;
 +                      }
 +                      
                        if( (fd->flags & FD_FLAGS_SWITCH_ENDIAN) && (mdisps[i].disps) ) {
                                /* DNA_struct_switch_endian doesn't do endian swap for (*disps)[] */
                                /* this does swap for data written at write_mdisps() - readfile.c */
        }
  }
  
 +/*this isn't really a public api function, so prototyped here*/
  static void direct_link_customdata(FileData *fd, CustomData *data, int count)
  {
        int i = 0;
                        i++;
                }
        }
 +
 +      CustomData_update_typemap(data);
  }
  
  static void direct_link_mesh(FileData *fd, Mesh *mesh)
        mesh->mvert= newdataadr(fd, mesh->mvert);
        mesh->medge= newdataadr(fd, mesh->medge);
        mesh->mface= newdataadr(fd, mesh->mface);
 +      mesh->mloop= newdataadr(fd, mesh->mloop);
 +      mesh->mpoly= newdataadr(fd, mesh->mpoly);
        mesh->tface= newdataadr(fd, mesh->tface);
        mesh->mtface= newdataadr(fd, mesh->mtface);
        mesh->mcol= newdataadr(fd, mesh->mcol);
        mesh->msticky= newdataadr(fd, mesh->msticky);
        mesh->dvert= newdataadr(fd, mesh->dvert);
 -      
 +      mesh->mloopcol= newdataadr(fd, mesh->mloopcol);
 +      mesh->mloopuv= newdataadr(fd, mesh->mloopuv);
 +      mesh->mtpoly= newdataadr(fd, mesh->mtpoly);
 +
        /* animdata */
        mesh->adt= newdataadr(fd, mesh->adt);
        direct_link_animdata(fd, mesh->adt);
        direct_link_customdata(fd, &mesh->vdata, mesh->pv ? mesh->pv->totvert : mesh->totvert);
        direct_link_customdata(fd, &mesh->edata, mesh->pv ? mesh->pv->totedge : mesh->totedge);
        direct_link_customdata(fd, &mesh->fdata, mesh->pv ? mesh->pv->totface : mesh->totface);
 -
 +      direct_link_customdata(fd, &mesh->ldata, mesh->totloop);
 +      direct_link_customdata(fd, &mesh->pdata, mesh->totpoly);
 +      
        mesh->bb= NULL;
        mesh->mselect = NULL;
 -      mesh->edit_mesh= NULL;
 +      mesh->edit_btmesh= NULL;
        
        /* Multires data */
        mesh->mr= newdataadr(fd, mesh->mr);
@@@ -5677,6 -5611,7 +5677,7 @@@ static void direct_link_screen(FileDat
                        else if(sl->spacetype==SPACE_BUTS) {
                                SpaceButs *sbuts= (SpaceButs *)sl;
                                sbuts->path= NULL;
+                               sbuts->texuser= NULL;
                        }
                        else if(sl->spacetype==SPACE_CONSOLE) {
                                SpaceConsole *sconsole= (SpaceConsole *)sl;
@@@ -12011,7 -11946,7 +12012,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_tessface_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
        }
  
        if (main->versionfile < 256 || (main->versionfile == 256 && main->subversionfile < 2)){
index 7599cf1117aca32a82486d75f58e34d9d9cf906f,e55438a30b886c6f1b7724cf38a7d814c7b19b23..4d024113cf88c10e04f06d0167baa9d577bd1a2c
@@@ -43,7 -43,6 +43,7 @@@
  
  #include "BLI_blenlib.h"
  #include "BLI_math.h"
 +#include "BLI_memarena.h"
  #include "BLI_utildefines.h"
  #include "BLI_ghash.h"
  
@@@ -198,7 -197,7 +198,7 @@@ unsigned int vpaint_get_current_col(VPa
        return rgba_to_mcol(brush->rgb[0], brush->rgb[1], brush->rgb[2], 1.0f);
  }
  
 -static void do_shared_vertexcol(Mesh *me)
 +static void do_shared_vertex_tesscol(Mesh *me)
  {
        /* if no mcol: do not do */
        /* if tface: only the involved faces, otherwise all */
        MEM_freeN(scolmain);
  }
  
 +void do_shared_vertexcol(Mesh *me)
 +{
 +      MLoop *ml = me->mloop;
 +      MLoopCol *lcol = me->mloopcol;
 +      MTexPoly *mtp = me->mtpoly;
 +      MPoly *mp = me->mpoly;
 +      float (*scol)[5];
 +      int i, has_shared = 0;
 +
 +      /* if no mloopcol: do not do */
 +      /* if mtexpoly: only the involved faces, otherwise all */
 +
 +      if(me->mloopcol==0 || me->totvert==0 || me->totpoly==0) return;
 +
 +      scol = MEM_callocN(sizeof(float)*me->totvert*5, "scol");
 +
 +      for (i=0; i<me->totloop; i++, ml++, lcol++) {
 +              if (i >= mp->loopstart + mp->totloop) {
 +                      mp++;
 +                      if (mtp) mtp++;
 +              }
 +
 +              if (!(mtp && (mtp->mode & TF_SHAREDCOL)) && (me->editflag & ME_EDIT_PAINT_MASK)!=0)
 +                      continue;
 +
 +              scol[ml->v][0] += lcol->r;
 +              scol[ml->v][1] += lcol->g;
 +              scol[ml->v][2] += lcol->b;
 +              scol[ml->v][3] += lcol->a;
 +              scol[ml->v][4] += 1.0;
 +              has_shared = 1;
 +      }
 +      
 +      if (has_shared) {
 +              for (i=0; i<me->totvert; i++) {
 +                      if (!scol[i][4]) continue;
 +
 +                      scol[i][0] /= scol[i][4];
 +                      scol[i][1] /= scol[i][4];
 +                      scol[i][2] /= scol[i][4];
 +                      scol[i][3] /= scol[i][4];
 +              }
 +      
 +              ml = me->mloop;
 +              lcol = me->mloopcol;
 +              for (i=0; i<me->totloop; i++, ml++, lcol++) {
 +                      if (!scol[ml->v][4]) continue;
 +
 +                      lcol->r = scol[ml->v][0];
 +                      lcol->g = scol[ml->v][1];
 +                      lcol->b = scol[ml->v][2];
 +                      lcol->a = scol[ml->v][3];
 +              }
 +      }
 +
 +      MEM_freeN(scol);
 +
 +      if (has_shared) {
 +              do_shared_vertex_tesscol(me);
 +      }
 +}
 +
  static void make_vertexcol(Object *ob)        /* single ob */
  {
        Mesh *me;
        if(!ob || ob->id.lib) return;
        me= get_mesh(ob);
        if(me==NULL) return;
 -      if(me->edit_mesh) return;
 +      if(me->edit_btmesh) return;
  
        /* copies from shadedisplist to mcol */
 -      if(!me->mcol) {
 -              CustomData_add_layer(&me->fdata, CD_MCOL, CD_CALLOC, NULL, me->totface);
 -              mesh_update_customdata_pointers(me);
 -      }
 +      if(!me->mcol)
 +              CustomData_add_layer(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface);
 +      if (!me->mloopcol)
 +              CustomData_add_layer(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop);
 +      
 +      mesh_update_customdata_pointers(me);
  
        //if(shade)
        //      shadeMeshMCol(scene, ob, me);
@@@ -388,7 -323,7 +388,7 @@@ static int wpaint_mirror_vgroup_ensure(
        return -1;
  }
  
 -static void copy_vpaint_prev(VPaint *vp, unsigned int *mcol, int tot)
 +static void copy_vpaint_prev(VPaint *vp, unsigned int *lcol, int tot)
  {
        if(vp->vpaint_prev) {
                MEM_freeN(vp->vpaint_prev);
        }
        vp->tot= tot;   
        
 -      if(mcol==NULL || tot==0) return;
 +      if(lcol==NULL || tot==0) return;
        
 -      vp->vpaint_prev= MEM_mallocN(4*sizeof(int)*tot, "vpaint_prev");
 -      memcpy(vp->vpaint_prev, mcol, 4*sizeof(int)*tot);
 +      vp->vpaint_prev= MEM_mallocN(sizeof(int)*tot, "vpaint_prev");
 +      memcpy(vp->vpaint_prev, lcol, sizeof(int)*tot);
        
  }
  
@@@ -422,11 -357,9 +422,11 @@@ static void copy_wpaint_prev (VPaint *w
  void vpaint_fill(Object *ob, unsigned int paintcol)
  {
        Mesh *me;
 -      MFace *mf;
 +      MFace *mf;
 +      MPoly *mp;
 +      MLoopCol *lcol;
        unsigned int *mcol;
 -      int i, selected;
 +      int i, j, selected;
  
        me= get_mesh(ob);
        if(me==NULL || me->totface==0) return;
                        mcol[3] = paintcol;
                }
        }
 +
 +      mp = me->mpoly;
 +      lcol = me->mloopcol;
 +      for (i=0; i<me->totpoly; i++, mp++) {
 +              if (!(!selected || mp->flag & ME_FACE_SEL))
 +                      continue;
 +
 +              lcol = me->mloopcol + mp->loopstart;
 +              for (j=0; j<mp->totloop; j++, lcol++) {
 +                      *(int*)lcol = paintcol;
 +              }
 +      }
        
        DAG_id_tag_update(&me->id, 0);
  }
  void wpaint_fill(VPaint *wp, Object *ob, float paintweight)
  {
        Mesh *me= ob->data;
 -      MFace *mf;
 +      MPoly *mf;
        MDeformWeight *dw, *uw;
        int vgroup, vgroup_mirror= -1;
        unsigned int index;
        /* mutually exclusive, could be made into a */
        const short paint_selmode= ME_EDIT_PAINT_SEL_MODE(me);
  
 -      if(me->totface==0 || me->dvert==NULL || !me->mface) return;
 +      if(me->totpoly==0 || me->dvert==NULL || !me->mpoly) return;
        
        vgroup= ob->actdef-1;
  
        
        copy_wpaint_prev(wp, me->dvert, me->totvert);
        
 -      for(index=0, mf= me->mface; index < me->totface; index++, mf++) {
 -              unsigned int fidx= mf->v4 ? 3:2;
 +      for(index=0, mf= me->mpoly; index < me->totpoly; index++, mf++) {
 +              unsigned int fidx= mf->totloop - 1;
  
                if ((paint_selmode == SCE_SELECT_FACE) && !(mf->flag & ME_FACE_SEL)) {
                        continue;
                }
  
                do {
 -                      unsigned int vidx= *(&mf->v1 + fidx);
 +                      unsigned int vidx= me->mloop[mf->loopstart + fidx].v;
  
                        if(!me->dvert[vidx].flag) {
                                if((paint_selmode == SCE_SELECT_VERTEX) && !(me->mvert[vidx].flag & SELECT)) {
@@@ -960,14 -881,14 +960,14 @@@ static int weight_sample_invoke(bContex
  
                index= view3d_sample_backbuf(&vc, event->mval[0], event->mval[1]);
  
 -              if(index && index<=me->totface) {
 +              if(index && index<=me->totpoly) {
                        DerivedMesh *dm= mesh_get_derived_final(vc.scene, vc.obact, CD_MASK_BAREMESH);
  
                        if(dm->getVertCo==NULL) {
                                BKE_report(op->reports, RPT_WARNING, "The modifier used does not support deformed locations");
                        }
                        else {
 -                              MFace *mf= ((MFace *)me->mface) + index-1;
 +                              MPoly *mf= ((MPoly *)me->mpoly) + index-1;
                                const int vgroup= vc.obact->actdef - 1;
                                ToolSettings *ts= vc.scene->toolsettings;
                                float mval_f[2];
                                mval_f[0]= (float)event->mval[0];
                                mval_f[1]= (float)event->mval[1];
  
 -                              fidx= mf->v4 ? 3:2;
 +                              fidx= mf->totloop - 1;
                                do {
                                        float co[3], sco[3], len;
 -                                      const int v_idx= (*(&mf->v1 + fidx));
 +                                      const int v_idx= me->mloop[mf->loopstart + fidx].v;
                                        dm->getVertCo(dm, v_idx, co);
                                        project_float_noclip(vc.ar, co, sco);
                                        len= len_squared_v2v2(mval_f, sco);
@@@ -1047,13 -968,13 +1047,13 @@@ static EnumPropertyItem *weight_paint_s
                                if(index && index<=me->totface) {
                                        const int totgroup= BLI_countlist(&vc.obact->defbase);
                                        if(totgroup) {
 -                                              MFace *mf= ((MFace *)me->mface) + index-1;
 -                                              unsigned int fidx= mf->v4 ? 3:2;
 +                                              MPoly *mf= ((MPoly *)me->mpoly) + index-1;
 +                                              unsigned int fidx= mf->totloop - 1;
                                                int *groups= MEM_callocN(totgroup*sizeof(int), "groups");
                                                int found= FALSE;
  
                                                do {
 -                                                      MDeformVert *dvert= me->dvert + (*(&mf->v1 + fidx));
 +                                                      MDeformVert *dvert= me->dvert + me->mloop[mf->loopstart + fidx].v;
                                                        int i= dvert->totweight;
                                                        MDeformWeight *dw;
                                                        for(dw= dvert->dw; i > 0; dw++, i--) {
@@@ -1421,16 -1342,16 +1421,16 @@@ static void enforce_locks(MDeformVert *
                if(vgroup_validmap && total_changed < 0 && total_valid) {
                        totchange_allowed = total_valid;
                }
+               /* the way you modify the unlocked+unchanged groups is different depending
+                * on whether or not you are painting the weight(s) up or down */
+               if(totchange < 0) {
+                       totchange_allowed = total_valid - totchange_allowed;
+               }
+               else {
+                       totchange_allowed *= -1;
+               }
                /* there needs to be change allowed, or you should not bother */
                if(totchange_allowed) {
-                       /* the way you modify the unlocked+unchanged groups is different depending
-                        * on whether or not you are painting the weight(s) up or down */
-                       if(totchange < 0) {
-                               totchange_allowed = total_valid - totchange_allowed;
-                       }
-                       else {
-                               totchange_allowed *= -1;
-                       }
                        left_over = 0;
                        if(fabsf(totchange_allowed) < fabsf(totchange)) {
                                /* this amount goes back onto the changed, unlocked weights */
                                        odw = defvert_find_index(odv, designatedw);
                                        storedw = ndw->weight;
                                        for(i = 0; i < ndv->totweight; i++) {
-                                               if(change_status[ndw->def_nr] == 2) {
+                                               if(ndv->dw[i].def_nr == designatedw) {
+                                                       continue;
+                                               }
+                                               ndw2 = &ndv->dw[i];
+                                               if(change_status[ndw2->def_nr] == 2) {
                                                        odw2 = &odv->dw[i];
-                                                       ndw2 = &ndv->dw[i];
+                                                       
                                                        if(!designatedw_changed) {
-                                                               ndw->weight = (totchange_allowed + odw->weight + odw2->weight)/(1.0f + ndw2->weight/ndw->weight);
+                                                               ndw->weight = (-left_over + odw->weight + odw2->weight)/(1.0f + ndw2->weight/ndw->weight);
                                                                designatedw_changed = TRUE;
                                                        }
                                                        ndw2->weight = ndw->weight * ndw2->weight / storedw;
@@@ -1937,13 -1862,6 +1941,13 @@@ static int wpaint_stroke_test_start(bCo
        me= get_mesh(ob);
        if(me==NULL || me->totface==0) return OPERATOR_PASS_THROUGH;
        
 +      /*we can't assume mfaces have a correct origindex layer that indices to mpolys.
 +        so instead we have to regenerate the tesselation faces altogether.*/
 +      me->totface = mesh_recalcTesselation(&me->fdata, &me->ldata, &me->pdata, 
 +              me->mvert, me->totface, me->totloop, me->totpoly, 1, 0);
 +      mesh_update_customdata_pointers(me);
 +      makeDerivedMesh(scene, ob, NULL, CD_MASK_BAREMESH, 0);
 +
        /* if nothing was added yet, we make dverts and a vertex deform group */
        if (!me->dvert) {
                ED_vgroup_data_create(&me->id);
@@@ -2086,22 -2004,22 +2090,22 @@@ static void wpaint_stroke_update_step(b
                        
        if(wp->flag & VP_COLINDEX) {
                for(index=0; index<totindex; index++) {
 -                      if(indexar[index] && indexar[index]<=me->totface) {
 -                              MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
 +                      if(indexar[index] && indexar[index]<=me->totpoly) {
 +                              MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
                                                
 -                              if(mface->mat_nr!=ob->actcol-1) {
 +                              if(mpoly->mat_nr!=ob->actcol-1) {
                                        indexar[index]= 0;
                                }
                        }
                }
        }
                        
 -      if((me->editflag & ME_EDIT_PAINT_MASK) && me->mface) {
 +      if((me->editflag & ME_EDIT_PAINT_MASK) && me->mpoly) {
                for(index=0; index<totindex; index++) {
 -                      if(indexar[index] && indexar[index]<=me->totface) {
 -                              MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
 +                      if(indexar[index] && indexar[index]<=me->totpoly) {
 +                              MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
                                                
 -                              if((mface->flag & ME_FACE_SEL)==0) {
 +                              if((mpoly->flag & ME_FACE_SEL)==0) {
                                        indexar[index]= 0;
                                }
                        }                                       
                paintweight= ts->vgroup_weight;
                        
        for(index=0; index<totindex; index++) {
 -              if(indexar[index] && indexar[index]<=me->totface) {
 -                      MFace *mface= me->mface + (indexar[index]-1);
 +              if(indexar[index] && indexar[index]<=me->totpoly) {
 +                      MPoly *mpoly= me->mpoly + (indexar[index]-1);
 +                      MLoop *ml = me->mloop + mpoly->loopstart;
 +                      int i;
  
                        if(use_vert_sel) {
 -                              me->dvert[mface->v1].flag = (me->mvert[mface->v1].flag & SELECT);
 -                              me->dvert[mface->v2].flag = (me->mvert[mface->v2].flag & SELECT);
 -                              me->dvert[mface->v3].flag = (me->mvert[mface->v3].flag & SELECT);
 -                              if(mface->v4) me->dvert[mface->v4].flag = (me->mvert[mface->v4].flag & SELECT);
 +                              for (i=0; i<mpoly->totloop; i++, ml++) {
 +                                      me->dvert[ml->v].flag = (me->mvert[ml->v].flag & SELECT);
 +                              }
                        }
                        else {
 -                              me->dvert[mface->v1].flag= 1;
 -                              me->dvert[mface->v2].flag= 1;
 -                              me->dvert[mface->v3].flag= 1;
 -                              if(mface->v4) me->dvert[mface->v4].flag= 1;
 +                              for (i=0; i<mpoly->totloop; i++, ml++) {
 +                                      me->dvert[ml->v].flag = 1;
 +                              }
                        }
                                        
                        if(brush->vertexpaint_tool==VP_BLUR) {
                                MDeformWeight *dw, *(*dw_func)(MDeformVert *, const int);
 -                              unsigned int fidx= mface->v4 ? 3:2;
                                                
                                if(wp->flag & VP_ONLYVGROUP)
                                        dw_func= (MDeformWeight *(*)(MDeformVert *, const int))defvert_find_index;
                                else
                                        dw_func= defvert_verify_index;
 -
 -                              do {
 -                                      unsigned int vidx= *(&mface->v1 + fidx);
 -
 -                                      dw= dw_func(me->dvert+vidx, ob->actdef-1);
 -                                      if(dw) {
 -                                              paintweight+= dw->weight;
 +                                              
 +                              ml = me->mloop + mpoly->loopstart;
 +                              for (i=0; i<mpoly->totloop; i++, ml++) {
 +                                      dw = dw_func(me->dvert+ml->v, ob->actdef-1);
 +                                      if (dw) {
 +                                              paintweight += dw->weight;
                                                totw++;
                                        }
 -
 -                              } while (fidx--);
 -
 +                              }
                        }
                }
        }
                paintweight/= (float)totw;
                        
        for(index=0; index<totindex; index++) {
 -                              
 -              if(indexar[index] && indexar[index]<=me->totface) {
 -                      MFace *mf= me->mface + (indexar[index]-1);
 -                      unsigned int fidx= mf->v4 ? 3:2;
 -                      do {
 -                              unsigned int vidx= *(&mf->v1 + fidx);
 -
 -                              if(me->dvert[vidx].flag) {
 +              if(indexar[index] && indexar[index]<=me->totpoly) {
 +                      MPoly *mpoly= me->mpoly + (indexar[index]-1);
 +                      MLoop *ml=me->mloop+mpoly->loopstart;
 +                      int i;
 +
 +                      for (i=0; i<mpoly->totloop; i++, ml++) {
 +                              unsigned int vidx= ml->v;
 +                              if (me->dvert[vidx].flag) {
                                        alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*vidx, mval, pressure);
                                        if(alpha) {
                                                do_weight_paint_vertex(wp, ob, &wpi, vidx, alpha, paintweight);
                                        }
                                        me->dvert[vidx].flag= 0;
                                }
 -                      } while (fidx--);
 +                      }
                }
        }
  
@@@ -2311,7 -2233,7 +2315,7 @@@ static int set_vpaint(bContext *C, wmOp
                return OPERATOR_PASS_THROUGH;
        }
        
 -      if(me && me->mcol==NULL) make_vertexcol(ob);
 +      if(me && me->mloopcol==NULL) make_vertexcol(ob);
        
        /* toggle: end vpaint */
        if(ob->mode & OB_MODE_VERTEX_PAINT) {
@@@ -2379,60 -2301,14 +2383,60 @@@ For future
  
  */
  
 +typedef struct polyfacemap_e {
 +      struct polyfacemap_e *next, *prev;
 +      int facenr;
 +} polyfacemap_e;
 +
  typedef struct VPaintData {
        ViewContext vc;
        unsigned int paintcol;
        int *indexar;
        float *vertexcosnos;
        float vpimat[3][3];
 +      
 +      /*mpoly -> mface mapping*/
 +      MemArena *arena;
 +      ListBase *polyfacemap;
  } VPaintData;
  
 +static void vpaint_build_poly_facemap(struct VPaintData *vd, Mesh *me,
 +                                    Object *ob, Scene *scene)
 +{
 +      MFace *mf;
 +      polyfacemap_e *e;
 +      int *origIndex;
 +      int i;
 +
 +      vd->arena = BLI_memarena_new(1<<13, "vpaint tmp");
 +      BLI_memarena_use_calloc(vd->arena);
 +
 +      vd->polyfacemap = BLI_memarena_alloc(vd->arena, sizeof(ListBase)*me->totpoly);
 +
 +      /*we can't assume mfaces have a correct origindex layer that indices to mpolys.
 +        so instead we have to regenerate the tesselation faces altogether.*/
 +      me->totface = mesh_recalcTesselation(&me->fdata, &me->ldata, &me->pdata, 
 +              me->mvert, me->totface, me->totloop, me->totpoly, 1, 0);
 +      mesh_update_customdata_pointers(me);
 +      makeDerivedMesh(scene, ob, NULL, CD_MASK_BAREMESH, 0);
 +
 +      origIndex = CustomData_get_layer(&me->fdata, CD_ORIGINDEX);
 +      mf = me->mface;
 +
 +      if (!origIndex)
 +              return;
 +
 +      for (i=0; i<me->totface; i++, mf++, origIndex++) {
 +              if (*origIndex == ORIGINDEX_NONE)
 +                      continue;
 +
 +              e = BLI_memarena_alloc(vd->arena, sizeof(polyfacemap_e));
 +              e->facenr = i;
 +              
 +              BLI_addtail(&vd->polyfacemap[*origIndex], e);
 +      }
 +}
 +
  static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent *UNUSED(event))
  {
        ToolSettings *ts= CTX_data_tool_settings(C);
        VPaint *vp= ts->vpaint;
        struct VPaintData *vpd;
        Object *ob= CTX_data_active_object(C);
 +      Scene *scene = CTX_data_scene(C);
        Mesh *me;
        float mat[4][4], imat[4][4];
  
        /* context checks could be a poll() */
        me= get_mesh(ob);
 -      if(me==NULL || me->totface==0) return OPERATOR_PASS_THROUGH;
 +      if(me==NULL || me->totpoly==0)
 +              return OPERATOR_PASS_THROUGH;
        
 -      if(me->mcol==NULL) make_vertexcol(ob);
 -      if(me->mcol==NULL) return OPERATOR_CANCELLED;
 +      if(me->mloopcol==NULL)
 +              make_vertexcol(ob);
 +      if(me->mloopcol==NULL)
 +              return OPERATOR_CANCELLED;
        
        /* make mode data storage */
        vpd= MEM_callocN(sizeof(struct VPaintData), "VPaintData");
        vpd->vertexcosnos= mesh_get_mapped_verts_nors(vpd->vc.scene, ob);
        vpd->indexar= get_indexarray(me);
        vpd->paintcol= vpaint_get_current_col(vp);
 +      vpaint_build_poly_facemap(vpd, me, ob, scene);
        
        /* for filtering */
 -      copy_vpaint_prev(vp, (unsigned int *)me->mcol, me->totface);
 +      copy_vpaint_prev(vp, (unsigned int *)me->mloopcol, me->totloop);
        
        /* some old cruft to sort out later */
        mul_m4_m4m4(mat, ob->obmat, vpd->vc.rv3d->viewmat);
        return 1;
  }
  
 -static void vpaint_paint_face(VPaint *vp, VPaintData *vpd, Object *ob, const unsigned int index, const float mval[2], float pressure, int UNUSED(flip))
 +#if 0
 +static void vpaint_paint_face(VPaint *vp, VPaintData *vpd, Object *ob, int index, const float mval[2], float pressure, int UNUSED(flip))
  {
        ViewContext *vc = &vpd->vc;
        Brush *brush = paint_brush(&vp->paint);
                        vpaint_blend(vp, mcol+i, mcolorig+i, vpd->paintcol, (int)(alpha*255.0f));
        }
  }
 +#endif
  
  static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
  {
        Brush *brush = paint_brush(&vp->paint);
        ViewContext *vc= &vpd->vc;
        Object *ob= vc->obact;
 +      polyfacemap_e *e;
        Mesh *me= ob->data;
        float mat[4][4];
        int *indexar= vpd->indexar;
                        
        /* which faces are involved */
        if(vp->flag & VP_AREA) {
 -              totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], brush_size(brush));
 +              totindex= sample_backbuf_area(vc, indexar, me->totpoly, mval[0], mval[1], brush_size(brush));
        }
        else {
                indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]);
                        
        swap_m4m4(vc->rv3d->persmat, mat);
                        
 -      for(index=0; index<totindex; index++) {                         
 -              if(indexar[index] && indexar[index]<=me->totface)
 -                      vpaint_paint_face(vp, vpd, ob, indexar[index]-1, mval, pressure, flip);
 +      if(vp->flag & VP_COLINDEX) {
 +              for(index=0; index<totindex; index++) {
 +                      if(indexar[index] && indexar[index]<=me->totpoly) {
 +                              MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
 +                                              
 +                              if(mpoly->mat_nr!=ob->actcol-1) {
 +                                      indexar[index]= 0;
 +                              }
 +                      }                                       
 +              }
        }
 +
 +      if((me->editflag & ME_EDIT_PAINT_MASK) && me->mpoly) {
 +              for(index=0; index<totindex; index++) {
 +                      if(indexar[index] && indexar[index]<=me->totpoly) {
 +                              MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
                                                
 +                              if((mpoly->flag & ME_FACE_SEL)==0)
 +                                      indexar[index]= 0;
 +                      }                                       
 +              }
 +      }
 +      
        swap_m4m4(vc->rv3d->persmat, mat);
  
        /* was disabled because it is slow, but necessary for blur */
        if(brush->vertexpaint_tool == VP_BLUR)
                do_shared_vertexcol(me);
                        
 -      ED_region_tag_redraw(vc->ar);
 +      for(index=0; index<totindex; index++) {
 +                              
 +              if(indexar[index] && indexar[index]<=me->totpoly) {
 +                      MPoly *mpoly= ((MPoly *)me->mpoly) + (indexar[index]-1);
 +                      MFace *mf;
 +                      MCol *mc;
 +                      MLoop *ml;
 +                      MLoopCol *mlc;
 +                      unsigned int *lcol = ((unsigned int*)me->mloopcol) + mpoly->loopstart;
 +                      unsigned int *lcolorig = ((unsigned int*)vp->vpaint_prev) + mpoly->loopstart;
 +                      float alpha;
 +                      int i, j;
 +                                      
 +                      if(brush->vertexpaint_tool==VP_BLUR) {
 +                              unsigned int blend[5] = {0};
 +                              char *col;
 +
 +                              for (j=0; j<mpoly->totloop; j += 2) {
 +                                      col = (char*)(lcol + j);
 +                                      blend[0] += col[0];
 +                                      blend[1] += col[1];
 +                                      blend[2] += col[2];
 +                                      blend[3] += col[3];
 +                              }
 +
 +                              blend[0] /= mpoly->totloop;
 +                              blend[1] /= mpoly->totloop;
 +                              blend[2] /= mpoly->totloop;
 +                              blend[3] /= mpoly->totloop;
 +                              col = (char*)(blend + 4);
 +                              col[0] = blend[0];
 +                              col[1] = blend[1];
 +                              col[2] = blend[2];
 +                              col[3] = blend[3];
 +
 +                              vpd->paintcol = *((unsigned int*)col);
 +                      }
 +
 +                      ml = me->mloop + mpoly->loopstart;
 +                      for (i=0; i<mpoly->totloop; i++, ml++) {
 +                              alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, 
 +                                         vpd->vertexcosnos+6*ml->v, mval, pressure);
 +                              if(alpha > 0.0f) vpaint_blend(vp, lcol+i, lcolorig+i, vpd->paintcol, (int)(alpha*255.0f));
 +                      }
 +      
 +                      #ifdef CPYCOL
 +                      #undef CPYCOL
 +                      #endif
 +                      #define CPYCOL(c, l) (c)->a = (l)->a, (c)->r = (l)->r, (c)->g = (l)->g, (c)->b = (l)->b
 +
 +                      /*update vertex colors for tesselations incrementally,
 +                        rather then regenerating the tesselation altogether.*/
 +                      for (e=vpd->polyfacemap[(indexar[index]-1)].first; e; e=e->next) {
 +                              mf = me->mface + e->facenr;
 +                              mc = me->mcol + e->facenr*4;
 +                              
 +                              ml = me->mloop + mpoly->loopstart;
 +                              mlc = me->mloopcol + mpoly->loopstart;
 +                              for (j=0; j<mpoly->totloop; j++, ml++, mlc++) {
 +                                      if (ml->v == mf->v1)
 +                                              CPYCOL(mc, mlc);
 +                                      else if (ml->v == mf->v2)
 +                                              CPYCOL(mc+1, mlc);
 +                                      else if (ml->v == mf->v3)
 +                                              CPYCOL(mc+2, mlc);
 +                                      else if (mf->v4 && ml->v == mf->v4)
 +                                              CPYCOL(mc+3, mlc);
 +
 +                              }
 +                      }
 +                      #undef CPYCOL
 +              }
 +      }
 +              
 +      swap_m4m4(vc->rv3d->persmat, mat);
                        
 +      /* was disabled because it is slow, but necessary for blur */
 +      if(brush->vertexpaint_tool == VP_BLUR) {
 +              do_shared_vertexcol(me);
 +      }
 +
 +      ED_region_tag_redraw(vc->ar);           
        DAG_id_tag_update(ob->data, 0);
  }
  
@@@ -2676,8 -2446,7 +2680,8 @@@ static void vpaint_stroke_done(bContex
        
        /* frees prev buffer */
        copy_vpaint_prev(ts->vpaint, NULL, 0);
 -      
 +      BLI_memarena_free(vpd->arena);
 +
        MEM_freeN(vpd);
  }
  
index b104c5bb513d7dcf997fe0db1e014fb9d2654326,7ab1b24e9b3911937e39b5e9c61f35e8dd4afcb8..5b2e83cbfbd5cd8edadab2bdf6a5dfd0def65159
@@@ -73,7 -73,6 +73,7 @@@
  #include "BKE_sequencer.h"
  #include "BKE_pointcache.h"
  #include "BKE_bmesh.h"
 +#include "BKE_tessmesh.h"
  #include "BKE_scene.h"
  #include "BKE_report.h"
  #include "BKE_tracking.h"
  #include "BLI_math.h"
  #include "BLI_blenlib.h"
  #include "BLI_editVert.h"
 +#include "BLI_array.h"
  #include "BLI_utildefines.h"
 +#include "BLI_smallhash.h"
  
  #include "RNA_access.h"
  
  extern ListBase editelems;
  
  #include "transform.h"
 +#include "bmesh.h"
  
  #include "BLO_sys_types.h" // for intptr_t support
  
@@@ -299,20 -295,18 +299,20 @@@ static void createTransTexspace(TransIn
  /* ********************* edge (for crease) ***** */
  
  static void createTransEdge(TransInfo *t) {
 -      EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
 +      BMEditMesh *em = ((Mesh *)t->obedit->data)->edit_btmesh;
        TransData *td = NULL;
 -      EditEdge *eed;
 +      BMEdge *eed;
 +      BMIter iter;
        float mtx[3][3], smtx[3][3];
        int count=0, countsel=0;
        int propmode = t->flag & T_PROP_EDIT;
  
 -      for(eed= em->edges.first; eed; eed= eed->next) {
 -              if(eed->h==0) {
 -                      if (eed->f & SELECT) countsel++;
 -                      if (propmode) count++;
 -              }
 +      BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
 +              if (BM_TestHFlag(eed, BM_HIDDEN))
 +                      continue;
 +
 +              if (BM_TestHFlag(eed, BM_SELECT)) countsel++;
 +              if (propmode) count++;
        }
  
        if (countsel == 0)
        copy_m3_m4(mtx, t->obedit->obmat);
        invert_m3_m3(smtx, mtx);
  
 -      for(eed= em->edges.first; eed; eed= eed->next) {
 -              if(eed->h==0 && (eed->f & SELECT || propmode)) {
 +      BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
 +              if(!BM_TestHFlag(eed, BM_HIDDEN) && (BM_TestHFlag(eed, BM_SELECT) || propmode)) { 
 +                      float *bweight = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_BWEIGHT);
 +                      float *crease = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_CREASE);
 +                      
                        /* need to set center for center calculations */
                        add_v3_v3v3(td->center, eed->v1->co, eed->v2->co);
                        mul_v3_fl(td->center, 0.5f);
  
                        td->loc= NULL;
 -                      if (eed->f & SELECT)
 +                      if (BM_TestHFlag(eed, BM_SELECT))
                                td->flag= TD_SELECTED;
                        else
                                td->flag= 0;
  
                        td->ext = NULL;
                        if (t->mode == TFM_BWEIGHT) {
 -                              td->val = &(eed->bweight);
 -                              td->ival = eed->bweight;
 +                              td->val = bweight;
 +                              td->ival = bweight ? *bweight : 1.0f;
                        }
                        else {
 -                              td->val = &(eed->crease);
 -                              td->ival = eed->crease;
 +                              td->val = crease;
 +                              td->ival = crease ? *crease : 0.0f;
                        }
  
                        td++;
@@@ -1824,144 -1815,113 +1824,144 @@@ void flushTransParticles(TransInfo *t
  /* proportional distance based on connectivity  */
  #define THRESHOLDFACTOR (1.0f-0.0001f)
  
 -static int connectivity_edge(float mtx[][3], EditVert *v1, EditVert *v2)
 +/*I did this wrong, it should be a breadth-first search
 +  but instead it's a depth-first search, fudged
 +  to report shortest distances.  I have no idea how fast
 +  or slow this is.*/
 +static void editmesh_set_connectivity_distance(BMEditMesh *em, float mtx[][3], float *dists)
  {
 -      float edge_vec[3];
 -      float edge_len;
 -      int done = 0;
 -
 -      /* note: hidden verts are not being checked for, this assumes
 -       * flushing of hidden faces & edges is working right */
 -      
 -      if (v1->f2 + v2->f2 == 4)
 -              return 0;
 +      BMVert **queue = NULL;
 +      float *dqueue = NULL;
 +      int *tots = MEM_callocN(sizeof(int)*em->bm->totvert, "tots editmesh_set_connectivity_distance");
 +      BLI_array_declare(queue);
 +      BLI_array_declare(dqueue);
 +      SmallHash svisit, *visit=&svisit;
 +      BMVert *v;
 +      BMIter viter;
 +      int i, start;
        
 -      sub_v3_v3v3(edge_vec, v1->co, v2->co);
 -      mul_m3_v3(mtx, edge_vec);
 -
 -      edge_len = len_v3(edge_vec);
 -
 -      if (v1->f2) {
 -              if (v2->f2) {
 -                      if (v2->tmp.fp + edge_len < THRESHOLDFACTOR * v1->tmp.fp) {
 -                              v1->tmp.fp = v2->tmp.fp + edge_len;
 -                              done = 1;
 -                      } else if (v1->tmp.fp + edge_len < THRESHOLDFACTOR * v2->tmp.fp) {
 -                              v2->tmp.fp = v1->tmp.fp + edge_len;
 -                              done = 1;
 -                      }
 -              }
 -              else {
 -                      v2->f2 = 1;
 -                      v2->tmp.fp = v1->tmp.fp + edge_len;
 -                      done = 1;
 -              }
 -      }
 -      else if (v2->f2) {
 -              v1->f2 = 1;
 -              v1->tmp.fp = v2->tmp.fp + edge_len;
 -              done = 1;
 +      i = 0;
 +      BM_ITER(v, &viter, em->bm, BM_VERTS_OF_MESH, NULL) {
 +              BM_SetIndex(v, i);
 +              dists[i] = FLT_MAX;
 +              i++;
        }
 +      
 +      BLI_smallhash_init(visit);
  
 -      return done;
 -}
 -
 -static void editmesh_set_connectivity_distance(EditMesh *em, float mtx[][3])
 -{
 -      EditVert *eve;
 -      EditEdge *eed;
 -      EditFace *efa;
 -      int done= 1;
 -
 -      /* f2 flag is used for 'selection' */
 -      /* tmp.l is offset on scratch array   */
 -      for(eve= em->verts.first; eve; eve= eve->next) {
 -              if(eve->h==0) {
 -                      eve->tmp.fp = 0;
 -
 -                      if(eve->f & SELECT) {
 -                              eve->f2= 2;
 -                      }
 -                      else {
 -                              eve->f2 = 0;
 -                      }
 -              }
 +      BM_ITER(v, &viter, em->bm, BM_VERTS_OF_MESH, NULL) {
 +              if (BM_TestHFlag(v, BM_SELECT)==0 || BM_TestHFlag(v, BM_HIDDEN))
 +                      continue;
 +                      
 +              
 +              BLI_smallhash_insert(visit, (uintptr_t)v, NULL);
 +              BLI_array_append(queue, v);
 +              BLI_array_append(dqueue, 0.0f);
 +              dists[BM_GetIndex(v)] = 0.0f;
        }
 +      
 +      start = 0;
 +      while (start < BLI_array_count(queue)) {
 +              BMIter eiter;
 +              BMEdge *e;
 +              BMVert *v3, *v2;
 +              float d, vec[3];
 +              
 +              v2 = queue[start];
 +              d = dqueue[start];
 +              
 +              BM_ITER(e, &eiter, em->bm, BM_EDGES_OF_VERT, v2) {
 +                      float d2;
 +                      v3 = BM_OtherEdgeVert(e, v2);
 +                      
 +                      if (BM_TestHFlag(v3, BM_SELECT) || BM_TestHFlag(v3, BM_HIDDEN))
 +                              continue;
 +                      
 +                      sub_v3_v3v3(vec, v2->co, v3->co);
 +                      mul_m3_v3(mtx, vec);
 +                      
 +                      d2 = d + len_v3(vec);
 +                      
 +                      if (dists[BM_GetIndex(v3)] != FLT_MAX)
 +                              dists[BM_GetIndex(v3)] = MIN2(d2, dists[BM_GetIndex(v3)]);
 +                      else
 +                              dists[BM_GetIndex(v3)] = d2;
 +                      
 +                      tots[BM_GetIndex(v3)] = 1;
  
 -
 -      /* Floodfill routine */
 -      /*
 -      At worst this is n*n of complexity where n is number of edges
 -      Best case would be n if the list is ordered perfectly.
 -      Estimate is n log n in average (so not too bad)
 -      */
 -      while(done) {
 -              done= 0;
 -
 -              for(eed= em->edges.first; eed; eed= eed->next) {
 -                      if(eed->h==0) {
 -                              done |= connectivity_edge(mtx, eed->v1, eed->v2);
 -                      }
 +                      if (BLI_smallhash_haskey(visit, (uintptr_t)v3))
 +                              continue;
 +                      
 +                      BLI_smallhash_insert(visit, (uintptr_t)v3, NULL);
 +                      
 +                      BLI_array_append(queue, v3);
 +                      BLI_array_append(dqueue, d2);
                }
 +              
 +              start++;
 +      }
  
 -              /* do internal edges for quads */
 -              for(efa= em->faces.first; efa; efa= efa->next) {
 -                      if (efa->v4 && efa->h==0) {
 -                              done |= connectivity_edge(mtx, efa->v1, efa->v3);
 -                              done |= connectivity_edge(mtx, efa->v2, efa->v4);
 -                      }
 -              }
 +      BLI_smallhash_release(visit);
 +      
 +      for (i=0; i<em->bm->totvert; i++) {
 +              if (tots[i])
 +                      dists[i] /= (float)tots[i];
        }
 +      
 +      BLI_array_free(queue);
 +      BLI_array_free(dqueue);
 +      MEM_freeN(tots);
  }
  
  /* loop-in-a-loop I know, but we need it! (ton) */
 -static void get_face_center(float *cent, EditMesh *em, EditVert *eve)
 + static void get_face_center(float *centout, BMesh *bm, BMVert *eve)
 +
  {
 -      EditFace *efa;
 +      BMFace *efa;
 +      BMLoop *l;
 +      BMIter iter;
 +      float cent[3] = {0.0, 0.0, 0.0};
  
 -      for(efa= em->faces.first; efa; efa= efa->next)
 -              if(efa->f & SELECT)
 -                      if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve)
 -                              break;
 -      if(efa) {
 -              copy_v3_v3(cent, efa->cent);
 +      efa = BMIter_New(&iter, bm, BM_FACES_OF_VERT, eve);
 +      if (efa) {
 +              l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa);
 +              for ( ; l; l=BMIter_Step(&iter)) {
 +                      VECADD(cent, cent, l->v->co);
 +              }
 +
 +              mul_v3_fl(cent, 1.0f / (float)efa->len);
        }
 +
 +      if (cent[0] == 0.0f && cent[1] == 0.0f && cent[2] == 0.0f) cent[2] = 1.0f;
 +      copy_v3_v3(centout, cent);
  }
  
 +#define VertsToTransData(t, td, em, eve, bweight) \
 +      td->flag = 0;\
 +      td->loc = eve->co;\
 +      copy_v3_v3(td->center, td->loc);\
 +      if(t->around==V3D_LOCAL && (em->selectmode & SCE_SELECT_FACE))\
 +              get_face_center(td->center, em, eve);\
 +      copy_v3_v3(td->iloc, td->loc);\
 +      copy_v3_v3(td->axismtx[2], eve->no);\
 +      td->axismtx[0][0]               =\
 +              td->axismtx[0][1]       =\
 +              td->axismtx[0][2]       =\
 +              td->axismtx[1][0]       =\
 +              td->axismtx[1][1]       =\
 +              td->axismtx[1][2]       = 0.0f;\
 +      td->ext = NULL;\
 +      td->val = NULL;\
 +      td->extra = NULL;\
 +      if (t->mode == TFM_BWEIGHT) {\
 +              td->val = bweight;\
 +              td->ival = bweight ? *(bweight) : 1.0f;\
 +      }
 +
 +#if 0
  //way to overwrite what data is edited with transform
  //static void VertsToTransData(TransData *td, EditVert *eve, BakeKey *key)
 -static void VertsToTransData(TransInfo *t, TransData *td, EditMesh *em, EditVert *eve)
 +inline void VertsToTransData(TransInfo *t, TransData *td, BMesh *em, BMVert *eve)
  {
        td->flag = 0;
        //if(key)
                td->ival = eve->bweight;
        }
  }
 +#endif
  
 -#if 0
 -static void createTransBMeshVerts(TransInfo *t, BME_Mesh *bm, BME_TransData_Head *td) {
 -      BME_Vert *v;
 -      BME_TransData *vtd;
 -      TransData *tob;
 -      int i;
 +/* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
  
 -      tob = t->data = MEM_callocN(td->len*sizeof(TransData), "TransObData(Bevel tool)");
 +static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
 +{
 +      float *vec = userData;
  
 -      for (i=0,v=bm->verts.first;v;v=v->next) {
 -              if ( (vtd = BME_get_transdata(td,v)) ) {
 -                      tob->loc = vtd->loc;
 -                      tob->val = &vtd->factor;
 -                      copy_v3_v3(tob->iloc,vtd->co);
 -                      copy_v3_v3(tob->center,vtd->org);
 -                      copy_v3_v3(tob->axismtx[0],vtd->vec);
 -                      tob->axismtx[1][0] = vtd->max ? *vtd->max : 0;
 -                      tob++;
 -                      i++;
 -              }
 +      vec+= 3*index;
 +      VECCOPY(vec, co);
 +}
 +
 +static int modifiers_disable_subsurf_temporary(Object *ob)
 +{
 +      ModifierData *md;
 +      int disabled = 0;
 +
 +      for(md=ob->modifiers.first; md; md=md->next)
 +              if(md->type==eModifierType_Subsurf)
 +                      if(md->mode & eModifierMode_OnCage) {
 +                              md->mode ^= eModifierMode_DisableTemporary;
 +                              disabled= 1;
 +                      }
 +
 +      return disabled;
 +}
 +
 +/* disable subsurf temporal, get mapped cos, and enable it */
 +static float *get_crazy_mapped_editverts(TransInfo *t)
 +{
 +      Mesh *me= t->obedit->data;
 +      DerivedMesh *dm;
 +      float *vertexcos;
 +
 +      /* disable subsurf temporal, get mapped cos, and enable it */
 +      if(modifiers_disable_subsurf_temporary(t->obedit)) {
 +              /* need to make new derivemesh */
 +              makeDerivedMesh(t->scene, t->obedit, me->edit_btmesh, CD_MASK_BAREMESH, 0);
        }
 -      /* since td is a memarena, it can hold more transdata than actual elements
 -       * (i.e. we can't depend on td->len to determine the number of actual elements) */
 -      t->total = i;
 +
 +      /* now get the cage */
 +      dm= editbmesh_get_derived_cage(t->scene, t->obedit, me->edit_btmesh, CD_MASK_BAREMESH);
 +
 +      vertexcos= MEM_mallocN(3*sizeof(float)*me->edit_btmesh->bm->totvert, "vertexcos map");
 +      dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
 +
 +      dm->release(dm);
 +
 +      /* set back the flag, no new cage needs to be built, transform does it */
 +      modifiers_disable_subsurf_temporary(t->obedit);
 +
 +      return vertexcos;
  }
 -#endif
 +
 +#define TAN_MAKE_VEC(a, b, c) a[0]= b[0] + 0.2f*(b[0]-c[0]); a[1]= b[1] + 0.2f*(b[1]-c[1]); a[2]= b[2] + 0.2f*(b[2]-c[2])
 +static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
 +{
 +      float vecu[3], vecv[3];
 +      float q1[4], q2[4];
 +
 +      TAN_MAKE_VEC(vecu, v1, v2);
 +      TAN_MAKE_VEC(vecv, v1, v3);
 +      tri_to_quat( q1,v1, vecu, vecv);
 +
 +      TAN_MAKE_VEC(vecu, def1, def2);
 +      TAN_MAKE_VEC(vecv, def1, def3);
 +      tri_to_quat( q2,def1, vecu, vecv);
 +
 +      sub_qt_qtqt(quat, q2, q1);
 +}
 +#undef TAN_MAKE_VEC
  
  static void createTransEditVerts(bContext *C, TransInfo *t)
  {
        ToolSettings *ts = CTX_data_tool_settings(C);
        TransData *tob = NULL;
 -      EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
 -      EditVert *eve;
 -      EditVert *eve_act = NULL;
 +      BMEditMesh *em = ((Mesh *)t->obedit->data)->edit_btmesh;
 +      BMesh *bm = em->bm;
 +      BMVert *eve;
 +      BMIter iter;
 +      BMVert *eve_act = NULL;
        float *mappedcos = NULL, *quats= NULL;
        float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
 -      int count=0, countsel=0, a, totleft;
 +      float *dists=NULL;
 +      int count=0, countsel=0, a, totleft, *selstate = NULL;
 +      BLI_array_declare(selstate);
        int propmode = (t->flag & T_PROP_EDIT) ? (t->flag & (T_PROP_EDIT | T_PROP_CONNECTED)) : 0;
        int mirror = 0;
        short selectmode = ts->selectmode;
  
        if (t->flag & T_MIRROR)
        {
 +              EDBM_CacheMirrorVerts(em, TRUE);
                mirror = 1;
        }
  
                selectmode = SCE_SELECT_EDGE;
        }
  
 +      /* BMESH_TODO, writing into the index values is BAD!, means we cant
 +       * use the values for vertex mirror - campbell */
 +
        // transform now requires awareness for select mode, so we tag the f1 flags in verts
        if(selectmode & SCE_SELECT_VERTEX) {
 -              for(eve= em->verts.first; eve; eve= eve->next) {
 -                      if(eve->h==0 && (eve->f & SELECT))
 -                              eve->f1= SELECT;
 -                      else
 -                              eve->f1= 0;
 +              BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
 +                      if (BM_Selected(bm, eve)) {
 +                              BM_SetHFlag(eve, BM_TMP_TAG);
 +                      }
 +                      else {
 +                              BM_ClearHFlag(eve, BM_TMP_TAG);
 +                      }
                }
        }
        else if(selectmode & SCE_SELECT_EDGE) {
 -              EditEdge *eed;
 -              for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
 -              for(eed= em->edges.first; eed; eed= eed->next) {
 -                      if(eed->h==0 && (eed->f & SELECT))
 -                              eed->v1->f1= eed->v2->f1= SELECT;
 +              BMEdge *eed;
 +
 +              eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
 +              for( ; eve; eve=BMIter_Step(&iter)) BM_ClearHFlag(eve, BM_TMP_TAG);
 +
 +              eed = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
 +              for( ; eed; eed=BMIter_Step(&iter)) {
 +                      if (BM_Selected(bm, eed)) {
 +                              BM_SetHFlag(eed->v1, BM_TMP_TAG);
 +                              BM_SetHFlag(eed->v2, BM_TMP_TAG);
 +                      }
                }
        }
        else {
 -              EditFace *efa;
 -              for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
 -              for(efa= em->faces.first; efa; efa= efa->next) {
 -                      if(efa->h==0 && (efa->f & SELECT)) {
 -                              efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
 -                              if(efa->v4) efa->v4->f1= SELECT;
 +              BMFace *efa;
 +              eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
 +              for( ; eve; eve=BMIter_Step(&iter)) BM_ClearHFlag(eve, BM_TMP_TAG);
 +
 +              efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
 +              for( ; efa; efa=BMIter_Step(&iter)) {
 +                      if (BM_Selected(bm, efa)) {
 +                              BMIter liter;
 +                              BMLoop *l;
 +
 +                              l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, efa);
 +                              for (; l; l=BMIter_Step(&liter)) {
 +                                      BM_SetHFlag(l->v, BM_TMP_TAG);
 +                              }
                        }
                }
        }
  
 -      /* now we can count */
 -      for(eve= em->verts.first; eve; eve= eve->next) {
 -              if(eve->h==0) {
 -                      if(eve->f1) countsel++;
 -                      if(propmode) count++;
 +      /* now we can count. we store selection state in selstate, since
 +         get_crazy_mapped_editverts messes up the index state of the
 +         verts*/
 +      eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
 +      for(a=0; eve; eve=BMIter_Step(&iter), a++) {
 +              BLI_array_growone(selstate);
 +
 +              if (BM_TestHFlag(eve, BM_TMP_TAG)) {
 +                      selstate[a] = 1;
 +                      countsel++;
                }
 +              if(propmode) count++;
        }
  
 -       /* note: in prop mode we need at least 1 selected */
 -      if (countsel==0) return;
 +      /* note: in prop mode we need at least 1 selected */
 +      if (countsel == 0) {
 +              goto cleanup;
 +      }
  
        /* check active */
 -      if (em->selected.last) {
 -              EditSelection *ese = em->selected.last;
 -              if ( ese->type == EDITVERT ) {
 -                      eve_act = (EditVert *)ese->data;
 +      if (em->bm->selected.last) {
 +              BMEditSelection *ese = em->bm->selected.last;
 +              if (ese->htype == BM_VERT) {
 +                      eve_act = (BMVert *)ese->data;
                }
        }
  
  
 -      if(propmode) t->total = count;
 +      if(propmode) {
 +              t->total = count;
 +
 +              /* allocating scratch arrays */
 +              if (propmode & T_PROP_CONNECTED)
 +                      dists = MEM_mallocN(em->bm->totvert * sizeof(float), "scratch nears");
 +      }
        else t->total = countsel;
  
        tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
        copy_m3_m4(mtx, t->obedit->obmat);
        invert_m3_m3(smtx, mtx);
  
 -      if(propmode & T_PROP_CONNECTED) {
 -              editmesh_set_connectivity_distance(em, mtx);
 -      }
 +      if(propmode & T_PROP_CONNECTED)
 +              editmesh_set_connectivity_distance(em, mtx, dists);
  
        /* detect CrazySpace [tm] */
        if(modifiers_getCageIndex(t->scene, t->obedit, NULL, 1)>=0) {
                if(modifiers_isCorrectableDeformed(t->obedit)) {
                        /* check if we can use deform matrices for modifier from the
                           start up to stack, they are more accurate than quats */
 -                      totleft= editmesh_get_first_deform_matrices(t->scene, t->obedit, em, &defmats, &defcos);
 +                      totleft= editbmesh_get_first_deform_matrices(t->scene, t->obedit, em, &defmats, &defcos);
  
                        /* if we still have more modifiers, also do crazyspace
                           correction with quats, relative to the coordinates after
                        if(totleft > 0) {
                                mappedcos= crazyspace_get_mapped_editverts(t->scene, t->obedit);
                                quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
 -                              crazyspace_set_quats_editmesh(em, (float*)defcos, mappedcos, quats);
 +                              crazyspace_set_quats_editmesh(em, (float*)defcos, mappedcos, quats); /* BMESH_TODO, abuses vertex index, should use an int array */
                                if(mappedcos)
                                        MEM_freeN(mappedcos);
                        }
  
        /* find out which half we do */
        if(mirror) {
 -              for (eve=em->verts.first; eve; eve=eve->next) {
 -                      if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
 +              eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
 +              for(a=0; eve; eve=BMIter_Step(&iter), a++) {
 +                      if(!BM_TestHFlag(eve, BM_HIDDEN) && selstate[a] && eve->co[0]!=0.0f) {
                                if(eve->co[0]<0.0f)
                                {
                                        t->mirror = -1;
                }
        }
  
 -      for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
 -              if(eve->h==0) {
 -                      if(propmode || eve->f1) {
 -                              VertsToTransData(t, tob, em, eve);
 +      eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
 +      for(a=0; eve; eve=BMIter_Step(&iter), a++) {
 +              if(!BM_TestHFlag(eve, BM_HIDDEN)) {
 +                      if(propmode || selstate[a]) {
 +                              float *bweight = CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_BWEIGHT);
 +                              
 +                              VertsToTransData(t, tob, bm, eve, bweight);
  
                                /* selected */
 -                              if(eve->f1) tob->flag |= TD_SELECTED;
 +                              if(selstate[a]) tob->flag |= TD_SELECTED;
  
                                /* active */
                                if(eve == eve_act) tob->flag |= TD_ACTIVE;
  
                                if(propmode) {
 -                                      if (eve->f2) {
 -                                              tob->dist= eve->tmp.fp;
 -                                      }
 -                                      else {
 +                                      if (propmode & T_PROP_CONNECTED) {
 +                                              tob->dist = dists[a];
 +                                      } else {
                                                tob->flag |= TD_NOTCONNECTED;
                                                tob->dist = MAXFLOAT;
                                        }
                                }
  
                                /* CrazySpace */
 -                              if(defmats || (quats && eve->tmp.p)) {
 -                                      float mat[3][3], imat[3][3], qmat[3][3];
 +                              if(defmats || (quats && BM_GetIndex(eve) != -1)) {
 +                                      float mat[3][3], qmat[3][3], imat[3][3];
  
                                        /* use both or either quat and defmat correction */
 -                                      if(quats && eve->tmp.f) {
 -                                              quat_to_mat3( qmat,eve->tmp.p);
 +                                      if(quats && BM_GetIndex(eve) != -1) {
 +                                              quat_to_mat3(qmat, quats + 4*BM_GetIndex(eve));
  
                                                if(defmats)
                                                        mul_serie_m3(mat, mtx, qmat, defmats[a],
  
                                /* Mirror? */
                                if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
 -                                      EditVert *vmir= editmesh_get_x_mirror_vert(t->obedit, em, eve, tob->iloc, a);   /* initializes octree on first call */
 -                                      if(vmir != eve) {
 +                                      BMVert *vmir= EDBM_GetMirrorVert(em, eve); //t->obedit, em, eve, tob->iloc, a);
 +                                      if(vmir && vmir != eve) {
                                                tob->extra = vmir;
                                        }
                                }
                        }
                }
        }
 -      
 +
 +cleanup:
        /* crazy space free */
        if(quats)
                MEM_freeN(quats);
        if(defmats)
                MEM_freeN(defmats);
 +      if (dists)
 +              MEM_freeN(dists);
 +      
 +      BLI_array_free(selstate);
 +
 +      if (t->flag & T_MIRROR)
 +      {
 +              EDBM_EndMirrorCache(em);
 +              mirror = 1;
 +      }
  }
  
  /* *** NODE EDITOR *** */
@@@ -2483,33 -2348,30 +2483,33 @@@ static void createTransUVs(bContext *C
        Scene *scene = t->scene;
        TransData *td = NULL;
        TransData2D *td2d = NULL;
 -      MTFace *tf;
 +      MTexPoly *tf;
 +      MLoopUV *luv;
 +      BMEditMesh *em = ((Mesh *)t->obedit->data)->edit_btmesh;
 +      BMFace *efa;
 +      BMLoop *l;
 +      BMIter iter, liter;
        int count=0, countsel=0;
        int propmode = t->flag & T_PROP_EDIT;
  
 -      EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
 -      EditFace *efa;
 -
        if(!ED_space_image_show_uvedit(sima, t->obedit)) return;
  
        /* count */
 -      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)) {
 -                      efa->tmp.p = tf;
 +              if(!uvedit_face_visible(scene, ima, efa, tf)) {
 +                      BM_ClearHFlag(efa, BM_TMP_TAG);
 +                      continue;
 +              }
 +              
 +              BM_SetHFlag(efa, BM_TMP_TAG);
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                      if (uvedit_uv_selected(em, scene, l)) 
 +                              countsel++;
  
 -                      if (uvedit_uv_selected(scene, efa, tf, 0)) countsel++;
 -                      if (uvedit_uv_selected(scene, efa, tf, 1)) countsel++;
 -                      if (uvedit_uv_selected(scene, efa, tf, 2)) countsel++;
 -                      if (efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) countsel++;
                        if(propmode)
 -                              count += (efa->v4)? 4: 3;
 -              } else {
 -                      efa->tmp.p = NULL;
 +                              count++;
                }
        }
  
        td= t->data;
        td2d= t->data2d;
  
 -      for (efa= em->faces.first; efa; efa= efa->next) {
 -              if ((tf=(MTFace *)efa->tmp.p)) {
 -                      if (propmode) {
 -                              UVsToTransData(sima, td++, td2d++, tf->uv[0], uvedit_uv_selected(scene, efa, tf, 0));
 -                              UVsToTransData(sima, td++, td2d++, tf->uv[1], uvedit_uv_selected(scene, efa, tf, 1));
 -                              UVsToTransData(sima, td++, td2d++, tf->uv[2], uvedit_uv_selected(scene, efa, tf, 2));
 -                              if(efa->v4)
 -                                      UVsToTransData(sima, td++, td2d++, tf->uv[3], uvedit_uv_selected(scene, efa, tf, 3));
 -                      } else {
 -                              if(uvedit_uv_selected(scene, efa, tf, 0))                               UVsToTransData(sima, td++, td2d++, tf->uv[0], 1);
 -                              if(uvedit_uv_selected(scene, efa, tf, 1))                               UVsToTransData(sima, td++, td2d++, tf->uv[1], 1);
 -                              if(uvedit_uv_selected(scene, efa, tf, 2))                               UVsToTransData(sima, td++, td2d++, tf->uv[2], 1);
 -                              if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3))    UVsToTransData(sima, td++, td2d++, tf->uv[3], 1);
 -                      }
 +      BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
 +              if (!BM_TestHFlag(efa, BM_TMP_TAG))
 +                      continue;
 +
 +              tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +              BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
 +                      if (!propmode && !uvedit_uv_selected(em, scene, l))
 +                              continue;
 +                      
 +                      luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 +                      UVsToTransData(sima, td++, td2d++, luv->uv, uvedit_uv_selected(em, scene, l));
                }
        }
  
@@@ -2560,8 -2425,6 +2560,8 @@@ void flushTransUVs(TransInfo *t
  
        /* flush to 2d vector from internally used 3d vector */
        for(a=0, td= t->data2d; a<t->total; a++, td++) {
 +              if (!td->loc2d) continue;
 +              
                td->loc2d[0]= td->loc[0]*invx;
                td->loc2d[1]= td->loc[1]*invy;
  
@@@ -4904,7 -4767,7 +4904,7 @@@ void special_aftertrans_update(bContex
        if (t->spacetype==SPACE_VIEW3D) {
                if (t->obedit) {
                        if (cancelled==0) {
 -                              EM_automerge(t->scene, t->obedit, 1);
 +                              EDBM_automerge(t->scene, t->obedit, 1);
                        }
                }
        }
        else if (t->obedit) {
                if (t->obedit->type == OB_MESH)
                {
 -                      EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
 +                      BMEditMesh *em = ((Mesh *)t->obedit->data)->edit_btmesh;
                        /* table needs to be created for each edit command, since vertices can move etc */
                        mesh_octree_table(t->obedit, em, NULL, 'e');
                }
@@@ -5533,7 -5396,7 +5533,7 @@@ static void createTransTrackingData(bCo
        TransDataTracking *tdt;
        int framenr = sc->user.framenr;
  
-       if(clip && !BKE_movieclip_has_frame(clip, &sc->user)) {
+       if(!clip || !BKE_movieclip_has_frame(clip, &sc->user)) {
                t->total = 0;
                return;
        }
index 665215b6592a5ec58e0658d2be225551fa48a8a8,9933840a24ed6df3955f8568f3576099f8f29611..e83fc143ef114f5842999168fb7476c11e434cc7
@@@ -304,8 -304,6 +304,8 @@@ extern StructRNA RNA_MeshColorLayer
  extern StructRNA RNA_MeshDeformModifier;
  extern StructRNA RNA_MeshEdge;
  extern StructRNA RNA_MeshFace;
 +extern StructRNA RNA_MeshPolygon;
 +extern StructRNA RNA_MeshLoop;
  extern StructRNA RNA_MeshFloatProperty;
  extern StructRNA RNA_MeshFloatPropertyLayer;
  extern StructRNA RNA_MeshIntProperty;
@@@ -625,6 -623,8 +625,8 @@@ StructRNA *RNA_struct_base(StructRNA *t
  int RNA_struct_is_ID(StructRNA *type);
  int RNA_struct_is_a(StructRNA *type, StructRNA *srna);
  
+ int RNA_struct_undo_check(StructRNA *type);
  StructRegisterFunc RNA_struct_register(StructRNA *type);
  StructUnregisterFunc RNA_struct_unregister(StructRNA *type);
  void **RNA_struct_instance(PointerRNA *ptr);
index f0e841abdae414ee9214eb2268fd1df561233804,769ec880a65178a97c5ebe8c3cc03abc7d1b2e0c..816f103cc9d14420af1c040b5481aea038735531
@@@ -8,7 -8,7 +8,7 @@@ objs += 
  
  incs = '#/intern/guardedalloc #/intern/memutil #/intern/audaspace/intern ../blenkernel ../blenlib ../makesdna intern .'
  incs += ' ../windowmanager ../editors/include ../gpu ../imbuf ../ikplugin ../blenfont ../blenloader'
 -incs += ' ../render/extern/include'
 +incs += ' ../render/extern/include ../bmesh'
  incs += ' ../nodes'
  incs += ' #/extern/glew/include'
  
@@@ -65,4 -65,6 +65,6 @@@ if env['OURPLATFORM'] in ('win32-vc', '
  if env['WITH_BF_INTERNATIONAL']:
      defs.append('WITH_INTERNATIONAL')
  
- env.BlenderLib ( 'bf_rna', objs, Split(incs), defines=defs, libtype=['core','player'], priority = [165,20] )
+ rnalib = env.BlenderLib ( 'bf_rna', objs, Split(incs), defines=defs, libtype=['core','player'], priority = [165,20] )
+ Return ('rnalib')
index 042cf7486693ca8ec8d82015cc642a4c8824137a,c4508c718e5d0caa7a6656bc1253a22b5bca322d..a9d0ed1a0bf7d3a8adfa22c12bc9eb518d406859
@@@ -76,7 -76,7 +76,7 @@@
  
  /* copied from Mesh_getFromObject and adapted to RNA interface */
  /* settings: 0 - preview, 1 - render */
static Mesh *rna_Object_to_mesh(Object *ob, ReportList *reports, Scene *sce, int apply_modifiers, int settings)
+ Mesh *rna_Object_to_mesh(Object *ob, ReportList *reports, Scene *sce, int apply_modifiers, int settings)
  {
        Mesh *tmpmesh;
        Curve *tmpcu = NULL;
                                dm = mesh_create_derived_view( sce, ob, mask );
                        
                        tmpmesh = add_mesh( "Mesh" );
 -                      DM_to_mesh( dm, tmpmesh );
 +                      DM_to_mesh( dm, tmpmesh, ob );
                        dm->release( dm );
                }
                
@@@ -284,7 -284,7 +284,7 @@@ static void dupli_render_particle_set(S
                dupli_render_particle_set(scene, go->ob, level+1, enable);
  }
  /* When no longer needed, duplilist should be freed with Object.free_duplilist */
static void rna_Object_create_duplilist(Object *ob, ReportList *reports, Scene *sce)
+ void rna_Object_create_duplilist(Object *ob, ReportList *reports, Scene *sce)
  {
        if (!(ob->transflag & OB_DUPLI)) {
                BKE_report(reports, RPT_ERROR, "Object does not have duplis");
        /* ob->duplilist should now be freed with Object.free_duplilist */
  }
  
static void rna_Object_free_duplilist(Object *ob)
+ void rna_Object_free_duplilist(Object *ob)
  {
        if (ob->duplilist) {
                free_object_duplilist(ob->duplilist);
index c1fee1c16428b888b9131fd36b3b6eb8b6a8ef2f,c9c475a299ebbff855e32d8a15939e8bd0528d25..5f6b6255b68135dfeacf8d867006a327cf073152
@@@ -751,6 -751,16 +751,16 @@@ if(WITH_MOD_FLUID
        list(APPEND BLENDER_LINK_LIBS bf_intern_elbeem)
  endif()
  
+ if(WITH_CYCLES)
+       list(APPEND BLENDER_LINK_LIBS
+               cycles_render
+               cycles_bvh
+               cycles_device
+               cycles_kernel
+               cycles_util
+               cycles_subd)
+ endif()
  #if(UNIX)
        # Sort libraries
        set(BLENDER_SORTED_LIBS
                bf_editor_space_outliner
                bf_editor_space_script
                bf_editor_space_sequencer
-               bf_editor_space_sound
                bf_editor_space_time
                bf_editor_space_userpref
                bf_editor_space_view3d
                bf_python_ext
                bf_python_mathutils
                bf_ikplugin
 +              bf_bmesh
                bf_modifiers
                bf_blenkernel
                bf_nodes
                extern_minilzo
                extern_lzma
                extern_colamd
-               extern_libmv
                ge_logic_ketsji
                extern_recastnavigation
                ge_phys_common
                bf_blenfont
                bf_intern_audaspace
                bf_intern_mikktspace
+               bf_intern_cycles
+               cycles_render
+               cycles_bvh
+               cycles_device
+               cycles_kernel
+               cycles_util
+               cycles_subd
        )
  
        if(WITH_LIBMV)