merge with 2.5 at r21568
authorJoseph Eagar <joeedh@gmail.com>
Thu, 16 Jul 2009 06:27:37 +0000 (06:27 +0000)
committerJoseph Eagar <joeedh@gmail.com>
Thu, 16 Jul 2009 06:27:37 +0000 (06:27 +0000)
83 files changed:
1  2 
SConstruct
config/win32-vc-config.py
intern/guardedalloc/intern/mallocn.c
projectfiles_vc9/blender/blender.sln
projectfiles_vc9/blender/blender.vcproj
projectfiles_vc9/blender/blenkernel/BKE_blenkernel.vcproj
projectfiles_vc9/blender/editors/ED_editors.vcproj
source/blender/SConscript
source/blender/blenkernel/BKE_modifier.h
source/blender/blenkernel/BKE_utildefines.h
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/booleanops.c
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/blenkernel/intern/cloth.c
source/blender/blenkernel/intern/constraint.c
source/blender/blenkernel/intern/displist.c
source/blender/blenkernel/intern/exotic.c
source/blender/blenkernel/intern/fluidsim.c
source/blender/blenkernel/intern/mesh.c
source/blender/blenkernel/intern/modifier.c
source/blender/blenkernel/intern/multires.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/subsurf_ccg.c
source/blender/blenlib/BLI_editVert.h
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/bmesh/bmesh.h
source/blender/bmesh/bmesh_operators.h
source/blender/bmesh/intern/bmesh_interp.c
source/blender/bmesh/intern/bmesh_opdefines.c
source/blender/bmesh/operators/subdivideop.c
source/blender/bmesh/operators/subdivideop.h
source/blender/editors/armature/reeb.c
source/blender/editors/include/ED_mesh.h
source/blender/editors/include/ED_view3d.h
source/blender/editors/mesh/bmesh_select.c
source/blender/editors/mesh/bmesh_tools.c
source/blender/editors/mesh/bmeshutils.c
source/blender/editors/mesh/editmesh.c
source/blender/editors/mesh/editmesh_add.c
source/blender/editors/mesh/editmesh_lib.c
source/blender/editors/mesh/editmesh_loop.c
source/blender/editors/mesh/editmesh_mods.c
source/blender/editors/mesh/editmesh_tools.c
source/blender/editors/mesh/mesh_intern.h
source/blender/editors/mesh/mesh_layers.c
source/blender/editors/mesh/meshtools.c
source/blender/editors/object/object_edit.c
source/blender/editors/physics/editparticle.c
source/blender/editors/screen/screen_ops.c
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/editors/space_buttons/SConscript
source/blender/editors/space_buttons/buttons_ops.c
source/blender/editors/space_image/image_header.c
source/blender/editors/space_view3d/SConscript
source/blender/editors/space_view3d/drawobject.c
source/blender/editors/space_view3d/view3d_buttons.c
source/blender/editors/space_view3d/view3d_header.c
source/blender/editors/space_view3d/view3d_ops.c
source/blender/editors/space_view3d/view3d_select.c
source/blender/editors/transform/transform.c
source/blender/editors/transform/transform_conversions.c
source/blender/editors/transform/transform_generics.c
source/blender/editors/transform/transform_manipulator.c
source/blender/editors/transform/transform_ops.c
source/blender/editors/transform/transform_orientations.c
source/blender/editors/transform/transform_snap.c
source/blender/editors/uvedit/uvedit_draw.c
source/blender/editors/uvedit/uvedit_ops.c
source/blender/makesdna/DNA_meshdata_types.h
source/blender/makesdna/DNA_object_types.h
source/blender/makesrna/SConscript
source/blender/makesrna/intern/Makefile
source/blender/makesrna/intern/SConscript
source/blender/makesrna/intern/rna_mesh.c
source/blender/render/intern/source/convertblender.c
source/gameengine/Converter/BL_BlenderDataConversion.cpp
tools/Blender.py
tools/btools.py

diff --cc SConstruct
Simple merge
Simple merge
Simple merge
index 970a8bd736e3a5725a373932a31ebb1e5346198a,b8a478671150cf4940a601f6e98b362bc4f9999a..1396564d57864efe39e89d6be61d7c69802d7822
@@@ -8,8 -9,9 +9,8 @@@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C
                {98330220-47A6-42E0-9DE4-AD0FF5D204D6} = {98330220-47A6-42E0-9DE4-AD0FF5D204D6}\r
                {BAAE3F2B-BCF8-4E84-B8BA-CFB2D64945FE} = {BAAE3F2B-BCF8-4E84-B8BA-CFB2D64945FE}\r
                {C66F722C-46BE-40C9-ABAE-2EAC7A697EB8} = {C66F722C-46BE-40C9-ABAE-2EAC7A697EB8}\r
-               {9625642D-6F20-4FB6-A089-BE7441B223E3} = {9625642D-6F20-4FB6-A089-BE7441B223E3}\r
 -              {D1A9312F-4557-4982-A0F4-4D08508235F4} = {D1A9312F-4557-4982-A0F4-4D08508235F4}\r
                {884D8731-654C-4C7F-9A75-8F37A305BE1E} = {884D8731-654C-4C7F-9A75-8F37A305BE1E}\r
+               {E645CC32-4823-463E-82F0-46ADDE664018} = {E645CC32-4823-463E-82F0-46ADDE664018}\r
                {7495FE37-933A-4AC1-BB2A-B3FDB4DE4284} = {7495FE37-933A-4AC1-BB2A-B3FDB4DE4284}\r
                {FAF46346-65CC-4DB2-85C4-B99826F79D0C} = {FAF46346-65CC-4DB2-85C4-B99826F79D0C}\r
                {51FB3D48-2467-4BFA-A321-D848252B437E} = {51FB3D48-2467-4BFA-A321-D848252B437E}\r
index 7d8d70e43b588a046514a22eb9586c19363a50c0,497560b4a5a6cd6bf5104ca5d8ce2e0cea44d1e5..80fe23614435a83b960cc98a765aef1b3a8997ba
                <Filter\r
                        Name="mesh"\r
                        >\r
-                       <File\r
-                               RelativePath="..\..\..\source\blender\editors\mesh\editdeform.c"\r
-                               >\r
-                       </File>\r
 +                      <File\r
 +                              RelativePath="..\..\..\source\blender\editors\mesh\bmesh_select.c"\r
 +                              >\r
 +                      </File>\r
 +                      <File\r
 +                              RelativePath="..\..\..\source\blender\editors\mesh\bmesh_selecthistory.c"\r
 +                              >\r
 +                      </File>\r
 +                      <File\r
 +                              RelativePath="..\..\..\source\blender\editors\mesh\bmesh_tools.c"\r
 +                              >\r
 +                      </File>\r
 +                      <File\r
 +                              RelativePath="..\..\..\source\blender\editors\mesh\bmeshutils.c"\r
 +                              >\r
 +                      </File>\r
                        <File\r
                                RelativePath="..\..\..\source\blender\editors\mesh\editface.c"\r
                                >\r
Simple merge
index ef3a99f5fd826677b150be88b1f0c03bf2b25a1e,eb3aefe7ee63a53dddf7b2c0c36eb77247574b22..b6d1f7612b0382fda7de23859d10527cfba5d9d9
@@@ -184,12 -185,18 +185,18 @@@ static void FaceIt_Fill(CSG_IteratorPt
  {
        // assume CSG_IteratorPtr is of the correct type.
        FaceIt *face_it = (FaceIt *)it;
 -      MFace *mfaces = face_it->dm->getFaceArray(face_it->dm);
 +      MFace *mfaces = face_it->dm->getTessFaceArray(face_it->dm);
        MFace *mface = &mfaces[face_it->pos];
  
-       face->vertex_index[0] = mface->v1;
+       /* reverse face vertices if necessary */
        face->vertex_index[1] = mface->v2;
+       if( face_it->flip == 0 ) {
+       face->vertex_index[0] = mface->v1;
        face->vertex_index[2] = mface->v3;
+       } else {
+               face->vertex_index[2] = mface->v1;
+               face->vertex_index[0] = mface->v3;
+       }
        if (mface->v4) {
                face->vertex_index[3] = mface->v4;
                face->vertex_number = 4;
index 0af3196de927ea758a3dcbe2efaaa5a3361ef08d,3facf9759926f84be1c471cef1863d837c5369ae..8f67fdc74d2b3109eeeb3b13e0c31da94a8a717a
@@@ -81,8 -79,6 +81,9 @@@ EditMesh *BKE_mesh_get_editmesh(Mesh *m
  
  void BKE_mesh_end_editmesh(Mesh *me, EditMesh *em)
  {
++      BM_Free_Mesh(me->edit_btmesh->bm);
 +      me->edit_btmesh->bm = editmesh_to_bmesh(em);
 +      BMEdit_RecalcTesselation(me->edit_btmesh);
  }
  
  
@@@ -97,14 -93,6 +98,13 @@@ void mesh_update_customdata_pointers(Me
        me->mface = CustomData_get_layer(&me->fdata, CD_MFACE);
        me->mcol = CustomData_get_layer(&me->fdata, CD_MCOL);
        me->mtface = CustomData_get_layer(&me->fdata, CD_MTFACE);
++      
 +      me->mpoly = CustomData_get_layer(&me->pdata, CD_MPOLY);
 +      me->mloop = CustomData_get_layer(&me->ldata, CD_MLOOP);
 +
 +      me->mtpoly = CustomData_get_layer(&me->pdata, CD_MTEXPOLY);
 +      me->mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL);
 +      me->mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
  }
  
  /* Note: unlinking is called when me->id.us is 0, question remains how
index 4e1f6d8265a6d8e31f3d2158ae13555838774342,046dfcc9f87d847077556b6953396674be73197d..fc4788d9ff30227cba516e87f22abeddee2efe80
@@@ -3539,13 -3585,12 +3608,12 @@@ static void get_texture_coords(Displace
                        MFace *mf;
                        char *done = MEM_callocN(sizeof(*done) * numVerts,
                                        "get_texture_coords done");
 -                      int numFaces = dm->getNumFaces(dm);
 +                      int numFaces = dm->getNumTessFaces(dm);
+                       char uvname[32];
                        MTFace *tf;
  
-                       validate_layer_name(&dm->faceData, CD_MTFACE, dmd->uvlayer_name);
-                       tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE,
-                                       dmd->uvlayer_name);
+                       validate_layer_name(&dm->faceData, CD_MTFACE, dmd->uvlayer_name, uvname);
+                       tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
  
                        /* verts are given the UV from the first face that uses them */
                        for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) {
@@@ -3852,10 -3898,10 +3921,10 @@@ static DerivedMesh *uvprojectModifier_d
        if(num_projectors == 0) return dm;
  
        /* make sure there are UV layers available */
 -      if(!dm->getFaceDataArray(dm, CD_MTFACE)) return dm;
 +      if(!dm->getTessFaceDataArray(dm, CD_MTFACE)) return dm;
  
        /* make sure we're using an existing layer */
-       validate_layer_name(&dm->faceData, CD_MTFACE, umd->uvlayer_name);
+       validate_layer_name(&dm->faceData, CD_MTFACE, umd->uvlayer_name, uvname);
  
        /* make sure we are not modifying the original UV layer */
        tface = CustomData_duplicate_referenced_layer_named(&dm->faceData,
@@@ -5141,13 -5186,12 +5209,12 @@@ static void wavemod_get_texture_coords(
                        MFace *mf;
                        char *done = MEM_callocN(sizeof(*done) * numVerts,
                                        "get_texture_coords done");
 -                      int numFaces = dm->getNumFaces(dm);
 +                      int numFaces = dm->getNumTessFaces(dm);
+                       char uvname[32];
                        MTFace *tf;
  
-                       validate_layer_name(&dm->faceData, CD_MTFACE, wmd->uvlayer_name);
-                       tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE,
-                                       wmd->uvlayer_name);
+                       validate_layer_name(&dm->faceData, CD_MTFACE, wmd->uvlayer_name, uvname);
+                       tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
  
                        /* verts are given the UV from the first face that uses them */
                        for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) {
@@@ -6619,8 -6662,10 +6685,11 @@@ static DerivedMesh * particleInstanceMo
                end_latt_deform(psys->lattice);
                psys->lattice= NULL;
        }
 -
 +      
 +      CDDM_tessfaces_to_faces(result);
+       if(size)
+               MEM_freeN(size);
        return result;
  }
  static DerivedMesh *particleInstanceModifier_applyModifierEM(
@@@ -8009,10 -8055,10 +8080,10 @@@ static void shrinkwrapModifier_deformVe
                dm->release(dm);
  }
  
 -static void shrinkwrapModifier_deformVertsEM(ModifierData *md, Object *ob, EditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
 +static void shrinkwrapModifier_deformVertsEM(ModifierData *md, Object *ob, BMEditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
  {
        DerivedMesh *dm = NULL;
-       CustomDataMask dataMask = shrinkwrapModifier_requiredDataMask(md);
+       CustomDataMask dataMask = shrinkwrapModifier_requiredDataMask(ob, md);
  
        if(dataMask)
        {
@@@ -8124,10 -8170,10 +8195,10 @@@ static void simpledeformModifier_deform
  
  }
  
 -static void simpledeformModifier_deformVertsEM(ModifierData *md, Object *ob, EditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
 +static void simpledeformModifier_deformVertsEM(ModifierData *md, Object *ob, BMEditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
  {
        DerivedMesh *dm = NULL;
-       CustomDataMask dataMask = simpledeformModifier_requiredDataMask(md);
+       CustomDataMask dataMask = simpledeformModifier_requiredDataMask(ob, md);
  
        /* We implement requiredDataMask but thats not really usefull since mesh_calc_modifiers pass a NULL derivedData or without the modified vertexs applied */
        if(dataMask)
index c365f449801af1c4c08cd3a7b50b335c4de108c9,56ca3e8e22b21a87da86a929332c0aa38ae771bc..9004f4b9973c0c60d80eab0c3b3a2e0941cf85ad
@@@ -409,8 -409,8 +409,8 @@@ static void distribute_particles_in_gri
                int a, a1, a2, a0mul, a1mul, a2mul, totface;
                int amax= from==PART_FROM_FACE ? 3 : 1;
  
-               totface=dm->getNumTessFaces(dm);
+               totface=dm->getNumFaces(dm);
 -              mface=dm->getFaceDataArray(dm,CD_MFACE);
 +              mface=dm->getTessFaceDataArray(dm,CD_MFACE);
                
                for(a=0; a<amax; a++){
                        if(a==0){ a0mul=res*res; a1mul=res; a2mul=1; }
@@@ -1300,9 -1300,23 +1300,23 @@@ int psys_threads_init_distribution(Part
        /* for hair, sort by origindex, allows optimizations in rendering */
        /* however with virtual parents the children need to be in random order */
        if(part->type == PART_HAIR && !(part->childtype==PART_CHILD_FACES && part->parents!=0.0)) {
-               COMPARE_ORIG_INDEX= dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
-               if(COMPARE_ORIG_INDEX)
-                       qsort(index, totpart, sizeof(int), compare_orig_index);
+               if(from != PART_FROM_PARTICLE) {
+                       COMPARE_ORIG_INDEX = NULL;
+                       if(from == PART_FROM_VERT) {
+                               if(dm->numVertData)
+                                       COMPARE_ORIG_INDEX= dm->getVertDataArray(dm, CD_ORIGINDEX);
+                       }
+                       else {
+                               if(dm->numFaceData)
 -                                      COMPARE_ORIG_INDEX= dm->getFaceDataArray(dm, CD_ORIGINDEX);
++                                      COMPARE_ORIG_INDEX= dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+                       }
+                       if(COMPARE_ORIG_INDEX) {
+                               qsort(index, totpart, sizeof(int), compare_orig_index);
+                               COMPARE_ORIG_INDEX = NULL;
+                       }
+               }
        }
  
        /* weights are no longer used except for FROM_PARTICLE, which needs them zeroed for indexing */
@@@ -2922,8 -3030,8 +3030,8 @@@ int psys_intersect_dm(Scene *scene, Obj
                VECCOPY(p_max,pa_minmax+3);
        }
  
-       totface=dm->getNumTessFaces(dm);
+       totface=dm->getNumFaces(dm);
 -      mface=dm->getFaceDataArray(dm,CD_MFACE);
 +      mface=dm->getTessFaceDataArray(dm,CD_MFACE);
        mvert=dm->getVertDataArray(dm,CD_MVERT);
        
        /* lets intersect the faces */
Simple merge
index 06665d4b8ba6908c426b083109164f639492cc57,0000000000000000000000000000000000000000..443e04c87119eaa1dbce412c96b8f2a1eee49f5d
mode 100644,000000..100644
--- /dev/null
@@@ -1,352 -1,0 +1,355 @@@
 +/**
 + *  bmesh.h    jan 2007
 + *
 + *    BMesh API.
 + *
 + * $Id: BKE_bmesh.h,v 1.00 2007/01/17 17:42:01 Briggs Exp $
 + *
 + * ***** BEGIN GPL LICENSE BLOCK *****
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version. The Blender
 + * Foundation also sells licenses for use in proprietary software under
 + * the Blender License.  See http://www.blender.org/BL/ for information
 + * about this.        
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software Foundation,
 + * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 + *
 + * The Original Code is Copyright (C) 2004 Blender Foundation.
 + * All rights reserved.
 + *
 + * The Original Code is: all of this file.
 + *
 + * Contributor(s): Geoffrey Bantle, Levi Schooley.
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +
 +#ifndef BMESH_H
 +#define BMESH_H
 +
 +#include "DNA_listBase.h"
 +#include "DNA_customdata_types.h"
 +#include "DNA_scene_types.h"
 +#include "BLI_mempool.h"
 +#include "BKE_customdata.h"
 +
 +/*
 +short introduction:
 +
 +the bmesh structure is a boundary representation, supporting non-manifold 
 +locally modifiable topology. the API is designed to allow clean, maintainable
 +code, that never (or almost never) directly inspects the underlying structure.
 +
 +The API includes iterators, including many useful topological iterators;
 +walkers, which walk over a mesh, without the risk of hitting the recursion
 +limit; operators, which are logical, reusable mesh modules; topological
 +modification functions (like split face, join faces, etc), which are used for 
 +topological manipulations; and some (not yet finished) geometric utility 
 +functions.
 +
 +some definitions:
 +
 +tool flags: private flags for tools.  each operator has it's own private
 +            tool flag "layer", which it can use to flag elements.
 +          tool flags are also used by various other parts of the api.
 +header flags: stores persistent flags, such as selection state, hide state,
 +              etc.  be careful of touching these.
 +*/
 +
 +/*forward declarations*/
 +struct BMVert;
 +struct BMEdge;
 +struct BMFace;
 +struct BMLoop;
 +struct BMOperator;
 +struct Mesh;
 +struct EditMesh;
 +
 +/*
 + * BMHeader
 + *
 + * All mesh elements begin with a BMHeader. This structure 
 + * hold several types of data
 + *
 + * 1: The type of the element (vert, edge, loop or face)
 + * 2: Persistant flags/markings (sharp, seam, select, hidden, ect)
 + * 3: Unique ID in the bmesh.
 + * 4: some elements for internal record keeping.
 + *
 +*/
 +
 +/*BMHeader->type*/
 +#define BM_VERT       1
 +#define BM_EDGE       2
 +#define BM_FACE       4
 +#define BM_LOOP       8
 +#define BM_ALL                (BM_VERT | BM_EDGE | BM_FACE | BM_LOOP)
 +
 +/*BMHeader->flag*/
 +#define BM_SELECT     (1<<0)
 +
 +#define BM_SEAM               (1<<1)
 +#define BM_FGON               (1<<2)
 +#define BM_HIDDEN     (1<<3)
 +#define BM_SHARP      (1<<4)
 +#define BM_SMOOTH     (1<<5)
 +#define BM_ACTIVE     (1<<6)
 +#define BM_NONORMCALC (1<<7)
 +
 +typedef struct BMHeader {
 +      struct BMHeader *next, *prev;
 +      int             EID;  /*Consider removing this/making it ifdeffed for debugging*/
 +      
 +      /*don't confuse this with tool flags.  this flag
 +        member is what "header flag" means.*/
 +      int             flag;
 +      int             type;
 +      int             eflag1, eflag2; /*Flags used by eulers. Try and get rid of/minimize some of these*/
 +      
 +      //this can only be used to store a temporary index.  don't use it for anything else.
 +      //use the BMINDEX_GET and BMINDEX_SET macros!!
 +      int index;
 +      struct BMFlagLayer *flags; /*Dynamically allocated block of flag layers for operators to use*/
 +      void *data; /*customdata*/
 +} BMHeader;
 +
 +typedef struct BMFlagLayer {
 +      int f1;
 +      short mask, pflag;
 +} BMFlagLayer;
 +
 +#define BM_OVERLAP            (1<<14)                 /*used by bmesh_verts_in_face*/
 +#define BM_EDGEVERT   (1<<15)                 /*used by bmesh_make_ngon*/
 +
 +/*
 + * BMNode
 + *
 + * Used for circular/linked list functions that form basis of
 + * adjacency system in BMesh. This should probably be hidden 
 + * somewhere since tool authors never need to know about it.
 + *
 +*/
 +
 +typedef struct BMNode {
 +      struct BMNode *next, *prev;
 +      void *data;
 +} BMNode;
 +
 +typedef struct BMesh {
 +      ListBase verts, edges, polys;
 +      struct BLI_mempool *vpool;
 +      struct BLI_mempool *epool;
 +      struct BLI_mempool *lpool;
 +      struct BLI_mempool *ppool;
 +      struct BMVert **vtar;
 +      struct BMEdge **edar;
 +      struct BMLoop **lpar;
 +      struct BMFace **plar;
 +      int vtarlen, edarlen, lparlen, plarlen;
 +      int totvert, totedge, totface, totloop; 
 +      int totvertsel, totedgesel, totfacesel;
 +      int nextv, nexte, nextp, nextl;
 +      struct CustomData vdata, edata, pdata, ldata;
 +      int selectmode; /*now uses defines in DNA_scene_types.h*/
 +      struct BLI_mempool *flagpool;                                   /*memory pool for dynamically allocated flag layers*/
 +      int stackdepth;                                                                 /*current depth of operator stack*/
 +      int totflags, walkers;                                                  /*total number of tool flag layers*/
 +      ListBase errorstack;
 +
 +      /*active face pointer*/
 +      struct BMFace *act_face;
 +} BMesh;
 +
 +typedef struct BMVert {       
 +      struct BMHeader head;
 +      float co[3];                                                                    
 +      float no[3];                                                                    
 +      struct BMEdge *edge;
 +      void *tmp;                                                                                                      /*what?*/
 +      float bweight;                                                                                          /*please, someone just get rid of me...*/
 +} BMVert;
 +
 +typedef struct BMEdge {
 +      struct BMHeader head;
 +      struct BMVert *v1, *v2;
 +      struct BMNode d1, d2;
 +      struct BMLoop *loop;
 +      float crease, bweight; /*make these custom data.... no really, please....*/
 +} BMEdge;
 +
 +typedef struct BMLoop  {
 +      struct BMHeader head;
 +      struct BMNode radial;
 +      struct BMVert *v;
 +      struct BMEdge *e;
 +      struct BMFace *f;       
 +} BMLoop;
 +
 +typedef struct BMFace {
 +      struct BMHeader head;
 +      struct BMLoop *loopbase;
 +      int len;
 +      float no[3];
 +
 +      /*custom data again*/
 +      short mat_nr; 
 +} BMFace;
 +
 +/*stub */
 +void bmesh_error(void);
 +
 +/*Mesh Level Ops */
 +struct BMesh *BM_Make_Mesh(int allocsize[4]);
 +BMesh *BM_Copy_Mesh(BMesh *bmold);
 +void BM_Free_Mesh(struct BMesh *bm);
 +
 +/*frees mesh, but not actual BMesh struct*/
 +void BM_Free_Mesh_Data(BMesh *bm);
 +void BM_Compute_Normals(struct BMesh *bm);
 +
 +/*Construction*/
 +struct BMVert *BM_Make_Vert(struct BMesh *bm, float co[3], struct BMVert *example);
 +struct BMEdge *BM_Make_Edge(struct BMesh *bm, struct BMVert *v1, struct BMVert *v2, struct BMEdge *example, int nodouble);
 +struct BMFace *BM_Make_Quadtriangle(struct BMesh *bm, struct BMVert **verts, BMEdge **edges, int len, struct BMFace *example, int nodouble);
 +
 +/*more easier to use version of BM_Make_Quadtriangle.
 +  creates edges if necassary.*/
 +BMFace *BM_Make_QuadTri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, 
 +                      BMVert *v4, BMFace *example, int nodouble);
 +
 +/*makes an ngon from an unordered list of edges.  v1 and v2 must be the verts
 +defining edges[0], and define the winding of the new face.*/
 +struct BMFace *BM_Make_Ngon(struct BMesh *bm, struct BMVert *v1, struct BMVert *v2, struct BMEdge **edges, int len, int nodouble);
 +
 +/*stuff for dealing with header flags*/
 +#define BM_TestHFlag(ele, f) (((BMHeader*)ele)->flag & (f))
 +#define BM_SetHFlag(ele, f) (((BMHeader*)ele)->flag = ((BMHeader*)ele)->flag | (f))
 +#define BM_ClearHFlag(ele, f) (((BMHeader*)ele)->flag = ((BMHeader*)ele)->flag & ~(f))
 +
 +/*stuff for setting indices in elements.*/
 +#define BMINDEX_SET(ele, i) (((BMHeader*)ele)->index = i)
 +#define BMINDEX_GET(ele) ((BMHeader*)ele)->index
 +
 +/*copies loop data from adjacent faces*/
 +void BM_Face_CopyShared(BMesh *bm, BMFace *f);
 +
 +/*copies attributes, e.g. customdata, header flags, etc, from one element
 +  to another of the same type.*/
 +void BM_Copy_Attributes(struct BMesh *source_mesh, struct BMesh *target_mesh, void *source, void *target);
 +
 +/*remove tool flagged elements*/
 +void BM_remove_tagged_faces(struct BMesh *bm, int flag);
 +void BM_remove_tagged_edges(struct BMesh *bm, int flag);
 +void BM_remove_tagged_verts(struct BMesh *bm, int flag);
 +
 +
 +/*Modification*/
 +/*join two adjacent faces together along an edge.  note that
 +  the faces must only be joined by on edge.  e is the edge you
 +  wish to dissolve.*/
 +struct BMFace *BM_Join_Faces(struct BMesh *bm, struct BMFace *f1, 
 +                             struct BMFace *f2, struct BMEdge *e);
 +
 +/*split a face along two vertices.  returns the newly made face, and sets
 +  the nl member to a loop in the newly created edge.*/
 +struct BMFace *BM_Split_Face(struct BMesh *bm, struct BMFace *f,  
 +                             struct BMVert *v1, struct BMVert *v2, 
 +                           struct BMLoop **nl, struct BMEdge *example);
 +
 +/*dissolves a vert shared only by two edges*/
 +void BM_Collapse_Vert(struct BMesh *bm, struct BMEdge *ke, struct BMVert *kv, 
 +                    float fac);
 +
 +/*splits an edge.  ne is set to the new edge created.*/
 +struct BMVert *BM_Split_Edge(struct BMesh *bm, struct BMVert *v, 
 +                             struct BMEdge *e, struct BMEdge **ne,
 +                             float percent);
 +
 +/*split an edge multiple times evenly*/
 +struct BMVert  *BM_Split_Edge_Multi(struct BMesh *bm, struct BMEdge *e, 
 +                                  int numcuts);
 +
 +/*connect two verts together, through a face they share.  this function may
 +  be removed in the future.*/
 +BMEdge *BM_Connect_Verts(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **nf);
 +
 +
 +/*updates a face normal*/
 +void BM_Face_UpdateNormal(BMesh *bm, BMFace *f);
 +
 +/*updates face and vertex normals incident on an edge*/
 +void BM_Edge_UpdateNormals(BMesh *bm, BMEdge *e);
 +
 +/*update a vert normal (but not the faces incident on it)*/
 +void BM_Vert_UpdateNormal(BMesh *bm, BMVert *v);
 +
 +
 +/*dissolves all faces around a vert, and removes it.*/
 +int BM_Dissolve_Disk(BMesh *bm, BMVert *v);
 +
 +/*dissolves vert, in more situations then BM_Dissolve_Disk
 +  (e.g. if the vert is part of a wire edge, etc).*/
 +int BM_Dissolve_Vert(BMesh *bm, BMVert *v);
 +
 +
 +/*Interpolation*/
 +void BM_Data_Interp_From_Verts(struct BMesh *bm, struct BMVert *v1, struct BMVert *v2, struct BMVert *v, float fac);
 +void BM_Data_Facevert_Edgeinterp(struct BMesh *bm, struct BMVert *v1, struct BMVert *v2, struct BMVert *v, struct BMEdge *e1, float fac);
 +//void bmesh_data_interp_from_face(struct BMesh *bm, struct BMFace *source, struct BMFace *target);
++void BM_add_data_layer(BMesh *em, CustomData *data, int type);
++void BM_free_data_layer(BMesh *em, CustomData *data, int type);
++
 +
 +/*computes the centroid of a face, using the center of the bounding box*/
 +int BM_Compute_Face_Center(BMesh *bm, BMFace *f, float center[3]);
 +void BM_SelectMode_Flush(BMesh *bm);
 +
 +/*convert an editmesh to a bmesh*/
 +BMesh *editmesh_to_bmesh(struct EditMesh *em);
 +
 +/*initializes editmesh to bmesh operator, but doesn't execute.
 +  this is used in situations where you need to get access to the
 +  conversion operator's editmesh->bmesh mapping slot (e.g. if you
 +  need to find the bmesh edge that corrusponds to a specific editmesh
 +  edge).*/
 +BMesh *init_editmesh_to_bmesh(struct EditMesh *em, struct BMOperator *op);
 +
 +/*converts a bmesh to an editmesh*/
 +struct EditMesh *bmesh_to_editmesh(BMesh *bm);
 +
 +/*convert between bmesh and Mesh flags*/
 +int BMFlags_To_MEFlags(void *element);
 +
 +/*convert between Mesh and bmesh flags
 +  type must be BM_VERT/BM_EDGE/BM_FACE,
 +  and represents the type of the element
 +  parameter (the three defines map to
 +  MVert, MEdge, and MPoly, respectively).*/
 +int MEFlags_To_BMFlags(int flag, int type);
 +
 +/*convert MLoop*** in a bmface to mtface and mcol in
 +  an MFace*/
 +void BM_loops_to_corners(BMesh *bm, struct Mesh *me, int findex,
 +                         BMFace *f, int numTex, int numCol);
 +
 +/*include the rest of the API*/
 +#include "bmesh_filters.h"
 +#include "bmesh_iterators.h"
 +#include "bmesh_marking.h"
 +#include "bmesh_operator_api.h"
 +#include "bmesh_operators.h"
 +#include "bmesh_error.h"
 +#include "bmesh_queries.h"
 +#include "bmesh_walkers.h"
 +
 +#endif /* BMESH_H */
index e7d801b9beb8aee794bc50f17e1a0d57ceb97444,0000000000000000000000000000000000000000..3ef229f00c616a95ce5b7286af9f28c40b8b792b
mode 100644,000000..100644
--- /dev/null
@@@ -1,43 -1,0 +1,40 @@@
- void BM_esubdivideflag(struct Object *obedit, struct BMesh *bm, int selflag, float rad, 
-              int flag, int numcuts, int seltype);
- void BM_esubdivideflag_conv(struct Object *obedit, struct EditMesh *em, 
-                             int selflag, float rad, int flag, int numcuts, 
-                             int seltype);
 +#ifndef BM_OPERATORS_H
 +#define BM_OPERATORS_H
 +
 +/*--------defines/enumerations for specific operators-------*/
 +
 +/*del operator "context" slot values*/
 +enum {
 +      DEL_VERTS = 1,
 +      DEL_EDGES,
 +      DEL_ONLYFACES,
 +      DEL_EDGESFACES,
 +      DEL_FACES,
 +      DEL_ALL ,
 +      DEL_ONLYTAGGED,
 +};
 +
 +extern BMOpDefine *opdefines[];
 +extern int bmesh_total_ops;
 +
 +/*------specific operator helper functions-------*/
 +
 +/*executes the duplicate operation, feeding elements of 
 +  type flag etypeflag and header flag flag to it.  note,
 +  to get more useful information (such as the mapping from
 +  original to new elements) you should run the dupe op manually.*/
 +struct Object;
 +struct EditMesh;
 +
 +void BMOP_DupeFromFlag(struct BMesh *bm, int etypeflag, int flag);
++void BM_esubdivideflag(struct Object *obedit, BMesh *bm, int flag, float smooth, 
++                     float fractal, int beauty, int numcuts, int seltype);
 +void BM_extrudefaceflag(BMesh *bm, int flag);
 +
 +/*this next one return 1 if they did anything, or zero otherwise.
 +  they're kindof a hackish way to integrate with fkey, until
 +  such time as fkey is completely bmeshafied.*/
 +/*this doesn't display errors to the user, btw*/
 +int BM_ConnectVerts(struct EditMesh *em, int flag);
 +
 +#endif
index 6dc116dc7cdc0bc9869abc5352123e1ce796c85d,0000000000000000000000000000000000000000..ae0904a75dffaaedec1d6e989890f93ad9c3b7d5
mode 100644,000000..100644
--- /dev/null
@@@ -1,166 -1,0 +1,246 @@@
 +/**
 + * BME_interp.c    August 2008
 + *
 + *    BM interpolation functions.
 + *
 + * ***** BEGIN GPL LICENSE BLOCK *****
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + * about this.        
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software Foundation,
 + * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 + *
 + * The Original Code is Copyright (C) 2007 Blender Foundation.
 + * All rights reserved.
 + *
 + * The Original Code is: all of this file.
 + *
 + * Contributor(s): Geoffrey Bantle.
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +
 +#include "MEM_guardedalloc.h"
 +
 +#include "DNA_mesh_types.h"
 +#include "DNA_meshdata_types.h"
 +
 +#include "BKE_customdata.h" 
 +#include "BKE_utildefines.h"
 +
 +#include "bmesh.h"
 +#include "bmesh_private.h"
 +
 +/*
 + * BME_INTERP.C
 + *
 + * Functions for interpolating data across the surface of a mesh.
 + *
 +*/
 +
 +/**
 + *                    bmesh_data_interp_from_verts
 + *
 + *  Interpolates per-vertex data from two sources to a target.
 + * 
 + *  Returns -
 + *    Nothing
 + */
 +void BM_Data_Interp_From_Verts(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v, float fac)
 +{
 +      void *src[2];
 +      float w[2];
 +      if (v1->head.data && v2->head.data) {
 +              src[0]= v1->head.data;
 +              src[1]= v2->head.data;
 +              w[0] = 1.0f-fac;
 +              w[1] = fac;
 +              CustomData_bmesh_interp(&bm->vdata, src, w, NULL, 2, v->head.data);
 +      }
 +}
 +
 +/**
 + *                    bmesh_data_facevert_edgeinterp
 + *
 + *  Walks around the faces of an edge and interpolates the per-face-edge
 + *  data between two sources to a target.
 + * 
 + *  Returns -
 + *    Nothing
 +*/
 + 
 +void BM_Data_Facevert_Edgeinterp(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v, BMEdge *e1, float fac){
 +      void *src[2];
 +      float w[2];
 +      BMLoop *l=NULL, *v1loop = NULL, *vloop = NULL, *v2loop = NULL;
 +      
 +      w[1] = 1.0f - fac;
 +      w[0] = fac;
 +
 +      if(!e1->loop) return;
 +      l = e1->loop;
 +      do{
 +              if(l->v == v1){ 
 +                      v1loop = l;
 +                      vloop = (BMLoop*)(v1loop->head.next);
 +                      v2loop = (BMLoop*)(vloop->head.next);
 +              }else if(l->v == v){
 +                      v1loop = (BMLoop*)(l->head.next);
 +                      vloop = l;
 +                      v2loop = (BMLoop*)(l->head.prev);
 +                      
 +              }
 +
 +              src[0] = v1loop->head.data;
 +              src[1] = v2loop->head.data;                                     
 +
 +              CustomData_bmesh_interp(&bm->ldata, src,w, NULL, 2, vloop->head.data);                          
 +              l = l->radial.next->data;
 +      }while(l!=e1->loop);
 +}
 +
 +void BM_loops_to_corners(BMesh *bm, Mesh *me, int findex,
 +                         BMFace *f, int numTex, int numCol) 
 +{
 +      BMLoop *l;
 +      BMIter iter;
 +      MTFace *texface;
 +      MTexPoly *texpoly;
 +      MCol *mcol;
 +      MLoopCol *mloopcol;
 +      MLoopUV *mloopuv;
 +      int i, j;
 +
 +      for(i=0; i < numTex; i++){
 +              texface = CustomData_get_n(&me->fdata, CD_MTFACE, findex, i);
 +              texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i);
 +              
 +              texface->tpage = texpoly->tpage;
 +              texface->flag = texpoly->flag;
 +              texface->transp = texpoly->transp;
 +              texface->mode = texpoly->mode;
 +              texface->tile = texpoly->tile;
 +              texface->unwrap = texpoly->unwrap;
 +
 +              j = 0;
 +              BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
 +                      mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
 +                      texface->uv[j][0] = mloopuv->uv[0];
 +                      texface->uv[j][1] = mloopuv->uv[1];
 +
 +                      j++;
 +              }
 +
 +      }
 +
 +      for(i=0; i < numCol; i++){
 +              mcol = CustomData_get_n(&me->fdata, CD_MCOL, findex, i);
 +
 +              j = 0;
 +              BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
 +                      mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i);
 +                      mcol[j].r = mloopcol->r;
 +                      mcol[j].g = mloopcol->g;
 +                      mcol[j].b = mloopcol->b;
 +                      mcol[j].a = mloopcol->a;
 +
 +                      j++;
 +              }
 +      }
 +}
 +
 +//static void bmesh_data_interp_from_face(BME_Mesh *bm, BMFace *source, BMFace *target)
 +//{
 +//
 +//}
 +/*insert BM_data_interp_from_face here for mean value coordinates...*/
++
++
++static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
++{
++      BMIter iter;
++      void *block;
++
++      if (data == &bm->vdata) {
++              BMVert *eve;
++
++              BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
++                      block = NULL;
++                      CustomData_bmesh_set_default(data, &block);
++                      CustomData_bmesh_copy_data(olddata, data, eve->head.data, &block);
++                      CustomData_bmesh_free_block(olddata, &eve->head.data);
++                      eve->head.data= block;
++              }
++      }
++      else if (data == &bm->edata) {
++              BMEdge *eed;
++
++              BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
++                      block = NULL;
++                      CustomData_bmesh_set_default(data, &block);
++                      CustomData_bmesh_copy_data(olddata, data, eed->head.data, &block);
++                      CustomData_bmesh_free_block(olddata, &eed->head.data);
++                      eed->head.data= block;
++              }
++      }
++      else if (data == &bm->pdata || data == &bm->ldata) {
++              BMIter liter;
++              BMFace *efa;
++              BMLoop *l;
++
++              BM_ITER(efa, &iter, bm, BM_FACES_OF_MESH, NULL) {
++                      if (data == &bm->pdata) {
++                              block = NULL;
++                              CustomData_bmesh_set_default(data, &block);
++                              CustomData_bmesh_copy_data(olddata, data, efa->head.data, &block);
++                              CustomData_bmesh_free_block(olddata, &efa->head.data);
++                              efa->head.data= block;
++                      }
++
++                      if (data == &bm->ldata) {
++                              BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, efa) {
++                                      block = NULL;
++                                      CustomData_bmesh_set_default(data, &block);
++                                      CustomData_bmesh_copy_data(olddata, data, l->head.data, &block);
++                                      CustomData_bmesh_free_block(olddata, &l->head.data);
++                                      l->head.data= block;
++                              }
++                      }
++              }
++      }
++}
++
++
++void BM_add_data_layer(BMesh *bm, CustomData *data, int type)
++{
++      CustomData olddata;
++
++      olddata= *data;
++      olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL;
++      CustomData_add_layer(data, type, CD_CALLOC, NULL, 0);
++
++      update_data_blocks(bm, &olddata, data);
++      if (olddata.layers) MEM_freeN(olddata.layers);
++}
++
++void BM_free_data_layer(BMesh *bm, CustomData *data, int type)
++{
++      CustomData olddata;
++
++      olddata= *data;
++      olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL;
++      CustomData_free_layer_active(data, type, 0);
++
++      update_data_blocks(bm, &olddata, data);
++      if (olddata.layers) MEM_freeN(olddata.layers);
++}
index 8c89697f5f2d9fdabad94bc0017289b2afc16a1d,0000000000000000000000000000000000000000..07f1144b37e92c9edf9a2ce93d48070bd5ae8770
mode 100644,000000..100644
--- /dev/null
@@@ -1,323 -1,0 +1,324 @@@
-       {BMOP_OPSLOT_INT, "flag"},
-       {BMOP_OPSLOT_FLT, "radius"},
 +#include "bmesh.h"
 +#include "bmesh_private.h"
 +
 +#include <stdio.h>
 +
 +/*do not rename any operator or slot names! otherwise you must go 
 +  through the code and find all references to them!*/
 +
 +BMOpDefine def_finddoubles = {
 +      "finddoubles",
 +      /*maps welded vertices to verts they should weld to.*/
 +      {{BMOP_OPSLOT_ELEMENT_BUF, "verts"},
 +       //list of verts to keep
 +       {BMOP_OPSLOT_ELEMENT_BUF, "keepverts"},
 +       {BMOP_OPSLOT_FLT,         "dist"},
 +       {BMOP_OPSLOT_MAPPING, "targetmapout"},
 +       {0, /*null-terminating sentinel*/}},
 +      bmesh_finddoubles_exec,
 +      0,
 +};
 +
 +BMOpDefine def_removedoubles = {
 +      "removedoubles",
 +      /*maps welded vertices to verts they should weld to.*/
 +      {{BMOP_OPSLOT_ELEMENT_BUF, "verts"},
 +       {BMOP_OPSLOT_FLT,         "dist"},
 +       {0, /*null-terminating sentinel*/}},
 +      bmesh_removedoubles_exec,
 +      0,
 +};
 +
 +BMOpDefine def_weldverts = {
 +      "weldverts",
 +      /*maps welded vertices to verts they should weld to.*/
 +      {{BMOP_OPSLOT_MAPPING, "targetmap"},
 +       {0, /*null-terminating sentinel*/}},
 +      bmesh_weldverts_exec,
 +      0,
 +};
 +
 +BMOpDefine def_makevert = {
 +      "makevert",
 +      {{BMOP_OPSLOT_VEC, "co"},
 +      {BMOP_OPSLOT_ELEMENT_BUF, "newvertout"},
 +      {0, /*null-terminating sentinel*/}},
 +      bmesh_makevert_exec,
 +      0,
 +};
 +
 +/*contextual_create is fkey, it creates
 +  new faces, makes stuff from edge nets,
 +  makes wire edges, etc.  it also dissolves
 +  faces.*/
 +BMOpDefine def_contextual_create= {
 +      "contextual_create",
 +      {{BMOP_OPSLOT_ELEMENT_BUF, "geom"},
 +       {BMOP_OPSLOT_ELEMENT_BUF, "faceout"},
 +       {0, /*null-terminating sentinel*/}},
 +      bmesh_contextual_create_exec,
 +      0,
 +};
 +
 +BMOpDefine def_edgenet_fill= {
 +      "edgenet_fill",
 +      {{BMOP_OPSLOT_ELEMENT_BUF, "edges"},
 +       {BMOP_OPSLOT_ELEMENT_BUF, "faceout"},
 +      {0, /*null-terminating sentinel*/}},
 +      bmesh_edgenet_fill_exec,
 +      0,
 +};
 +
 +BMOpDefine def_rotate = {
 +      "rotate",
 +      {{BMOP_OPSLOT_VEC, "cent"},
 +       {BMOP_OPSLOT_MAT, "mat"},
 +      {BMOP_OPSLOT_ELEMENT_BUF, "verts"},
 +      {0, /*null-terminating sentinel*/}},
 +      bmesh_rotate_exec,
 +      0,
 +};
 +
 +BMOpDefine def_translate= {
 +      "translate",
 +      {{BMOP_OPSLOT_VEC, "vec"},
 +      {BMOP_OPSLOT_ELEMENT_BUF, "verts"},
 +      {0, /*null-terminating sentinel*/}},
 +      bmesh_translate_exec,
 +      0,
 +};
 +
 +
 +/*applies a transform to vertices*/
 +BMOpDefine def_transform = {
 +      "transform",
 +      {{BMOP_OPSLOT_MAT, "mat"},
 +      {BMOP_OPSLOT_ELEMENT_BUF, "verts"},
 +      {0, /*null-terminating sentinel*/}},
 +      bmesh_transform_exec,
 +      0,
 +};
 +
 +/*loads a bmesh into an object*/
 +BMOpDefine def_object_load_bmesh = {
 +      "object_load_bmesh",
 +      {{BMOP_OPSLOT_PNT, "scene"},
 +      {BMOP_OPSLOT_PNT, "object"},
 +      {0, /*null-terminating sentinel*/}},
 +      bmesh_to_mesh_exec,
 +      0,
 +};
 +
 +
 +BMOpDefine def_mesh_to_bmesh = {
 +      "mesh_to_bmesh",
 +      {{BMOP_OPSLOT_PNT, "mesh"},
 +       {0, /*null-terminating sentinel*/}},
 +      mesh_to_bmesh_exec,
 +      0
 +};
 +
 +BMOpDefine def_extrudeverts_indiv = {
 +      "extrude_vert_indiv",
 +      {{BMOP_OPSLOT_ELEMENT_BUF, "verts"},
 +      {BMOP_OPSLOT_ELEMENT_BUF, "edgeout"},
 +      {BMOP_OPSLOT_ELEMENT_BUF, "vertout"},
 +      {0} /*null-terminating sentinel*/},
 +      extrude_vert_indiv_exec,
 +      0
 +};
 +
 +#if 0
 +BMOpDefine def_makeprim = {
 +      "makeprim",
 +      {{BMOP_OPSLOT_INT, "type"},
 +      {BMOP_OPSLOT_INT, "tot", /*rows/cols also applies to spheres*/
 +      {BMOP_OPSLOT_INT, "seg",
 +      {BMOP_OPSLOT_INT, "subdiv"},
 +      {BMOP_OPSLOT_INT, "ext"},
 +      {BMOP_OPSLOT_INT, "fill"},
 +      {BMOP_OPSLOT_FLT, "dia"},
 +      {BMOP_OPSLOT_FLT, "depth"},
 +      {BMOP_OPSLOT_PNT, "mat"},
 +      {BMOP_OPSLOT_ELEMENT_BUF, "geomout"}, //won't be implemented right away
 +      {0}}
 +      makeprim_exec,
 +      0
 +};
 +#endif
 +
 +BMOpDefine def_connectverts = {
 +      "connectverts",
 +      {{BMOP_OPSLOT_ELEMENT_BUF, "verts"},
 +      {BMOP_OPSLOT_ELEMENT_BUF, "edgeout"},
 +      {0} /*null-terminating sentinel*/},
 +      connectverts_exec,
 +      0
 +};
 +
 +BMOpDefine def_extrudefaceregion = {
 +      "extrudefaceregion",
 +      {{BMOP_OPSLOT_ELEMENT_BUF, "edgefacein"},
 +      {BMOP_OPSLOT_MAPPING, "exclude"},
 +      {BMOP_OPSLOT_ELEMENT_BUF, "geomout"},
 +      {0} /*null-terminating sentinel*/},
 +      extrude_edge_context_exec,
 +      0
 +};
 +
 +BMOpDefine def_makefgonsop = {
 +      "makefgon",
 +      {{BMOP_OPSLOT_INT, "trifan"}, /*use triangle fans instead of 
 +                                      real interpolation*/
 +       {0} /*null-terminating sentinel*/},
 +      bmesh_make_fgons_exec,
 +      0
 +};
 +
 +BMOpDefine def_dissolvevertsop = {
 +      "dissolveverts",
 +      {{BMOP_OPSLOT_ELEMENT_BUF, "verts"},
 +      {0} /*null-terminating sentinel*/},
 +      dissolveverts_exec,
 +      0
 +};
 +
 +BMOpDefine def_dissolveedgessop = {
 +      "dissolveedges",
 +      {{BMOP_OPSLOT_ELEMENT_BUF, "edges"},
 +      {BMOP_OPSLOT_ELEMENT_BUF, "regionout"},
 +      {0} /*null-terminating sentinel*/},
 +      dissolveedges_exec,
 +      0
 +};
 +
 +BMOpDefine def_dissolveedgeloopsop = {
 +      "dissolveedgeloop",
 +      {{BMOP_OPSLOT_ELEMENT_BUF, "edges"},
 +      {BMOP_OPSLOT_ELEMENT_BUF, "regionout"},
 +      {0} /*null-terminating sentinel*/},
 +      dissolve_edgeloop_exec,
 +      0
 +};
 +
 +BMOpDefine def_dissolvefacesop = {
 +      "dissolvefaces",
 +      {{BMOP_OPSLOT_ELEMENT_BUF, "faces"},
 +      {BMOP_OPSLOT_ELEMENT_BUF, "regionout"},
 +      {0} /*null-terminating sentinel*/},
 +      dissolvefaces_exec,
 +      0
 +};
 +
 +
 +BMOpDefine def_triangop = {
 +      "triangulate",
 +      {{BMOP_OPSLOT_ELEMENT_BUF, "faces"},
 +      {BMOP_OPSLOT_ELEMENT_BUF, "edgeout"},
 +      {BMOP_OPSLOT_ELEMENT_BUF, "faceout"},
 +      {BMOP_OPSLOT_MAPPING, "facemap"},
 +      {0} /*null-terminating sentinel*/},
 +      triangulate_exec,
 +      0
 +};
 +
 +BMOpDefine def_subdop = {
 +      "esubd",
 +      {{BMOP_OPSLOT_ELEMENT_BUF, "edges"},
 +      {BMOP_OPSLOT_INT, "numcuts"},
++      {BMOP_OPSLOT_FLT, "smooth"},
++      {BMOP_OPSLOT_FLT, "fractal"},
++      {BMOP_OPSLOT_INT, "beauty"},
 +      {BMOP_OPSLOT_MAPPING, "custompatterns"},
 +      {BMOP_OPSLOT_MAPPING, "edgepercents"},
 +      
 +      /*these next two can have multiple types of elements in them.*/
 +      {BMOP_OPSLOT_ELEMENT_BUF, "outinner"},
 +      {BMOP_OPSLOT_ELEMENT_BUF, "outsplit"},
 +      {0} /*null-terminating sentinel*/,
 +      },
 +      esubdivide_exec,
 +      0
 +};
 +
 +BMOpDefine def_edit2bmesh = {
 +      "editmesh_to_bmesh",
 +      {{BMOP_OPSLOT_PNT, "em"}, {BMOP_OPSLOT_MAPPING, "map"},
 +      {0} /*null-terminating sentinel*/},
 +      edit2bmesh_exec,
 +      0
 +};
 +
 +BMOpDefine def_bmesh2edit = {
 +      "bmesh_to_editmesh",
 +      {{BMOP_OPSLOT_PNT, "emout"},
 +      {0} /*null-terminating sentinel*/},
 +      bmesh2edit_exec,
 +      0
 +};
 +
 +BMOpDefine def_delop = {
 +      "del",
 +      {{BMOP_OPSLOT_ELEMENT_BUF, "geom"}, {BMOP_OPSLOT_INT, "context"},
 +      {0} /*null-terminating sentinel*/},
 +      delop_exec,
 +      0
 +};
 +
 +BMOpDefine def_dupeop = {
 +      "dupe",
 +      {{BMOP_OPSLOT_ELEMENT_BUF, "geom"},
 +      {BMOP_OPSLOT_ELEMENT_BUF, "origout"},
 +      {BMOP_OPSLOT_ELEMENT_BUF, "newout"},
 +      /*facemap maps from source faces to dupe
 +        faces, and from dupe faces to source faces.*/
 +      {BMOP_OPSLOT_MAPPING, "facemap"},
 +      {BMOP_OPSLOT_MAPPING, "boundarymap"},
 +      {BMOP_OPSLOT_MAPPING, "isovertmap"},
 +      {0} /*null-terminating sentinel*/},
 +      dupeop_exec,
 +      0
 +};
 +
 +BMOpDefine def_splitop = {
 +      "split",
 +      {{BMOP_OPSLOT_ELEMENT_BUF, "geom"},
 +      {BMOP_OPSLOT_ELEMENT_BUF, "geomout"},
 +      {BMOP_OPSLOT_MAPPING, "boundarymap"},
 +      {BMOP_OPSLOT_MAPPING, "isovertmap"},
 +      {0} /*null-terminating sentinel*/},
 +      splitop_exec,
 +      0
 +};
 +
 +BMOpDefine *opdefines[] = {
 +      &def_splitop,
 +      &def_dupeop,
 +      &def_delop,
 +      &def_edit2bmesh,
 +      &def_bmesh2edit,
 +      &def_subdop,
 +      &def_triangop,
 +      &def_dissolvefacesop,
 +      &def_dissolveedgessop,
 +      &def_dissolveedgeloopsop,
 +      &def_dissolvevertsop,
 +      &def_makefgonsop,
 +      &def_extrudefaceregion,
 +      &def_connectverts,
 +      //&def_makeprim,
 +      &def_extrudeverts_indiv,
 +      &def_mesh_to_bmesh,
 +      &def_object_load_bmesh,
 +      &def_transform,
 +      &def_translate,
 +      &def_rotate,
 +      &def_edgenet_fill,
 +      &def_contextual_create,
 +      &def_makevert,
 +      &def_weldverts,
 +      &def_removedoubles,
 +      &def_finddoubles,
 +};
 +
 +int bmesh_total_ops = (sizeof(opdefines) / sizeof(void*));
index 549146af1b7226b1ccae961544b832cadd027cc8,0000000000000000000000000000000000000000..8482fecb7bbb959ff07a28f27ffe3471280bbd85
mode 100644,000000..100644
--- /dev/null
@@@ -1,818 -1,0 +1,825 @@@
-       
-       if(params->flag & B_SMOOTH) {
 +#include "MEM_guardedalloc.h"
 +
 +#include "BKE_utildefines.h"
 +
 +#include "BLI_arithb.h"
 +#include "BLI_rand.h"
 +#include "BLI_ghash.h"
 +
 +#include "DNA_object_types.h"
 +
 +#include "ED_mesh.h"
 +
 +#include "bmesh.h"
 +#include "mesh_intern.h"
 +#include "subdivideop.h"
 +
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <string.h>
 +#include <math.h>
 +
 +/*flags for all elements share a common bitfield space*/
 +#define SUBD_SPLIT    1
 +
 +#define EDGE_PERCENT  2
 +
 +/*I don't think new faces are flagged, currently, but
 +  better safe than sorry.*/
 +#define FACE_NEW      4
 +#define FACE_CUSTOMFILL       8
 +#define ELE_INNER     16
 +#define ELE_SPLIT     32
 +#define ELE_CONNECT   64
 +
 +/*stuff for the flag paramter.  note that
 +  what used to live in "beauty" and
 +  in "seltype" live here.  still have to
 +  convert the beauty flags over, which
 +  is why it starts at 128 (to avoid
 +  collision).*/
 +#define SELTYPE_INNER 128
 +
 +/*
 +NOTE: beauty has been renamed to flag!
 +*/
 +
 +/*generic subdivision rules:
 +  
 +  * two selected edges in a face should make a link
 +    between them.
 +
 +  * one edge should do, what? make pretty topology, or just
 +    split the edge only?
 +*/
 +
 +/*connects face with smallest len, which I think should always be correct for
 +  edge subdivision*/
 +BMEdge *connect_smallest_face(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **nf) {
 +      BMIter iter, iter2;
 +      BMVert *v;
 +      BMLoop *nl;
 +      BMFace *face, *curf = NULL;
 +
 +      /*this isn't the best thing in the world.  it doesn't handle cases where there's
 +        multiple faces yet.  that might require a convexity test to figure out which
 +        face is "best," and who knows what for non-manifold conditions.*/
 +      for (face = BMIter_New(&iter, bm, BM_FACES_OF_VERT, v1); face; face=BMIter_Step(&iter)) {
 +              for (v=BMIter_New(&iter2, bm, BM_VERTS_OF_FACE, face); v; v=BMIter_Step(&iter2)) {
 +                      if (v == v2) {
 +                              if (!curf || face->len < curf->len) curf = face;
 +                      }
 +              }
 +      }
 +
 +      if (curf) {
 +              face = BM_Split_Face(bm, curf, v1, v2, &nl, NULL);
 +              
 +              if (nf) *nf = face;
 +              return nl ? nl->e : NULL;
 +      }
 +
 +      return NULL;
 +}
 +/* calculates offset for co, based on fractal, sphere or smooth settings  */
 +static void alter_co(float *co, BMEdge *edge, subdparams *params, float perc,
 +                   BMVert *vsta, BMVert *vend)
 +{
 +      float vec1[3], fac;
-               float len, fac, nor[3], nor1[3], nor2[3];
-               
++
++      if(params->beauty & B_SMOOTH) {
 +              /* we calculate an offset vector vec1[], to be added to *co */
-       
++              float len, fac, nor[3], nor1[3], nor2[3], smooth=params->smooth;
++
 +              VecSubf(nor, vsta->co, vend->co);
 +              len= 0.5f*Normalize(nor);
-       
++
 +              VECCOPY(nor1, vsta->no);
 +              VECCOPY(nor2, vend->no);
-               
++
 +              /* cosine angle */
 +              fac= nor[0]*nor1[0] + nor[1]*nor1[1] + nor[2]*nor1[2] ;
-       
++
 +              vec1[0]= fac*nor1[0];
 +              vec1[1]= fac*nor1[1];
 +              vec1[2]= fac*nor1[2];
-               
++
 +              /* cosine angle */
 +              fac= -nor[0]*nor2[0] - nor[1]*nor2[1] - nor[2]*nor2[2] ;
-               
-               vec1[0]*= params->rad*len;
-               vec1[1]*= params->rad*len;
-               vec1[2]*= params->rad*len;
-               
++
 +              vec1[0]+= fac*nor2[0];
 +              vec1[1]+= fac*nor2[1];
 +              vec1[2]+= fac*nor2[2];
-       else {
-               if(params->rad > 0.0) {   /* subdivide sphere */
-                       Normalize(co);
-                       co[0]*= params->rad;
-                       co[1]*= params->rad;
-                       co[2]*= params->rad;
-               }
-               else if(params->rad< 0.0) {  /* fractal subdivide */
-                       fac= params->rad* VecLenf(vsta->co, vend->co);
-                       vec1[0]= fac*(float)(0.5-BLI_drand());
-                       vec1[1]= fac*(float)(0.5-BLI_drand());
-                       vec1[2]= fac*(float)(0.5-BLI_drand());
-                       VecAddf(co, co, vec1);
-               }
++
++              /* falloff for multi subdivide */
++              smooth *= sqrt(fabs(1.0f - 2.0f*fabs(perc)));
++
++              vec1[0]*= smooth*len;
++              vec1[1]*= smooth*len;
++              vec1[2]*= smooth*len;
++
 +              co[0] += vec1[0];
 +              co[1] += vec1[1];
 +              co[2] += vec1[2];
 +      }
-       float rad;
-       int i, j, matched, a, b, numcuts, flag;
++      else if(params->beauty & B_SPHERE) { /* subdivide sphere */
++              Normalize(co);
++              co[0]*= params->smooth;
++              co[1]*= params->smooth;
++              co[2]*= params->smooth;
++      }
 +
++      if(params->beauty & B_FRACTAL) {
++              fac= params->fractal*VecLenf(vsta->co, vend->co);
++              vec1[0]= fac*(float)(0.5-BLI_drand());
++              vec1[1]= fac*(float)(0.5-BLI_drand());
++              vec1[2]= fac*(float)(0.5-BLI_drand());
++              VecAddf(co, co, vec1);
 +      }
 +}
 +
 +/* assumes in the edge is the correct interpolated vertices already */
 +/* percent defines the interpolation, rad and flag are for special options */
 +/* results in new vertex with correct coordinate, vertex normal and weight group info */
 +static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge,BMEdge *oedge,
 +                                      subdparams *params, float percent,
 +                                      float percent2,
 +                                      BMEdge **out,BMVert *vsta,BMVert *vend)
 +{
 +      BMVert *ev;
 +//    float co[3];
 +      
 +      ev = BM_Split_Edge(bm, edge->v1, edge, out, percent);
 +      BM_Vert_UpdateNormal(bm, ev);
 +
 +      BMO_SetFlag(bm, ev, ELE_INNER);
 +
 +      /* offset for smooth or sphere or fractal */
 +      alter_co(ev->co, oedge, params, percent2, vsta, vend);
 +
 +#if 0 //TODO
 +      /* clip if needed by mirror modifier */
 +      if (edge->v1->f2) {
 +              if ( edge->v1->f2 & edge->v2->f2 & 1) {
 +                      co[0]= 0.0f;
 +              }
 +              if ( edge->v1->f2 & edge->v2->f2 & 2) {
 +                      co[1]= 0.0f;
 +              }
 +              if ( edge->v1->f2 & edge->v2->f2 & 4) {
 +                      co[2]= 0.0f;
 +              }
 +      }
 +#endif        
 +      
 +      return ev;
 +}
 +
 +static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge, BMEdge *oedge,
 +                              int curpoint, int totpoint, subdparams *params,
 +                              BMEdge **newe, BMVert *vsta, BMVert *vend)
 +{
 +      BMVert *ev;
 +      float percent, percent2 = 0.0f;
 +       
 +      if (BMO_TestFlag(bm, edge, EDGE_PERCENT) && totpoint == 1)
 +              percent = BMO_Get_MapFloat(bm, params->op, 
 +                                      "edgepercents", edge);
 +      else {
 +              percent= 1.0f/(float)(totpoint+1-curpoint);
 +              percent2 = (float)curpoint / (float)(totpoint + 1);
 +
 +      }
 +      
 +      ev= bm_subdivide_edge_addvert(bm, edge, oedge, params, percent,
 +                                    percent2, newe, vsta, vend);
 +      return ev;
 +}
 +
 +static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, subdparams *params, 
 +                                BMVert *vsta, BMVert *vend) {
 +      BMEdge *eed = edge, *newe, temp = *edge;
 +      BMVert *v;
 +      int i, numcuts = params->numcuts;
 +
 +      for(i=0;i<numcuts;i++) {
 +              v = subdivideedgenum(bm, eed, &temp, i, params->numcuts, params, 
 +                                   &newe, vsta, vend);
 +              BMO_SetFlag(bm, v, SUBD_SPLIT);
 +              BMO_SetFlag(bm, eed, SUBD_SPLIT);
 +
 +              BMO_SetFlag(bm, v, ELE_SPLIT);
 +              BMO_SetFlag(bm, eed, ELE_SPLIT);
 +      }
 +}
 +
 +/*note: the patterns are rotated as necassary to
 +  match the input geometry.  they're based on the
 +  pre-split state of the  face*/
 +
 +/*
 +     
 +v3---------v2
 +|          |
 +|          |
 +|          |
 +|          |
 +v4---v0---v1
 +
 +*/
 +static void q_1edge_split(BMesh *bm, BMFace *face,
 +                        BMVert **verts, subdparams *params) {
 +      BMFace *nf;
 +      int i, add, numcuts = params->numcuts;
 +
 +      /*if it's odd, the middle face is a quad, otherwise it's a triangle*/
 +      if (numcuts % 2==0) {
 +              add = 2;
 +              for (i=0; i<numcuts; i++) {
 +                      if (i == numcuts/2) add -= 1;
 +                      connect_smallest_face(bm, verts[i], verts[numcuts+add], 
 +                                         &nf);
 +              }
 +      } else {
 +              add = 2;
 +              for (i=0; i<numcuts; i++) {
 +                      connect_smallest_face(bm, verts[i], verts[numcuts+add], 
 +                                         &nf);
 +                      if (i == numcuts/2) {
 +                              add -= 1;
 +                              connect_smallest_face(bm, verts[i], 
 +                                                 verts[numcuts+add],
 +                                                 &nf);
 +                      }
 +              }
 +
 +      }
 +}
 +
 +subdpattern q_1edge = {
 +      {1, 0, 0, 0},
 +      q_1edge_split,
 +      4,
 +};
 +
 +
 +/*
 + 
 +v4---v3---v2
 +|     s    |
 +|          |
 +|          |
 +|     s    |
 +v5---v0---v1
 +
 +*/
 +
 +static void q_2edge_op_split(BMesh *bm, BMFace *face, BMVert **verts, 
 +                             subdparams *params)
 +{
 +      BMFace *nf;
 +      int i, numcuts = params->numcuts;
 +      
 +      for (i=0; i<numcuts; i++) {
 +              connect_smallest_face(bm, verts[i],verts[(numcuts-i-1)+numcuts+2],
 +                                 &nf);
 +      }
 +}
 +
 +subdpattern q_2edge_op = {
 +      {1, 0, 1, 0},
 +      q_2edge_op_split,
 +      4,
 +};
 +
 +/*
 +v6--------v5
 +|          |
 +|          |v4s
 +|          |v3s
 +|   s  s   |
 +v7-v0--v1-v2
 +
 +*/
 +static void q_2edge_split(BMesh *bm, BMFace *face, BMVert **verts, 
 +                          subdparams *params)
 +{
 +      BMFace *nf;
 +      int i, numcuts = params->numcuts;
 +      
 +      for (i=0; i<numcuts; i++) {
 +              connect_smallest_face(bm, verts[i], verts[numcuts+(numcuts-i)],
 +                                 &nf);
 +      }
 +      connect_smallest_face(bm, verts[numcuts*2+3], verts[numcuts*2+1], &nf);
 +}
 +
 +subdpattern q_2edge = {
 +      {1, 1, 0, 0},
 +      q_2edge_split,
 +      4,
 +};
 +
 +/*  s   s
 +v8--v7--v6-v5
 +|          |
 +|          v4 s
 +|          |
 +|          v3 s
 +|   s  s   |
 +v9-v0--v1-v2
 +
 +*/
 +static void q_3edge_split(BMesh *bm, BMFace *face, BMVert **verts, 
 +                          subdparams *params)
 +{
 +      BMFace *nf;
 +      int i, add=0, numcuts = params->numcuts;
 +      
 +      for (i=0; i<numcuts; i++) {
 +              if (i == numcuts/2) {
 +                      if (numcuts % 2 != 0) {
 +                              connect_smallest_face(bm, verts[numcuts-i-1+add], 
 +                                               verts[i+numcuts+1], &nf);
 +                      }
 +                      add = numcuts*2+2;
 +              }
 +              connect_smallest_face(bm, verts[numcuts-i-1+add], 
 +                                   verts[i+numcuts+1], &nf);
 +      }
 +
 +      for (i=0; i<numcuts/2+1; i++) {
 +              connect_smallest_face(bm, verts[i],verts[(numcuts-i)+numcuts*2+1],
 +                                 &nf);
 +      }
 +}
 +
 +subdpattern q_3edge = {
 +      {1, 1, 1, 0},
 +      q_3edge_split,
 +      4,
 +};
 +
 +/*
 + 
 +           v8--v7-v6--v5
 +           |     s    |
 +           |v9 s     s|v4
 +first line |          |   last line
 +           |v10s s   s|v3
 +           v11-v0--v1-v2
 +
 +         it goes from bottom up
 +*/
 +static void q_4edge_split(BMesh *bm, BMFace *face, BMVert **verts, 
 +                          subdparams *params)
 +{
 +      BMFace *nf;
 +      BMVert *v, *v1, *v2;
 +      BMEdge *e, *ne, temp;
 +      BMVert **lines;
 +      int numcuts = params->numcuts;
 +      int i, j, a, b, s=numcuts+2, totv=numcuts*4+4;
 +
 +      lines = MEM_callocN(sizeof(BMVert*)*(numcuts+2)*(numcuts+2),
 +                                   "q_4edge_split");
 +      /*build a 2-dimensional array of verts,
 +        containing every vert (and all new ones)
 +        in the face.*/
 +
 +      /*first line*/
 +      for (i=0; i<numcuts+2; i++) {
 +              lines[i] = verts[numcuts*3+2+(numcuts-i+1)];
 +      }
 +
 +      /*last line*/
 +      for (i=0; i<numcuts+2; i++) {
 +              lines[(s-1)*s+i] = verts[numcuts+i];
 +      }
 +      
 +      /*first and last members of middle lines*/
 +      for (i=0; i<numcuts; i++) {
 +              a = i;
 +              b = numcuts + 1 + numcuts + 1 + (numcuts - i - 1);
 +              
 +              e = connect_smallest_face(bm, verts[a], verts[b], &nf);
 +              if (!e) continue;
 +
 +              BMO_SetFlag(bm, e, ELE_INNER);
 +              BMO_SetFlag(bm, nf, ELE_INNER);
 +
 +              
 +              v1 = lines[(i+1)*s] = verts[a];
 +              v2 = lines[(i+1)*s + s-1] = verts[b];
 +              
 +              temp = *e;
 +              for (a=0; a<numcuts; a++) {
 +                      v = subdivideedgenum(bm, e, &temp, a, numcuts, params, &ne,
 +                                           v1, v2);
 +                      BMO_SetFlag(bm, ne, ELE_INNER);
 +                      lines[(i+1)*s+a+1] = v;
 +              }
 +      }
 +
 +      for (i=1; i<numcuts+2; i++) {
 +              for (j=1; j<numcuts+1; j++) {
 +                      a = i*s + j;
 +                      b = (i-1)*s + j;
 +                      e = connect_smallest_face(bm, lines[a], lines[b], &nf);
 +                      if (!e) continue;
 +
 +                      BMO_SetFlag(bm, e, ELE_INNER);
 +                      BMO_SetFlag(bm, nf, ELE_INNER);
 +              }
 +      }
 +
 +      MEM_freeN(lines);
 +}
 +
 +/*    v3
 +     / \
 +    /   \
 +   /     \
 +  /       \
 + /         \
 +v4--v0--v1--v2
 +    s    s
 +*/
 +static void t_1edge_split(BMesh *bm, BMFace *face, BMVert **verts, 
 +                          subdparams *params)
 +{
 +      BMFace *nf;
 +      int i, numcuts = params->numcuts;
 +      
 +      for (i=0; i<numcuts; i++) {
 +              connect_smallest_face(bm, verts[i], verts[numcuts+1], &nf);
 +      }
 +}
 +
 +subdpattern t_1edge = {
 +      {1, 0, 0},
 +      t_1edge_split,
 +      3,
 +};
 +
 +/*    v5
 +     / \
 +    /   \ v4 s
 +   /     \
 +  /       \ v3 s
 + /         \
 +v6--v0--v1--v2
 +    s   s
 +*/
 +static void t_2edge_split(BMesh *bm, BMFace *face, BMVert **verts, 
 +                          subdparams *params)
 +{
 +      BMFace *nf;
 +      int i, numcuts = params->numcuts;
 +      
 +      for (i=0; i<numcuts; i++) {
 +              connect_smallest_face(bm, verts[i], verts[numcuts+numcuts-i], &nf);
 +      }
 +}
 +
 +subdpattern t_2edge = {
 +      {1, 1, 0},
 +      t_2edge_split,
 +      3,
 +};
 +
 +
 +/*     v5
 +      / \
 + s v6/---\ v4 s
 +    / \ / \
 +sv7/---v---\ v3 s
 +  /  \/  \/ \
 + v8--v0--v1--v2
 +    s    s
 +*/
 +static void t_3edge_split(BMesh *bm, BMFace *face, BMVert **verts, 
 +                          subdparams *params)
 +{
 +      BMFace *nf;
 +      BMEdge *e, *ne, temp;
 +      BMVert ***lines, *v;
 +      void *stackarr[1];
 +      int i, j, a, b, numcuts = params->numcuts;
 +      
 +      /*number of verts in each line*/
 +      lines = MEM_callocN(sizeof(void*)*(numcuts+2), "triangle vert table");
 +      
 +      lines[0] = (BMVert**) stackarr;
 +      lines[0][0] = verts[numcuts*2+1];
 +      
 +      lines[1+numcuts] = MEM_callocN(sizeof(void*)*(numcuts+2), 
 +                                     "triangle vert table 2");
 +      for (i=0; i<numcuts; i++) {
 +              lines[1+numcuts][1+i] = verts[i];
 +      }
 +      lines[1+numcuts][0] = verts[numcuts*3+2];
 +      lines[1+numcuts][1+numcuts] = verts[numcuts];
 +
 +      for (i=0; i<numcuts; i++) {
 +              lines[i+1] = MEM_callocN(sizeof(void*)*(2+i), 
 +                                     "triangle vert table row");
 +              a = numcuts*2 + 2 + i;
 +              b = numcuts + numcuts - i;
 +              e = connect_smallest_face(bm, verts[a], verts[b], &nf);
 +              if (!e) goto cleanup;
 +
 +              BMO_SetFlag(bm, e, ELE_INNER);
 +              BMO_SetFlag(bm, nf, ELE_INNER);
 +
 +              lines[i+1][0] = verts[a];
 +              lines[i+1][1+i] = verts[b];
 +              
 +              temp = *e;
 +              for (j=0; j<i; j++) {
 +                      v = subdivideedgenum(bm, e, &temp, j, i, params, &ne,
 +                                           verts[a], verts[b]);
 +                      lines[i+1][j+1] = v;
 +
 +                      BMO_SetFlag(bm, ne, ELE_INNER);
 +              }
 +      }
 +      
 +
 +/*     v5
 +      / \
 + s v6/---\ v4 s
 +    / \ / \
 +sv7/---v---\ v3 s
 +  /  \/  \/ \
 + v8--v0--v1--v2
 +    s    s
 +*/
 +      for (i=1; i<numcuts+1; i++) {
 +              for (j=0; j<i; j++) {
 +                      e= connect_smallest_face(bm, lines[i][j], lines[i+1][j+1],
 +                                         &nf);
 +
 +                      BMO_SetFlag(bm, e, ELE_INNER);
 +                      BMO_SetFlag(bm, nf, ELE_INNER);
 +
 +                      e= connect_smallest_face(bm,lines[i][j+1],lines[i+1][j+1],
 +                                         &nf);
 +
 +                      BMO_SetFlag(bm, e, ELE_INNER);
 +                      BMO_SetFlag(bm, nf, ELE_INNER);
 +              }
 +      }
 +
 +cleanup:
 +      for (i=1; i<numcuts+2; i++) {
 +              if (lines[i]) MEM_freeN(lines[i]);
 +      }
 +
 +      MEM_freeN(lines);
 +}
 +
 +subdpattern t_3edge = {
 +      {1, 1, 1},
 +      t_3edge_split,
 +      3,
 +};
 +
 +
 +subdpattern q_4edge = {
 +      {1, 1, 1, 1},
 +      q_4edge_split,
 +      4,
 +};
 +
 +subdpattern *patterns[] = {
 +      &q_1edge,
 +      &q_2edge_op,
 +      &q_4edge,
 +      &q_3edge,
 +      &q_2edge,
 +      &t_1edge,
 +      &t_2edge,
 +      &t_3edge,
 +};
 +
 +#define PLEN  (sizeof(patterns) / sizeof(void*))
 +
 +typedef struct subd_facedata {
 +      BMVert *start; subdpattern *pat;
 +} subd_facedata;
 +
 +void esubdivide_exec(BMesh *bmesh, BMOperator *op)
 +{
 +      BMOpSlot *einput;
 +      BMEdge *edge, **edges = NULL;
 +      V_DECLARE(edges);
 +      BMFace *face;
 +      BMLoop *nl;
 +      BMVert **verts = NULL;
 +      V_DECLARE(verts);
 +      BMIter fiter, liter;
 +      subdpattern *pat;
 +      subdparams params;
 +      subd_facedata *facedata = NULL;
 +      V_DECLARE(facedata);
-       flag = BMO_GetSlot(op, "flag")->data.i;
-       rad = BMO_GetSlot(op, "radius")->data.f;
++      float smooth, fractal;
++      int beauty;
++      int i, j, matched, a, b, numcuts;
 +      
 +      BMO_Flag_Buffer(bmesh, op, "edges", SUBD_SPLIT);
 +      
 +      numcuts = BMO_GetSlot(op, "numcuts")->data.i;
-       params.flag = flag;
++      smooth = BMO_GetSlot(op, "smooth")->data.f;
++      fractal = BMO_GetSlot(op, "fractal")->data.f;
++      beauty = BMO_GetSlot(op, "beauty")->data.i;
 +
 +      einput = BMO_GetSlot(op, "edges");
 +      
 +      /*first go through and tag edges*/
 +      BMO_Flag_To_Slot(bmesh, op, "edges",
 +               SUBD_SPLIT, BM_EDGE);
 +
-       params.rad = rad;
 +      params.numcuts = numcuts;
 +      params.op = op;
- void BM_esubdivideflag(Object *obedit, BMesh *bm, int selflag, float rad, 
-                      int flag, int numcuts, int seltype) {
++      params.smooth = smooth;
++      params.fractal = fractal;
++      params.beauty = beauty;
 +
 +      BMO_Mapping_To_Flag(bmesh, op, "custompatterns",
 +                          FACE_CUSTOMFILL);
 +
 +      BMO_Mapping_To_Flag(bmesh, op, "edgepercents",
 +                          EDGE_PERCENT);
 +
 +      for (face=BMIter_New(&fiter, bmesh, BM_FACES_OF_MESH, NULL);
 +           face; face=BMIter_Step(&fiter)) {
 +              /*figure out which pattern to use*/
 +
 +              V_RESET(edges);
 +              V_RESET(verts);
 +              i = 0;
 +              for (nl=BMIter_New(&liter, bmesh, BM_LOOPS_OF_FACE, face);
 +                   nl; nl=BMIter_Step(&liter)) {
 +                      V_GROW(edges);
 +                      V_GROW(verts);
 +                      edges[i] = nl->e;
 +                      verts[i] = nl->v;
 +                      i++;
 +              }
 +
 +              if (BMO_TestFlag(bmesh, face, FACE_CUSTOMFILL)) {
 +                      pat = BMO_Get_MapData(bmesh, op, 
 +                                  "custompatterns", face);
 +                      for (i=0; i<pat->len; i++) {
 +                              matched = 1;
 +                              for (j=0; j<pat->len; j++) {
 +                                      a = (j + i) % pat->len;
 +                                      if ((!!BMO_TestFlag(bmesh, edges[a], SUBD_SPLIT))
 +                                              != (!!pat->seledges[j])) {
 +                                                      matched = 0;
 +                                                      break;
 +                                      }
 +                              }
 +                              if (matched) {
 +                                      V_GROW(facedata);
 +                                      b = V_COUNT(facedata)-1;
 +                                      facedata[b].pat = pat;
 +                                      facedata[b].start = verts[i];
 +                                      BMO_SetFlag(bmesh, face, SUBD_SPLIT);
 +                                      break;
 +                              }
 +                      }
 +                      if (!matched) {
 +                              /*if no match, append null element to array.*/
 +                              V_GROW(facedata);
 +                      }
 +
 +                      /*obvously don't test for other patterns matching*/
 +                      continue;
 +              }
 +
 +              for (i=0; i<PLEN; i++) {
 +                      pat = patterns[i];
 +                      if (pat->len == face->len) {
 +                              for (a=0; a<pat->len; a++) {
 +                              matched = 1;
 +                              for (b=0; b<pat->len; b++) {
 +                                      j = (b + a) % pat->len;
 +                                      if ((!!BMO_TestFlag(bmesh, edges[j], SUBD_SPLIT))
 +                                              != (!!pat->seledges[b])) {
 +                                                      matched = 0;
 +                                                      break;
 +                                      }
 +                              }
 +                              if (matched) break;
 +                              }
 +                              if (matched) {
 +                                      V_GROW(facedata);
 +                                      BMO_SetFlag(bmesh, face, SUBD_SPLIT);
 +                                      j = V_COUNT(facedata) - 1;
 +                                      facedata[j].pat = pat;
 +                                      facedata[j].start = verts[a];
 +                                      break;
 +                              }
 +                      }
 +              }
 +      }
 +
 +      einput = BMO_GetSlot(op, "edges");
 +
 +      /*go through and split edges*/
 +      for (i=0; i<einput->len; i++) {
 +              edge = ((BMEdge**)einput->data.p)[i];
 +              bm_subdivide_multicut(bmesh, edge,&params, edge->v1, edge->v2);
 +              //BM_Split_Edge_Multi(bmesh, edge, numcuts);
 +      }
 +
 +      //if (facedata) V_FREE(facedata);
 +      //return;
 +
 +      i = 0;
 +      for (face=BMIter_New(&fiter, bmesh, BM_FACES_OF_MESH, NULL);
 +           face; face=BMIter_Step(&fiter)) {
 +              /*figure out which pattern to use*/
 +              V_RESET(verts);
 +              if (BMO_TestFlag(bmesh, face, SUBD_SPLIT) == 0) continue;
 +
 +              pat = facedata[i].pat;
 +              if (!pat) continue;
 +
 +              j = a = 0;
 +              for (nl=BMIter_New(&liter, bmesh, BM_LOOPS_OF_FACE, face);
 +                   nl; nl=BMIter_Step(&liter)) {
 +                      if (nl->v == facedata[i].start) {
 +                              a = j+1;
 +                              break;
 +                      }
 +                      j++;
 +              }
 +
 +              for (j=0; j<face->len; j++) {
 +                      V_GROW(verts);
 +              }
 +              
 +              j = 0;
 +              for (nl=BMIter_New(&liter, bmesh, BM_LOOPS_OF_FACE, face);
 +                   nl; nl=BMIter_Step(&liter)) {
 +                      b = (j-a+face->len) % face->len;
 +                      verts[b] = nl->v;
 +                      j += 1;
 +              }
 +              
 +              pat->connectexec(bmesh, face, verts, &params);
 +              i++;
 +      }
 +
 +      if (facedata) V_FREE(facedata);
 +      if (edges) V_FREE(edges);
 +      if (verts) V_FREE(verts);
 +
 +      BMO_Flag_To_Slot(bmesh, op, "outinner",
 +                       ELE_INNER, BM_ALL);
 +      BMO_Flag_To_Slot(bmesh, op, "outsplit",
 +                       ELE_SPLIT, BM_ALL);
 +}
 +
 +/*editmesh-emulating function*/
-       BMO_InitOpf(bm, &op, "esubd edges=%he flag=%d radius=%f numcuts=%d",
-                   selflag, flag, rad, numcuts);
++void BM_esubdivideflag(Object *obedit, BMesh *bm, int flag, float smooth, 
++                     float fractal, int beauty, int numcuts, int seltype) {
 +      BMOperator op;
 +      
++      BMO_InitOpf(bm, &op, "esubd edges=%he smooth=%f fractal=%f "
++                           "beauty=%d numcuts=%d", flag, smooth, fractal,
++                           beauty, numcuts);
++      
 +      BMO_Exec_Op(bm, &op);
- }
++      
 +      if (seltype == SUBDIV_SELECT_INNER) {
 +              BMOIter iter;
 +              BMHeader *ele;
 +              int i;
 +              
 +              ele = BMO_IterNew(&iter,bm,&op, "outinner", BM_EDGE|BM_VERT);
 +              for (; ele; ele=BMO_IterStep(&iter)) {
 +                      BM_Select(bm, ele, 1);
 +              }
 +      }
 +      BMO_Finish_Op(bm, &op);
 +}
 +
++#if 0
 +void BM_esubdivideflag_conv(Object *obedit,EditMesh *em,int selflag, float rad, 
 +                     int flag, int numcuts, int seltype) {
 +      BMesh *bm = editmesh_to_bmesh(em);
 +      EditMesh *em2;
 +
 +      BM_esubdivideflag(obedit, bm, selflag, rad, flag, numcuts, seltype);
 +      em2 = bmesh_to_editmesh(bm);
 +      
 +      free_editMesh(em);
 +      *em = *em2;
 +      MEM_freeN(em2);
 +      BM_Free_Mesh(bm);
++}
++#endif
index 7404f189e456cb00d1b87d820f5fde40e413fe11,0000000000000000000000000000000000000000..7bb471117d85c7b4d489c099fd9e8f93861b86bf
mode 100644,000000..100644
--- /dev/null
@@@ -1,37 -1,0 +1,38 @@@
-       int flag;
-       float rad;
 +#ifndef _SUBDIVIDEOP_H
 +#define _SUBDIVIDEOP_H
 +
 +typedef struct subdparams {
 +      int numcuts;
++      float smooth;
++      float fractal;
++      int beauty;
 +      BMOperator *op;
 +} subdparams;
 +
 +typedef void (*subd_pattern_fill_fp)(BMesh *bm, BMFace *face, BMVert **verts, 
 +                                   subdparams *params);
 +
 +/*
 +note: this is a pattern-based edge subdivider.
 +it tries to match a pattern to edge selections on faces,
 +then executes functions to cut them.
 +*/
 +typedef struct subdpattern {
 +      int seledges[20]; //selected edges mask, for splitting
 +
 +      /*verts starts at the first new vert cut, not the first vert in the
 +        face*/
 +      subd_pattern_fill_fp connectexec;
 +      int len; /*total number of verts, before any subdivision*/
 +} subdpattern;
 +
 +/*generic subdivision rules:
 +  
 +  * two selected edges in a face should make a link
 +    between them.
 +
 +  * one edge should do, what? make pretty topology, or just
 +    split the edge only?
 +*/
 +
 +#endif /* _SUBDIVIDEOP_H */
index a25d0675cb0b0ecdda4e23929c6ad16f1ccd7357,132d9edf8d0c94a46c9d73ce90481ad339ffb4b1..2a012437b427fbce4a5c09fee7729451c7f2ccc5
@@@ -64,6 -64,6 +64,7 @@@
  #include "BKE_global.h"
  #include "BKE_utildefines.h"
  #include "BKE_customdata.h"
++#include "BKE_mesh.h"
  
  //#include "blendef.h"
  
@@@ -3382,10 -3385,9 +3386,9 @@@ static int iteratorStopped(void *arg
  
  ReebGraph *BIF_ReebGraphMultiFromEditMesh(bContext *C)
  {
- #if 0 /*BMESH_TODO*/
        Scene *scene = CTX_data_scene(C);
        Object *obedit = CTX_data_edit_object(C);
--      EditMesh *em =( (Mesh*)obedit->data)->edit_mesh;
++      EditMesh *em =BKE_mesh_get_editmesh(((Mesh*)obedit->data));
        EdgeIndex indexed_edges;
        VertexData *data;
        ReebGraph *rg = NULL;
        
        MEM_freeN(data);
  
++      /*no need to load the editmesh back into the object, just
++        free it (avoids ngon conversion issues too going back the
++                 other way)*/
++      free_editMesh(em);
++      MEM_freeN(em);
++      
        return rg;
- #endif
  }
  
  #if 0
index 97852fb980c8d43ca1c4291858c6edd6d4087e54,0face00f82b272e441cdda77e54cffc9aad98054..dd29f2706809d5b4b6bf253aa7d37067993c42ff
@@@ -73,33 -67,8 +73,36 @@@ struct BMFace
  #define B_JOINTRIA_VCOL               0X400
  #define B_JOINTRIA_SHARP      0X800
  #define B_JOINTRIA_MAT                0X1000
 -#define B_FRACTAL                     0x2000
 -#define B_SPHERE                      0x4000
++#define B_FRACTAL             0x2000
++#define B_SPHERE              0x4000
 +
 +/* bmeshutils.c */
 +
 +/*this function is currently defunct, dead*/
 +void EDBM_Tesselate(struct EditMesh *em);
 +void EDBM_RecalcNormals(struct BMEditMesh *em);
 +void EDBM_MakeEditBMesh(struct Scene *scene, struct Object *ob);
 +void EDBM_FreeEditBMesh(struct BMEditMesh *tm);
 +void EDBM_LoadEditBMesh(struct Scene *scene, struct Object *ob);
 +void EDBM_init_index_arrays(struct BMEditMesh *tm, int forvert, int foredge, int forface);
 +void EDBM_free_index_arrays(struct BMEditMesh *tm);
 +struct BMVert *EDBM_get_vert_for_index(struct BMEditMesh *tm, int index);
 +struct BMEdge *EDBM_get_edge_for_index(struct BMEditMesh *tm, int index);
 +struct BMFace *EDBM_get_face_for_index(struct BMEditMesh *tm, int index);
 +struct BMFace *EDBM_get_actFace(struct BMEditMesh *em, int sloppy);
 +void EDBM_selectmode_flush(struct BMEditMesh *em);
 +int EDBM_get_actSelection(struct BMEditMesh *em, struct BMEditSelection *ese);
 +void EDBM_editselection_center(struct BMEditMesh *em, float *center, struct BMEditSelection *ese);
 +void EDBM_editselection_plane(struct BMEditMesh *em, float *plane, struct BMEditSelection *ese);
++void EDBM_editselection_normal(float *normal, struct BMEditSelection *ese);
 +void EDBM_selectmode_set(struct BMEditMesh *em);
 +void EDBM_convertsel(struct BMEditMesh *em, short oldmode, short selectmode);
 +
 +int                   EDBM_check_backbuf(unsigned int index);
 +int                   EDBM_mask_init_backbuf_border(struct ViewContext *vc, short mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax);
 +void          EDBM_free_backbuf(void);
 +int                   EDBM_init_backbuf_border(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax);
 +int                   EDBM_init_backbuf_circle(struct ViewContext *vc, short xs, short ys, short rads);
  
  /* meshtools.c */
  
index 640d16be43f78cce17475894e1935f434d7d084b,b576299c1d07f511ae7b0ab21a5328f28b535a83..6360bf49f1aaff9da246079cca6b98f20b543927
@@@ -37,10 -37,9 +37,9 @@@ struct bglMats
  struct BPoint;
  struct Nurb;
  struct BezTriple;
 -struct EditVert;
 -struct EditEdge;
 -struct EditFace;
 +struct BMVert;
 +struct BMEdge;
- struct BMEditMesh;
 +struct BMFace;
  struct ImBuf;
  struct Scene;
  struct bContext;
index f9e6e09cfe067b805b78a0a90a73228c9eb7da25,0000000000000000000000000000000000000000..c4f2a294d0b7d30cabb7b7ac2e96c0bbfd77e1a6
mode 100644,000000..100644
--- /dev/null
@@@ -1,1424 -1,0 +1,1424 @@@
-       {1, "MATERIAL", "Material", ""},
-       {2, "IMAGE", "Image", ""},
-       {3, "AREA", "Area", ""},
-       {4, "PERIMETER", "Perimeter", ""},
-       {5, "NORMAL", "Normal", ""},
-       {6, "COPLANAR", "Co-planar", ""},
-       {0, NULL, NULL, NULL}
 +/**
 + * $Id: 
 + *
 + * ***** BEGIN GPL LICENSE BLOCK *****
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software Foundation,
 + * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 + *
 + * The Original Code is Copyright (C) 2004 Blender Foundation.
 + * All rights reserved.
 + *
 + * The Original Code is: all of this file.
 + *
 + * Contributor(s): none yet.
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +
 +/*
 +
 +BMEditMesh_mods.c, UI level access, no geometry changes 
 +
 +*/
 +
 +#include <stdlib.h>
 +#include <string.h>
 +#include <math.h>
 +
 +#include "MEM_guardedalloc.h"
 +
 +#include "MTC_matrixops.h"
 +
 +#include "DNA_mesh_types.h"
 +#include "DNA_material_types.h"
 +#include "DNA_meshdata_types.h"
 +#include "DNA_modifier_types.h"
 +#include "DNA_object_types.h"
 +#include "DNA_texture_types.h"
 +#include "DNA_scene_types.h"
 +#include "DNA_screen_types.h"
 +#include "DNA_space_types.h"
 +#include "DNA_view3d_types.h"
 +
 +#include "BLI_blenlib.h"
 +#include "BLI_arithb.h"
 +#include "BLI_rand.h"
 +
 +#include "BKE_context.h"
 +#include "BKE_displist.h"
 +#include "BKE_depsgraph.h"
 +#include "BKE_DerivedMesh.h"
 +#include "BKE_customdata.h"
 +#include "BKE_global.h"
 +#include "BKE_mesh.h"
 +#include "BKE_material.h"
 +#include "BKE_texture.h"
 +#include "BKE_utildefines.h"
 +#include "BKE_report.h"
 +#include "BKE_tessmesh.h"
 +
 +#include "IMB_imbuf_types.h"
 +#include "IMB_imbuf.h"
 +
 +#include "RE_render_ext.h"  /* externtex */
 +
 +#include "WM_api.h"
 +#include "WM_types.h"
 +
 +#include "RNA_access.h"
 +#include "RNA_define.h"
 +
 +#include "ED_mesh.h"
 +#include "ED_screen.h"
 +#include "ED_view3d.h"
 +#include "bmesh.h"
 +
 +#include "BIF_gl.h"
 +#include "BIF_glutil.h"
 +
 +#include "mesh_intern.h"
 +
 +#include "BLO_sys_types.h" // for intptr_t support
 +
 +/* XXX */
 +static void waitcursor() {}
 +static int pupmenu() {return 0;}
 +
 +/* ****************************** MIRROR **************** */
 +
 +void EDBM_select_mirrored(Object *obedit, BMEditMesh *em)
 +{
 +#if 0 //BMESH_TODO
 +      if(em->selectmode & SCE_SELECT_VERTEX) {
 +              BMVert *eve, *v1;
 +              
 +              for(eve= em->verts.first; eve; eve= eve->next) {
 +                      if(eve->f & SELECT) {
 +                              v1= BMEditMesh_get_x_mirror_vert(obedit, em, eve->co);
 +                              if(v1) {
 +                                      eve->f &= ~SELECT;
 +                                      v1->f |= SELECT;
 +                              }
 +                      }
 +              }
 +      }
 +#endif
 +}
 +
 +void EDBM_automerge(int update) 
 +{
 +// XXX        int len;
 +      
 +//    if ((scene->automerge) &&
 +//            (obedit && obedit->type==OB_MESH) &&
 +//            (((Mesh*)obedit->data)->mr==NULL)
 +//      ) {
 +//            len = removedoublesflag(1, 1, scene->toolsettings->doublimit);
 +//            if (len) {
 +//                    em->totvert -= len; /* saves doing a countall */
 +//                    if (update) {
 +//                            DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 +//                    }
 +//            }
 +//    }
 +}
 +
 +/* ****************************** SELECTION ROUTINES **************** */
 +
 +unsigned int bm_solidoffs=0, bm_wireoffs=0, bm_vertoffs=0;    /* set in drawobject.c ... for colorindices */
 +
 +/* facilities for border select and circle select */
 +static char *selbuf= NULL;
 +
 +/* opengl doesn't support concave... */
 +static void draw_triangulated(short mcords[][2], short tot)
 +{
 +      ListBase lb={NULL, NULL};
 +      DispList *dl;
 +      float *fp;
 +      int a;
 +      
 +      /* make displist */
 +      dl= MEM_callocN(sizeof(DispList), "poly disp");
 +      dl->type= DL_POLY;
 +      dl->parts= 1;
 +      dl->nr= tot;
 +      dl->verts= fp=  MEM_callocN(tot*3*sizeof(float), "poly verts");
 +      BLI_addtail(&lb, dl);
 +      
 +      for(a=0; a<tot; a++, fp+=3) {
 +              fp[0]= (float)mcords[a][0];
 +              fp[1]= (float)mcords[a][1];
 +      }
 +      
 +      /* do the fill */
 +      filldisplist(&lb, &lb);
 +
 +      /* do the draw */
 +      dl= lb.first;   /* filldisplist adds in head of list */
 +      if(dl->type==DL_INDEX3) {
 +              int *index;
 +              
 +              a= dl->parts;
 +              fp= dl->verts;
 +              index= dl->index;
 +              glBegin(GL_TRIANGLES);
 +              while(a--) {
 +                      glVertex3fv(fp+3*index[0]);
 +                      glVertex3fv(fp+3*index[1]);
 +                      glVertex3fv(fp+3*index[2]);
 +                      index+= 3;
 +              }
 +              glEnd();
 +      }
 +      
 +      freedisplist(&lb);
 +}
 +
 +
 +/* reads rect, and builds selection array for quick lookup */
 +/* returns if all is OK */
 +int EDBM_init_backbuf_border(ViewContext *vc, short xmin, short ymin, short xmax, short ymax)
 +{
 +      struct ImBuf *buf;
 +      unsigned int *dr;
 +      int a;
 +      
 +      if(vc->obedit==NULL || vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
 +      
 +      buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
 +      if(buf==NULL) return 0;
 +      if(bm_vertoffs==0) return 0;
 +
 +      dr = buf->rect;
 +      
 +      /* build selection lookup */
 +      selbuf= MEM_callocN(bm_vertoffs+1, "selbuf");
 +      
 +      a= (xmax-xmin+1)*(ymax-ymin+1);
 +      while(a--) {
 +              if(*dr>0 && *dr<=bm_vertoffs) 
 +                      selbuf[*dr]= 1;
 +              dr++;
 +      }
 +      IMB_freeImBuf(buf);
 +      return 1;
 +}
 +
 +int EDBM_check_backbuf(unsigned int index)
 +{
 +      if(selbuf==NULL) return 1;
 +      if(index>0 && index<=bm_vertoffs)
 +              return selbuf[index];
 +      return 0;
 +}
 +
 +void EDBM_free_backbuf(void)
 +{
 +      if(selbuf) MEM_freeN(selbuf);
 +      selbuf= NULL;
 +}
 +
 +/* mcords is a polygon mask
 +   - grab backbuffer,
 +   - draw with black in backbuffer, 
 +   - grab again and compare
 +   returns 'OK' 
 +*/
 +int EDBM_mask_init_backbuf_border(ViewContext *vc, short mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax)
 +{
 +      unsigned int *dr, *drm;
 +      struct ImBuf *buf, *bufmask;
 +      int a;
 +      
 +      /* method in use for face selecting too */
 +      if(vc->obedit==NULL) {
 +              if(FACESEL_PAINT_TEST);
 +              else return 0;
 +      }
 +      else if(vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
 +
 +      buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
 +      if(buf==NULL) return 0;
 +      if(bm_vertoffs==0) return 0;
 +
 +      dr = buf->rect;
 +
 +      /* draw the mask */
 +      glDisable(GL_DEPTH_TEST);
 +      
 +      glColor3ub(0, 0, 0);
 +      
 +      /* yah, opengl doesn't do concave... tsk! */
 +      ED_region_pixelspace(vc->ar);
 +      draw_triangulated(mcords, tot); 
 +      
 +      glBegin(GL_LINE_LOOP);  /* for zero sized masks, lines */
 +      for(a=0; a<tot; a++) glVertex2s(mcords[a][0], mcords[a][1]);
 +      glEnd();
 +      
 +      glFinish();     /* to be sure readpixels sees mask */
 +      
 +      /* grab mask */
 +      bufmask= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
 +      drm = bufmask->rect;
 +      if(bufmask==NULL) return 0; /* only when mem alloc fails, go crash somewhere else! */
 +      
 +      /* build selection lookup */
 +      selbuf= MEM_callocN(bm_vertoffs+1, "selbuf");
 +      
 +      a= (xmax-xmin+1)*(ymax-ymin+1);
 +      while(a--) {
 +              if(*dr>0 && *dr<=bm_vertoffs && *drm==0) selbuf[*dr]= 1;
 +              dr++; drm++;
 +      }
 +      IMB_freeImBuf(buf);
 +      IMB_freeImBuf(bufmask);
 +      return 1;
 +      
 +}
 +
 +/* circle shaped sample area */
 +int EDBM_init_backbuf_circle(ViewContext *vc, short xs, short ys, short rads)
 +{
 +      struct ImBuf *buf;
 +      unsigned int *dr;
 +      short xmin, ymin, xmax, ymax, xc, yc;
 +      int radsq;
 +      
 +      /* method in use for face selecting too */
 +      if(vc->obedit==NULL) {
 +              if(FACESEL_PAINT_TEST);
 +              else return 0;
 +      }
 +      else if(vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
 +      
 +      xmin= xs-rads; xmax= xs+rads;
 +      ymin= ys-rads; ymax= ys+rads;
 +      buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
 +      if(bm_vertoffs==0) return 0;
 +      if(buf==NULL) return 0;
 +
 +      dr = buf->rect;
 +      
 +      /* build selection lookup */
 +      selbuf= MEM_callocN(bm_vertoffs+1, "selbuf");
 +      radsq= rads*rads;
 +      for(yc= -rads; yc<=rads; yc++) {
 +              for(xc= -rads; xc<=rads; xc++, dr++) {
 +                      if(xc*xc + yc*yc < radsq) {
 +                              if(*dr>0 && *dr<=bm_vertoffs) selbuf[*dr]= 1;
 +                      }
 +              }
 +      }
 +
 +      IMB_freeImBuf(buf);
 +      return 1;
 +      
 +}
 +
 +static void findnearestvert__doClosest(void *userData, BMVert *eve, int x, int y, int index)
 +{
 +      struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; BMVert *closest; } *data = userData;
 +
 +      if (data->pass==0) {
 +              if (index<=data->lastIndex)
 +                      return;
 +      } else {
 +              if (index>data->lastIndex)
 +                      return;
 +      }
 +
 +      if (data->dist>3) {
 +              int temp = abs(data->mval[0] - x) + abs(data->mval[1]- y);
 +              if (BM_TestHFlag(eve, BM_SELECT) == data->select) {
 +                      if (data->strict == 1)
 +                              return;
 +                      else
 +                              temp += 5;
 +              }
 +
 +              if (temp<data->dist) {
 +                      data->dist = temp;
 +                      data->closest = eve;
 +                      data->closestIndex = index;
 +              }
 +      }
 +}
 +
 +
 +
 +
 +static unsigned int findnearestvert__backbufIndextest(void *handle, unsigned int index)
 +{
 +      BMEditMesh *em= (BMEditMesh *)handle;
 +      BMIter iter;
 +      BMVert *eve = BMIter_AtIndex(em->bm, BM_VERTS_OF_MESH, NULL, index-1);
 +
 +      if(eve && BM_TestHFlag(eve, BM_SELECT)) return 0;
 +      return 1; 
 +}
 +/**
 + * findnearestvert
 + * 
 + * dist (in/out): minimal distance to the nearest and at the end, actual distance
 + * sel: selection bias
 + *            if SELECT, selected vertice are given a 5 pixel bias to make them farter than unselect verts
 + *            if 0, unselected vertice are given the bias
 + * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased 
 + */
 +BMVert *EDBM_findnearestvert(ViewContext *vc, int *dist, short sel, short strict)
 +{
 +      if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)){
 +              int distance;
 +              unsigned int index;
 +              BMVert *eve;
 +              
 +              if(strict) index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_wireoffs, 0xFFFFFF, &distance, strict, vc->em, findnearestvert__backbufIndextest); 
 +              else index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_wireoffs, 0xFFFFFF, &distance, 0, NULL, NULL); 
 +              
 +              eve = BMIter_AtIndex(vc->em->bm, BM_VERTS_OF_MESH, NULL, index-1);
 +              
 +              if(eve && distance < *dist) {
 +                      *dist = distance;
 +                      return eve;
 +              } else {
 +                      return NULL;
 +              }
 +                      
 +      }
 +      else {
 +              struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; BMVert *closest; } data;
 +              static int lastSelectedIndex=0;
 +              static BMVert *lastSelected=NULL;
 +              
 +              if (lastSelected && BMIter_AtIndex(vc->em->bm, BM_VERTS_OF_MESH, NULL, lastSelectedIndex)!=lastSelected) {
 +                      lastSelectedIndex = 0;
 +                      lastSelected = NULL;
 +              }
 +
 +              data.lastIndex = lastSelectedIndex;
 +              data.mval[0] = vc->mval[0];
 +              data.mval[1] = vc->mval[1];
 +              data.select = sel;
 +              data.dist = *dist;
 +              data.strict = strict;
 +              data.closest = NULL;
 +              data.closestIndex = 0;
 +
 +              data.pass = 0;
 +              mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, 1);
 +
 +              if (data.dist>3) {
 +                      data.pass = 1;
 +                      mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, 1);
 +              }
 +
 +              *dist = data.dist;
 +              lastSelected = data.closest;
 +              lastSelectedIndex = data.closestIndex;
 +
 +              return data.closest;
 +      }
 +}
 +
 +/* returns labda for closest distance v1 to line-piece v2-v3 */
 +static float labda_PdistVL2Dfl( float *v1, float *v2, float *v3) 
 +{
 +      float rc[2], len;
 +      
 +      rc[0]= v3[0]-v2[0];
 +      rc[1]= v3[1]-v2[1];
 +      len= rc[0]*rc[0]+ rc[1]*rc[1];
 +      if(len==0.0f)
 +              return 0.0f;
 +      
 +      return ( rc[0]*(v1[0]-v2[0]) + rc[1]*(v1[1]-v2[1]) )/len;
 +}
 +
 +/* note; uses v3d, so needs active 3d window */
 +static void findnearestedge__doClosest(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index)
 +{
 +      struct { ViewContext vc; float mval[2]; int dist; BMEdge *closest; } *data = userData;
 +      float v1[2], v2[2];
 +      int distance;
 +              
 +      v1[0] = x0;
 +      v1[1] = y0;
 +      v2[0] = x1;
 +      v2[1] = y1;
 +              
 +      distance= PdistVL2Dfl(data->mval, v1, v2);
 +              
 +      if(BM_TestHFlag(eed, BM_SELECT)) distance+=5;
 +      if(distance < data->dist) {
 +              if(data->vc.rv3d->rflag & RV3D_CLIPPING) {
 +                      float labda= labda_PdistVL2Dfl(data->mval, v1, v2);
 +                      float vec[3];
 +
 +                      vec[0]= eed->v1->co[0] + labda*(eed->v2->co[0] - eed->v1->co[0]);
 +                      vec[1]= eed->v1->co[1] + labda*(eed->v2->co[1] - eed->v1->co[1]);
 +                      vec[2]= eed->v1->co[2] + labda*(eed->v2->co[2] - eed->v1->co[2]);
 +                      Mat4MulVecfl(data->vc.obedit->obmat, vec);
 +
 +                      if(view3d_test_clipping(data->vc.rv3d, vec)==0) {
 +                              data->dist = distance;
 +                              data->closest = eed;
 +                      }
 +              }
 +              else {
 +                      data->dist = distance;
 +                      data->closest = eed;
 +              }
 +      }
 +}
 +BMEdge *EDBM_findnearestedge(ViewContext *vc, int *dist)
 +{
 +
 +      if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
 +              int distance;
 +              unsigned int index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_solidoffs, bm_wireoffs, &distance,0, NULL, NULL);
 +              BMEdge *eed = BMIter_AtIndex(vc->em->bm, BM_EDGES_OF_MESH, NULL, index-1);
 +
 +              if (eed && distance<*dist) {
 +                      *dist = distance;
 +                      return eed;
 +              } else {
 +                      return NULL;
 +              }
 +      }
 +      else {
 +              struct { ViewContext vc; float mval[2]; int dist; BMEdge *closest; } data;
 +
 +              data.vc= *vc;
 +              data.mval[0] = vc->mval[0];
 +              data.mval[1] = vc->mval[1];
 +              data.dist = *dist;
 +              data.closest = NULL;
 +
 +              mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, 2);
 +
 +              *dist = data.dist;
 +              return data.closest;
 +      }
 +}
 +
 +static void findnearestface__getDistance(void *userData, BMFace *efa, int x, int y, int index)
 +{
 +      struct { short mval[2]; int dist; BMFace *toFace; } *data = userData;
 +
 +      if (efa==data->toFace) {
 +              int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
 +
 +              if (temp<data->dist)
 +                      data->dist = temp;
 +      }
 +}
 +static void findnearestface__doClosest(void *userData, BMFace *efa, int x, int y, int index)
 +{
 +      struct { short mval[2], pass; int dist, lastIndex, closestIndex; BMFace *closest; } *data = userData;
 +
 +      if (data->pass==0) {
 +              if (index<=data->lastIndex)
 +                      return;
 +      } else {
 +              if (index>data->lastIndex)
 +                      return;
 +      }
 +
 +      if (data->dist>3) {
 +              int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
 +
 +              if (temp<data->dist) {
 +                      data->dist = temp;
 +                      data->closest = efa;
 +                      data->closestIndex = index;
 +              }
 +      }
 +}
 +static BMFace *EDBM_findnearestface(ViewContext *vc, int *dist)
 +{
 +
 +      if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
 +              unsigned int index = view3d_sample_backbuf(vc, vc->mval[0], vc->mval[1]);
 +              BMFace *efa = BMIter_AtIndex(vc->em->bm, BM_FACES_OF_MESH, NULL, index-1);
 +
 +              if (efa) {
 +                      struct { short mval[2]; int dist; BMFace *toFace; } data;
 +
 +                      data.mval[0] = vc->mval[0];
 +                      data.mval[1] = vc->mval[1];
 +                      data.dist = 0x7FFF;             /* largest short */
 +                      data.toFace = efa;
 +
 +                      mesh_foreachScreenFace(vc, findnearestface__getDistance, &data);
 +
 +                      if(vc->em->selectmode == SCE_SELECT_FACE || data.dist<*dist) {  /* only faces, no dist check */
 +                              *dist= data.dist;
 +                              return efa;
 +                      }
 +              }
 +              
 +              return NULL;
 +      }
 +      else {
 +              struct { short mval[2], pass; int dist, lastIndex, closestIndex; BMFace *closest; } data;
 +              static int lastSelectedIndex=0;
 +              static BMFace *lastSelected=NULL;
 +
 +              if (lastSelected && BMIter_AtIndex(vc->em->bm, BM_FACES_OF_MESH, NULL, lastSelectedIndex)!=lastSelected) {
 +                      lastSelectedIndex = 0;
 +                      lastSelected = NULL;
 +              }
 +
 +              data.lastIndex = lastSelectedIndex;
 +              data.mval[0] = vc->mval[0];
 +              data.mval[1] = vc->mval[1];
 +              data.dist = *dist;
 +              data.closest = NULL;
 +              data.closestIndex = 0;
 +
 +              data.pass = 0;
 +              mesh_foreachScreenFace(vc, findnearestface__doClosest, &data);
 +
 +              if (data.dist>3) {
 +                      data.pass = 1;
 +                      mesh_foreachScreenFace(vc, findnearestface__doClosest, &data);
 +              }
 +
 +              *dist = data.dist;
 +              lastSelected = data.closest;
 +              lastSelectedIndex = data.closestIndex;
 +
 +              return data.closest;
 +      }
 +}
 +
 +/* best distance based on screen coords. 
 +   use em->selectmode to define how to use 
 +   selected vertices and edges get disadvantage
 +   return 1 if found one
 +*/
 +static int unified_findnearest(ViewContext *vc, BMVert **eve, BMEdge **eed, BMFace **efa) 
 +{
 +      BMEditMesh *em= vc->em;
 +      int dist= 75;
 +      
 +      *eve= NULL;
 +      *eed= NULL;
 +      *efa= NULL;
 +      
 +      /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
 +      view3d_validate_backbuf(vc);
 +      
 +      if(em->selectmode & SCE_SELECT_VERTEX)
 +              *eve= EDBM_findnearestvert(vc, &dist, BM_SELECT, 0);
 +      if(em->selectmode & SCE_SELECT_FACE)
 +              *efa= EDBM_findnearestface(vc, &dist);
 +
 +      dist-= 20;      /* since edges select lines, we give dots advantage of 20 pix */
 +      if(em->selectmode & SCE_SELECT_EDGE)
 +              *eed= EDBM_findnearestedge(vc, &dist);
 +
 +      /* return only one of 3 pointers, for frontbuffer redraws */
 +      if(*eed) {
 +              *efa= NULL; *eve= NULL;
 +      }
 +      else if(*efa) {
 +              *eve= NULL;
 +      }
 +      
 +      return (*eve || *eed || *efa);
 +}
 +
 +
 +/* ****************  SIMILAR "group" SELECTS. FACE, EDGE AND VERTEX ************** */
 +
 +/* selects new faces/edges/verts based on the
 + existing selection
 +
 +FACES GROUP
 + mode 1: same material
 + mode 2: same image
 + mode 3: same area
 + mode 4: same perimeter
 + mode 5: same normal
 + mode 6: same co-planer
 +*/
 +
 +static EnumPropertyItem prop_simface_types[] = {
++      {1, "MATERIAL", 0, "Material", ""},
++      {2, "IMAGE", 0, "Image", ""},
++      {3, "AREA", 0, "Area", ""},
++      {4, "PERIMETER", 0, "Perimeter", ""},
++      {5, "NORMAL", 0, "Normal", ""},
++      {6, "COPLANAR", 0, "Co-planar", ""},
++      {0, NULL, 0, NULL, NULL}
 +};
 +
 +
 +/* this as a way to compare the ares, perim  of 2 faces thay will scale to different sizes
 +*0.5 so smaller faces arnt ALWAYS selected with a thresh of 1.0 */
 +#define SCALE_CMP(a,b) ((a+a*thresh >= b) && (a-(a*thresh*0.5) <= b))
 +
 +static int similar_face_select__internal(Scene *scene, BMEditMesh *em, int mode)
 +{
 +#if 0 //BMESH_TODO
 +      BMFace *efa, *base_efa=NULL;
 +      unsigned int selcount=0; /*count how many new faces we select*/
 +      
 +      /*deselcount, count how many deselected faces are left, so we can bail out early
 +      also means that if there are no deselected faces, we can avoid a lot of looping */
 +      unsigned int deselcount=0; 
 +      float thresh= scene->toolsettings->select_thresh;
 +      short ok=0;
 +      
 +      for(efa= em->faces.first; efa; efa= efa->next) {
 +              if (!efa->h) {
 +                      if (efa->f & SELECT) {
 +                              efa->f1=1;
 +                              ok=1;
 +                      } else {
 +                              efa->f1=0;
 +                              deselcount++; /* a deselected face we may select later */
 +                      }
 +              }
 +      }
 +      
 +      if (!ok || !deselcount) /* no data selected OR no more data to select */
 +              return 0;
 +      
 +      /*if mode is 3 then record face areas, 4 record perimeter */
 +      if (mode==3) {
 +              for(efa= em->faces.first; efa; efa= efa->next) {
 +                      efa->tmp.fp= EM_face_area(efa);
 +              }
 +      } else if (mode==4) {
 +              for(efa= em->faces.first; efa; efa= efa->next) {
 +                      efa->tmp.fp= EM_face_perimeter(efa);
 +              }
 +      }
 +      
 +      for(base_efa= em->faces.first; base_efa; base_efa= base_efa->next) {
 +              if (base_efa->f1) { /* This was one of the faces originaly selected */
 +                      if (mode==1) { /* same material */
 +                              for(efa= em->faces.first; efa; efa= efa->next) {
 +                                      if (
 +                                              !(efa->f & SELECT) &&
 +                                              !efa->h &&
 +                                              base_efa->mat_nr == efa->mat_nr
 +                                      ) {
 +                                              EM_select_face(efa, 1);
 +                                              selcount++;
 +                                              deselcount--;
 +                                              if (!deselcount) /*have we selected all posible faces?, if so return*/
 +                                                      return selcount;
 +                                      }
 +                              }
 +                      } else if (mode==2) { /* same image */
 +                              MTFace *tf, *base_tf;
 +
 +                              base_tf = (MTFace*)CustomData_em_get(&em->fdata, base_efa->data,
 +                                                                   CD_MTFACE);
 +
 +                              if(!base_tf)
 +                                      return selcount;
 +
 +                              for(efa= em->faces.first; efa; efa= efa->next) {
 +                                      if (!(efa->f & SELECT) && !efa->h) {
 +                                              tf = (MTFace*)CustomData_em_get(&em->fdata, efa->data,
 +                                                                              CD_MTFACE);
 +
 +                                              if(base_tf->tpage == tf->tpage) {
 +                                                      EM_select_face(efa, 1);
 +                                                      selcount++;
 +                                                      deselcount--;
 +                                                      if (!deselcount) /*have we selected all posible faces?, if so return*/
 +                                                              return selcount;
 +                                              }
 +                                      }
 +                              }
 +                      } else if (mode==3 || mode==4) { /* same area OR same perimeter, both use the same temp var */
 +                              for(efa= em->faces.first; efa; efa= efa->next) {
 +                                      if (
 +                                              (!(efa->f & SELECT) && !efa->h) &&
 +                                              SCALE_CMP(base_efa->tmp.fp, efa->tmp.fp)
 +                                      ) {
 +                                              EM_select_face(efa, 1);
 +                                              selcount++;
 +                                              deselcount--;
 +                                              if (!deselcount) /*have we selected all posible faces?, if so return*/
 +                                                      return selcount;
 +                                      }
 +                              }
 +                      } else if (mode==5) { /* same normal */
 +                              float angle;
 +                              for(efa= em->faces.first; efa; efa= efa->next) {
 +                                      if (!(efa->f & SELECT) && !efa->h) {
 +                                              angle= VecAngle2(base_efa->n, efa->n);
 +                                              if (angle/180.0<=thresh) {
 +                                                      EM_select_face(efa, 1);
 +                                                      selcount++;
 +                                                      deselcount--;
 +                                                      if (!deselcount) /*have we selected all posible faces?, if so return*/
 +                                                              return selcount;
 +                                              }
 +                                      }
 +                              }
 +                      } else if (mode==6) { /* same planer */
 +                              float angle, base_dot, dot;
 +                              base_dot= Inpf(base_efa->cent, base_efa->n);
 +                              for(efa= em->faces.first; efa; efa= efa->next) {
 +                                      if (!(efa->f & SELECT) && !efa->h) {
 +                                              angle= VecAngle2(base_efa->n, efa->n);
 +                                              if (angle/180.0<=thresh) {
 +                                                      dot=Inpf(efa->cent, base_efa->n);
 +                                                      if (fabs(base_dot-dot) <= thresh) {
 +                                                              EM_select_face(efa, 1);
 +                                                              selcount++;
 +                                                              deselcount--;
 +                                                              if (!deselcount) /*have we selected all posible faces?, if so return*/
 +                                                                      return selcount;
 +                                                      }
 +                                              }
 +                                      }
 +                              }
 +                      }
 +              }
 +      } /* end base_efa loop */
 +      return selcount;
 +#endif
 +}
 +
 +/* ***************************************************** */
 +
 +/* ****************  LOOP SELECTS *************** */
 +static void walker_select(BMEditMesh *em, int walkercode, void *start, int select)
 +{
 +      BMesh *bm = em->bm;
 +      BMHeader *h;
 +      BMWalker walker;
 +
 +      BMW_Init(&walker, bm, walkercode, 0);
 +      h = BMW_Begin(&walker, start);
 +      for (; h; h=BMW_Step(&walker)) {
 +              BM_Select(bm, h, select);
 +      }
 +      BMW_End(&walker);
 +}
 +
 +#if 0
 +/* selects quads in loop direction of indicated edge */
 +/* only flush over edges with valence <= 2 */
 +void faceloop_select(EditMesh *em, EditEdge *startedge, int select)
 +{
 +      EditEdge *eed;
 +      EditFace *efa;
 +      int looking= 1;
 +      
 +      /* in eed->f1 we put the valence (amount of faces in edge) */
 +      /* in eed->f2 we put tagged flag as correct loop */
 +      /* in efa->f1 we put tagged flag as correct to select */
 +
 +      for(eed= em->edges.first; eed; eed= eed->next) {
 +              eed->f1= 0;
 +              eed->f2= 0;
 +      }
 +      for(efa= em->faces.first; efa; efa= efa->next) {
 +              efa->f1= 0;
 +              if(efa->h==0) {
 +                      efa->e1->f1++;
 +                      efa->e2->f1++;
 +                      efa->e3->f1++;
 +                      if(efa->e4) efa->e4->f1++;
 +              }
 +      }
 +      
 +      /* tag startedge OK*/
 +      startedge->f2= 1;
 +      
 +      while(looking) {
 +              looking= 0;
 +              
 +              for(efa= em->faces.first; efa; efa= efa->next) {
 +                      if(efa->h==0 && efa->e4 && efa->f1==0) {        /* not done quad */
 +                              if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { /* valence ok */
 +
 +                                      /* if edge tagged, select opposing edge and mark face ok */
 +                                      if(efa->e1->f2) {
 +                                              efa->e3->f2= 1;
 +                                              efa->f1= 1;
 +                                              looking= 1;
 +                                      }
 +                                      else if(efa->e2->f2) {
 +                                              efa->e4->f2= 1;
 +                                              efa->f1= 1;
 +                                              looking= 1;
 +                                      }
 +                                      if(efa->e3->f2) {
 +                                              efa->e1->f2= 1;
 +                                              efa->f1= 1;
 +                                              looking= 1;
 +                                      }
 +                                      if(efa->e4->f2) {
 +                                              efa->e2->f2= 1;
 +                                              efa->f1= 1;
 +                                              looking= 1;
 +                                      }
 +                              }
 +                      }
 +              }
 +      }
 +      
 +      /* (de)select the faces */
 +      if(select!=2) {
 +              for(efa= em->faces.first; efa; efa= efa->next) {
 +                      if(efa->f1) EM_select_face(efa, select);
 +              }
 +      }
 +}
 +#endif
 +
 +
 +/* selects or deselects edges that:
 +- if edges has 2 faces:
 +      - has vertices with valence of 4
 +      - not shares face with previous edge
 +- if edge has 1 face:
 +      - has vertices with valence 4
 +      - not shares face with previous edge
 +      - but also only 1 face
 +- if edge no face:
 +      - has vertices with valence 2
 +*/
 +
 +/* 
 +   Almostly exactly the same code as faceloop select
 +*/
 +static void edgering_select(BMEditMesh *em, BMEdge *startedge, int select)
 +{
 +#if 0 //BMESH_TODO
 +      BMEdge *eed;
 +      BMFace *efa;
 +      int looking= 1;
 +      
 +      /* in eed->f1 we put the valence (amount of faces in edge) */
 +      /* in eed->f2 we put tagged flag as correct loop */
 +      /* in efa->f1 we put tagged flag as correct to select */
 +
 +      for(eed= em->edges.first; eed; eed= eed->next) {
 +              eed->f1= 0;
 +              eed->f2= 0;
 +      }
 +      for(efa= em->faces.first; efa; efa= efa->next) {
 +              efa->f1= 0;
 +              if(efa->h==0) {
 +                      efa->e1->f1++;
 +                      efa->e2->f1++;
 +                      efa->e3->f1++;
 +                      if(efa->e4) efa->e4->f1++;
 +              }
 +      }
 +      
 +      /* tag startedge OK */
 +      startedge->f2= 1;
 +      
 +      while(looking) {
 +              looking= 0;
 +              
 +              for(efa= em->faces.first; efa; efa= efa->next) {
 +                      if(efa->e4 && efa->f1==0 && !efa->h) {  /* not done quad */
 +                              if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { /* valence ok */
 +
 +                                      /* if edge tagged, select opposing edge and mark face ok */
 +                                      if(efa->e1->f2) {
 +                                              efa->e3->f2= 1;
 +                                              efa->f1= 1;
 +                                              looking= 1;
 +                                      }
 +                                      else if(efa->e2->f2) {
 +                                              efa->e4->f2= 1;
 +                                              efa->f1= 1;
 +                                              looking= 1;
 +                                      }
 +                                      if(efa->e3->f2) {
 +                                              efa->e1->f2= 1;
 +                                              efa->f1= 1;
 +                                              looking= 1;
 +                                      }
 +                                      if(efa->e4->f2) {
 +                                              efa->e2->f2= 1;
 +                                              efa->f1= 1;
 +                                              looking= 1;
 +                                      }
 +                              }
 +                      }
 +              }
 +      }
 +      
 +      /* (de)select the edges */
 +      for(eed= em->edges.first; eed; eed= eed->next) {
 +              if(eed->f2) EM_select_edge(eed, select);
 +      }
 +#endif
 +}
 +
 +static int loop_multiselect(bContext *C, wmOperator *op)
 +{
 +#if 0 //BMESH_TODO
 +      Object *obedit= CTX_data_edit_object(C);
 +      BMEditMesh *em= EM_GetBMEditMesh(((Mesh *)obedit->data));
 +      BMEdge *eed;
 +      BMEdge **edarray;
 +      int edindex, edfirstcount;
 +      int looptype= RNA_boolean_get(op->ptr, "ring");
 +      
 +      /* sets em->totedgesel */
 +      EM_nedges_selected(em);
 +      
 +      edarray = MEM_mallocN(sizeof(BMEdge*)*em->totedgesel,"edge array");
 +      edindex = 0;
 +      edfirstcount = em->totedgesel;
 +      
 +      for(eed=em->edges.first; eed; eed=eed->next){
 +              if(eed->f&SELECT){
 +                      edarray[edindex] = eed;
 +                      edindex += 1;
 +              }
 +      }
 +      
 +      if(looptype){
 +              for(edindex = 0; edindex < edfirstcount; edindex +=1){
 +                      eed = edarray[edindex];
 +                      edgering_select(em, eed,SELECT);
 +              }
 +              EM_selectmode_flush(em);
 +      }
 +      else{
 +              for(edindex = 0; edindex < edfirstcount; edindex +=1){
 +                      eed = edarray[edindex];
 +                      edgeloop_select(em, eed,SELECT);
 +              }
 +              EM_selectmode_flush(em);
 +      }
 +      MEM_freeN(edarray);
 +//    if (EM_texFaceCheck())
 +      
 +      WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
 +
 +      EM_EndBMEditMesh(obedit->data, em);
 +#endif
 +      return OPERATOR_FINISHED;       
 +}
 +
 +void MESH_OT_loop_multi_select(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name= "Multi Select Loops";
 +      ot->idname= "MESH_OT_loop_multi_select";
 +      
 +      /* api callbacks */
 +      ot->exec= loop_multiselect;
 +      ot->poll= ED_operator_editmesh;
 +      
 +      /* flags */
 +      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 +      
 +      /* properties */
 +      RNA_def_boolean(ot->srna, "ring", 0, "Ring", "");
 +}
 +
 +              
 +/* ***************** MAIN MOUSE SELECTION ************** */
 +
 +
 +/* ***************** loop select (non modal) ************** */
 +
 +static void mouse_mesh_loop(bContext *C, short mval[2], short extend, short ring)
 +{
 +      ViewContext vc;
 +      BMEditMesh *em;
 +      BMEdge *eed;
 +      int select= 1;
 +      int dist= 50;
 +      
 +      em_setup_viewcontext(C, &vc);
 +      vc.mval[0]= mval[0];
 +      vc.mval[1]= mval[1];
 +      em= vc.em;
 +      
 +      eed= EDBM_findnearestedge(&vc, &dist);
 +      if(eed) {
 +              if(extend==0) EDBM_clear_flag_all(em, BM_SELECT);
 +      
 +              if(BM_TestHFlag(em, BM_SELECT)==0) select=1;
 +              else if(extend) select=0;
 +
 +              if(em->selectmode & SCE_SELECT_FACE) {
 +                      walker_select(em, BMW_FACELOOP, eed, select);
 +              }
 +              else if(em->selectmode & SCE_SELECT_EDGE) {
 +                      if(ring)
 +                              edgering_select(em, eed, select);
 +                      else
 +                              walker_select(em, BMW_LOOP, eed, select);
 +              }
 +              else if(em->selectmode & SCE_SELECT_VERTEX) {
 +                      if(ring)
 +                              edgering_select(em, eed, select);
 +                      else 
 +                              walker_select(em, BMW_LOOP, eed, select);
 +              }
 +
 +              EDBM_selectmode_flush(em);
 +//                    if (EM_texFaceCheck())
 +              
 +              WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, vc.obedit);
 +      }
 +}
 +
 +static int mesh_select_loop_invoke(bContext *C, wmOperator *op, wmEvent *event)
 +{
 +      
 +      view3d_operator_needs_opengl(C);
 +      
 +      mouse_mesh_loop(C, event->mval, RNA_boolean_get(op->ptr, "extend"),
 +                                      RNA_boolean_get(op->ptr, "ring"));
 +      
 +      /* cannot do tweaks for as long this keymap is after transform map */
 +      return OPERATOR_FINISHED;
 +}
 +
 +void MESH_OT_loop_select(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name= "Loop Select";
 +      ot->idname= "MESH_OT_loop_select";
 +      
 +      /* api callbacks */
 +      ot->invoke= mesh_select_loop_invoke;
 +      ot->poll= ED_operator_editmesh;
 +      
 +      /* flags */
 +      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 +      
 +      /* properties */
 +      RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
 +      RNA_def_boolean(ot->srna, "ring", 0, "Select Ring", "");
 +}
 +
 +/* ******************* mesh shortest path select, uses prev-selected edge ****************** */
 +
 +/* since you want to create paths with multiple selects, it doesn't have extend option */
 +static void mouse_mesh_shortest_path(bContext *C, short mval[2])
 +{
 +#if 0 //BMESH_TODO
 +      ViewContext vc;
 +      BMEditMesh *em;
 +      BMEdge *eed;
 +      int dist= 50;
 +      
 +      em_setup_viewcontext(C, &vc);
 +      vc.mval[0]= mval[0];
 +      vc.mval[1]= mval[1];
 +      em= vc.em;
 +      
 +      eed= findnearestedge(&vc, &dist);
 +      if(eed) {
 +              Mesh *me= vc.obedit->data;
 +              int path = 0;
 +              
 +              if (em->selected.last) {
 +                      EditSelection *ese = em->selected.last;
 +                      
 +                      if(ese && ese->type == BMEdge) {
 +                              BMEdge *eed_act;
 +                              eed_act = (BMEdge*)ese->data;
 +                              if (eed_act != eed) {
 +                                      if (edgetag_shortest_path(vc.scene, em, eed_act, eed)) {
 +                                              EM_remove_selection(em, eed_act, BMEdge);
 +                                              path = 1;
 +                                      }
 +                              }
 +                      }
 +              }
 +              if (path==0) {
 +                      int act = (edgetag_context_check(vc.scene, eed)==0);
 +                      edgetag_context_set(vc.scene, eed, act); /* switch the edge option */
 +              }
 +              
 +              EM_selectmode_flush(em);
 +
 +              /* even if this is selected it may not be in the selection list */
 +              if(edgetag_context_check(vc.scene, eed)==0)
 +                      EDBM_remove_selection(em, eed);
 +              else
 +                      EDBM_store_selection(em, eed);
 +      
 +              /* force drawmode for mesh */
 +              switch (vc.scene->toolsettings->edge_mode) {
 +                      
 +                      case EDGE_MODE_TAG_SEAM:
 +                              me->drawflag |= ME_DRAWSEAMS;
 +                              break;
 +                      case EDGE_MODE_TAG_SHARP:
 +                              me->drawflag |= ME_DRAWSHARP;
 +                              break;
 +                      case EDGE_MODE_TAG_CREASE:      
 +                              me->drawflag |= ME_DRAWCREASES;
 +                              break;
 +                      case EDGE_MODE_TAG_BEVEL:
 +                              me->drawflag |= ME_DRAWBWEIGHTS;
 +                              break;
 +              }
 +              
 +              DAG_object_flush_update(vc.scene, vc.obedit, OB_RECALC_DATA);
 +      
 +              WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, vc.obedit);
 +      }
 +#endif
 +}
 +
 +
 +static int mesh_shortest_path_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
 +{
 +      
 +      view3d_operator_needs_opengl(C);
 +
 +      mouse_mesh_shortest_path(C, event->mval);
 +      
 +      return OPERATOR_FINISHED;
 +}
 +      
 +void MESH_OT_select_shortest_path(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name= "Shortest Path Select";
 +      ot->idname= "MESH_OT_select_shortest_path";
 +      
 +      /* api callbacks */
 +      ot->invoke= mesh_shortest_path_select_invoke;
 +      ot->poll= ED_operator_editmesh;
 +      
 +      /* flags */
 +      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 +      
 +      /* properties */
 +      RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
 +}
 +
 +
 +/* ************************************************** */
 +/* here actual select happens */
 +/* gets called via generic mouse select operator */
 +void mouse_mesh(bContext *C, short mval[2], short extend)
 +{
 +      ViewContext vc;
 +      BMVert *eve = NULL;
 +      BMEdge *eed = NULL;
 +      BMFace *efa = NULL;
 +      
 +      /* setup view context for argument to callbacks */
 +      em_setup_viewcontext(C, &vc);
 +      vc.mval[0]= mval[0];
 +      vc.mval[1]= mval[1];
 +      
 +      if(unified_findnearest(&vc, &eve, &eed, &efa)) {
 +              
 +              if(extend==0) EDBM_clear_flag_all(vc.em, BM_SELECT);
 +              
 +              if(efa) {
 +                      /* set the last selected face */
 +                      EDBM_set_actFace(vc.em, efa);
 +                      
 +                      if(!BM_TestHFlag(efa, BM_SELECT)) {
 +                              EDBM_store_selection(vc.em, efa);
 +                              BM_Select(vc.em->bm, efa, 1);
 +                      }
 +                      else if(extend) {
 +                              EDBM_remove_selection(vc.em, efa);
 +                              BM_Select(vc.em->bm, efa, 1);
 +                      }
 +              }
 +              else if(eed) {
 +                      if(!BM_TestHFlag(eed, BM_SELECT)) {
 +                              EDBM_store_selection(vc.em, eed);
 +                              BM_Select(vc.em->bm, eed, 1);
 +                      }
 +                      else if(extend) {
 +                              EDBM_remove_selection(vc.em, eed);
 +                              BM_Select(vc.em->bm, eed, 0);
 +                      }
 +              }
 +              else if(eve) {
 +                      if(!BM_TestHFlag(eve, BM_SELECT)) {
 +                              EDBM_store_selection(vc.em, eve);
 +                              BM_Select(vc.em->bm, eve, 1);
 +                      }
 +                      else if(extend){ 
 +                              EDBM_remove_selection(vc.em, eve);
 +                              BM_Select(vc.em->bm, eve, 0);
 +                      }
 +              }
 +              
 +              EDBM_selectmode_flush(vc.em);
 +                
 +//            if (EM_texFaceCheck()) {
 +
 +              if (efa && efa->mat_nr != vc.obedit->actcol-1) {
 +                      vc.obedit->actcol= efa->mat_nr+1;
 +                      vc.em->mat_nr= efa->mat_nr;
 +//                    BIF_preview_changed(ID_MA);
 +              }
 +      }
 +
 +      WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, vc.obedit);
 +}
 +
 +static void EDBM_strip_selections(BMEditMesh *em)
 +{
 +      BMEditSelection *ese, *nextese;
 +
 +      if(!(em->selectmode & SCE_SELECT_VERTEX)){
 +              ese = em->selected.first;
 +              while(ese){
 +                      nextese = ese->next; 
 +                      if(ese->type == BM_VERT) BLI_freelinkN(&(em->selected),ese);
 +                      ese = nextese;
 +              }
 +      }
 +      if(!(em->selectmode & SCE_SELECT_EDGE)){
 +              ese=em->selected.first;
 +              while(ese){
 +                      nextese = ese->next;
 +                      if(ese->type == BM_EDGE) BLI_freelinkN(&(em->selected), ese);
 +                      ese = nextese;
 +              }
 +      }
 +      if(!(em->selectmode & SCE_SELECT_FACE)){
 +              ese=em->selected.first;
 +              while(ese){
 +                      nextese = ese->next;
 +                      if(ese->type == BM_FACE) BLI_freelinkN(&(em->selected), ese);
 +                      ese = nextese;
 +              }
 +      }
 +}
 +
 +/* when switching select mode, makes sure selection is consistant for editing */
 +/* also for paranoia checks to make sure edge or face mode works */
 +void EDBM_selectmode_set(BMEditMesh *em)
 +{
 +      BMVert *eve;
 +      BMEdge *eed;
 +      BMFace *efa;
 +      BMIter iter;
 +      
 +      em->bm->selectmode = em->selectmode;
 +
 +      EDBM_strip_selections(em); /*strip BMEditSelections from em->selected that are not relevant to new mode*/
 +      
 +      if(em->selectmode & SCE_SELECT_VERTEX) {
 +              BMIter iter;
 +              
 +              /*eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
 +              for ( ; eed; eed=BMIter_Step(&iter)) BM_Select(em->bm, eed, 0);
 +              
 +              efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
 +              for ( ; efa; efa=BMIter_Step(&iter)) BM_Select(em->bm, efa, 0);*/
 +
 +              EDBM_selectmode_flush(em);
 +      }
 +      else if(em->selectmode & SCE_SELECT_EDGE) {
 +              /* deselect vertices, and select again based on edge select */
 +              eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
 +              for ( ; eve; eve=BMIter_Step(&iter)) BM_Select(em->bm, eve, 0);
 +              
 +              eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
 +              for ( ; eed; eed=BMIter_Step(&iter)) {
 +                      if (BM_TestHFlag(eed, BM_SELECT))
 +                              BM_Select(em->bm, eed, 1);
 +              }
 +              
 +              /* selects faces based on edge status */
 +              EDBM_selectmode_flush(em);
 +      }
 +      else if(em->selectmode & SCE_SELECT_FACE) {
 +              /* deselect eges, and select again based on face select */
 +              eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
 +              for ( ; eed; eed=BMIter_Step(&iter)) BM_Select(em->bm, eed, 0);
 +              
 +              efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
 +              for ( ; efa; efa=BMIter_Step(&iter)) {
 +                      if (BM_TestHFlag(efa, BM_SELECT))
 +                              BM_Select(em->bm, efa, 1);
 +              }
 +      }
 +}
 +
 +void EDBM_convertsel(BMEditMesh *em, short oldmode, short selectmode)
 +{
 +      BMVert *eve;
 +      BMEdge *eed;
 +      BMFace *efa;
 +      BMIter iter;
 +
 +      /*have to find out what the selectionmode was previously*/
 +      if(oldmode == SCE_SELECT_VERTEX) {
 +              if(selectmode == SCE_SELECT_EDGE) {
 +                      /*select all edges associated with every selected vertex*/
 +                      eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
 +                      for ( ; eed; eed=BMIter_Step(&iter)) {
 +                              if(BM_TestHFlag(eed->v1, BM_SELECT)) BM_Select(em->bm, eed, 1);
 +                              else if(BM_TestHFlag(eed->v2, BM_SELECT)) BM_Select(em->bm, eed, 1);
 +                      }
 +              }               
 +              else if(selectmode == SCE_SELECT_FACE) {
 +                      BMIter liter;
 +                      BMLoop *l;
 +
 +                      /*select all faces associated with every selected vertex*/
 +                      efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
 +                      for ( ; efa; efa=BMIter_Step(&iter)) {
 +                              l = BMIter_New(&liter, em->bm, BM_LOOPS_OF_FACE, efa);
 +                              for (; l; l=BMIter_Step(&liter)) {
 +                                      if (BM_TestHFlag(l->v, BM_SELECT)) {
 +                                              BM_Select(em->bm, efa, 1);
 +                                              break;
 +                                      }
 +                              }
 +                      }
 +              }
 +      }
 +      
 +      if(oldmode == SCE_SELECT_EDGE){
 +              if(selectmode == SCE_SELECT_FACE) {
 +                      BMIter liter;
 +                      BMLoop *l;
 +
 +                      /*select all faces associated with every selected vertex*/
 +                      efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
 +                      for ( ; efa; efa=BMIter_Step(&iter)) {
 +                              l = BMIter_New(&liter, em->bm, BM_LOOPS_OF_FACE, efa);
 +                              for (; l; l=BMIter_Step(&liter)) {
 +                                      if (BM_TestHFlag(l->v, BM_SELECT)) {
 +                                              BM_Select(em->bm, efa, 1);
 +                                              break;
 +                                      }
 +                              }
 +                      }
 +              }
 +      }
 +}
index b3be20b35aa057155a73f665dac1327394550fe1,0000000000000000000000000000000000000000..103bcbcebce388ef254cd13f15b6fc20d26c2524
mode 100644,000000..100644
--- /dev/null
@@@ -1,1145 -1,0 +1,1321 @@@
- #include "BIF_transform.h"
 + /* $Id: bmesh_tools.c
 + *
 + * ***** BEGIN GPL LICENSE BLOCK *****
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software Foundation,
 + * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 + *
 + * The Original Code is Copyright (C) 2004 by Blender Foundation.
 + * All rights reserved.
 + *
 + * The Original Code is: all of this file.
 + *
 + * Contributor(s): Joseph Eagar
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +#include <stdlib.h>
 +#include <stdarg.h>
 +#include <string.h>
 +#include <math.h>
 +#include <float.h>
 +
 +#include "MEM_guardedalloc.h"
 +#include "PIL_time.h"
 +
 +#include "BLO_sys_types.h" // for intptr_t support
 +
 +#include "DNA_mesh_types.h"
 +#include "DNA_material_types.h"
 +#include "DNA_meshdata_types.h"
 +#include "DNA_modifier_types.h"
 +#include "DNA_object_types.h"
 +#include "DNA_scene_types.h"
 +#include "DNA_screen_types.h"
 +#include "DNA_view3d_types.h"
 +#include "DNA_key_types.h"
 +#include "DNA_windowmanager_types.h"
 +
 +#include "RNA_types.h"
 +#include "RNA_define.h"
 +#include "RNA_access.h"
 +
 +#include "BLI_blenlib.h"
 +#include "BLI_arithb.h"
 +#include "BLI_editVert.h"
 +#include "BLI_rand.h"
 +#include "BLI_ghash.h"
 +#include "BLI_linklist.h"
 +#include "BLI_heap.h"
 +
 +#include "BKE_context.h"
 +#include "BKE_customdata.h"
 +#include "BKE_depsgraph.h"
 +#include "BKE_global.h"
 +#include "BKE_library.h"
 +#include "BKE_mesh.h"
 +#include "BKE_object.h"
 +#include "BKE_utildefines.h"
 +#include "BKE_bmesh.h"
 +#include "BKE_report.h"
 +#include "BKE_tessmesh.h"
 +
 +#include "BIF_gl.h"
 +#include "BIF_glutil.h"
 +
 +#include "WM_api.h"
 +#include "WM_types.h"
 +
 +#include "ED_mesh.h"
 +#include "ED_view3d.h"
 +#include "ED_util.h"
 +#include "ED_screen.h"
-               {0, "SIMPLE", "Simple", ""},
-               {1, "MULTI", "Multi", ""},
-               {2, "FRACTAL", "Fractal", ""},
-               {3, "SMOOTH", "Smooth", ""},
++#include "ED_transform.h"
 +
 +#include "UI_interface.h"
 +
 +#include "mesh_intern.h"
 +#include "bmesh.h"
 +
 +static void add_normal_aligned(float *nor, float *add)
 +{
 +      if( INPR(nor, add) < -0.9999f)
 +              VecSubf(nor, nor, add);
 +      else
 +              VecAddf(nor, nor, add);
 +}
 +
++
++static int subdivide_exec(bContext *C, wmOperator *op)
++{
++      Scene *scene = CTX_data_scene(C);
++      Object *obedit= CTX_data_edit_object(C);
++      BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
++      int cuts= RNA_int_get(op->ptr,"number_cuts");
++      float smooth= 0.292f*RNA_float_get(op->ptr, "smoothness");
++      float fractal= RNA_float_get(op->ptr, "fractal")/100;
++      int flag= 0;
++
++      if(smooth != 0.0f)
++              flag |= B_SMOOTH;
++      if(fractal != 0.0f)
++              flag |= B_FRACTAL;
++
++      BM_esubdivideflag(obedit, em->bm, BM_SELECT, smooth, fractal, scene->toolsettings->editbutflag|flag, cuts, 0);
++
++      DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
++      WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
++
++      return OPERATOR_FINISHED;
++}
++
++void MESH_OT_subdivide(wmOperatorType *ot)
++{
++      /* identifiers */
++      ot->name= "Subdivide";
++      ot->idname= "MESH_OT_subdivide";
++
++      /* api callbacks */
++      ot->exec= subdivide_exec;
++      ot->poll= ED_operator_editmesh;
++
++      /* flags */
++      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
++
++      /* properties */
++      RNA_def_int(ot->srna, "number_cuts", 1, 1, 10, "Number of Cuts", "", 1, INT_MAX);
++      RNA_def_float(ot->srna, "fractal", 0.0, 0.0f, FLT_MAX, "Fractal", "Fractal randomness factor.", 0.0f, 1000.0f);
++      RNA_def_float(ot->srna, "smoothness", 0.0f, 0.0f, 1000.0f, "Smoothness", "Smoothness factor.", 0.0f, FLT_MAX);
++}
++
++#if 0
 +static int subdivide_exec(bContext *C, wmOperator *op)
 +{
 +      Object *obedit= CTX_data_edit_object(C);
 +      Scene *scene = CTX_data_scene(C);
 +      BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
 +      
 +      BM_esubdivideflag(obedit, em->bm, 1, 0.0, scene->toolsettings->editbutflag, 1, 0);
 +              
 +      WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
 +
 +      DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 +
 +      return OPERATOR_FINISHED;       
 +}
 +
 +void MESH_OT_subdivide(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name= "Subdivide";
 +      ot->idname= "MESH_OT_subdivide";
 +      
 +      /* api callbacks */
 +      ot->exec= subdivide_exec;
 +      ot->poll= ED_operator_editmesh;
 +      
 +      /* flags */
 +      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 +}
 +
 +static int subdivide_multi_exec(bContext *C, wmOperator *op)
 +{
 +      Object *obedit= CTX_data_edit_object(C);
 +      Scene *scene = CTX_data_scene(C);
 +      BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
 +      
 +      BM_esubdivideflag(obedit, em->bm, 1, 0.0, scene->toolsettings->editbutflag, RNA_int_get(op->ptr,"number_cuts"), 0);
 +              
 +      WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
 +      
 +      DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 +
 +      return OPERATOR_FINISHED;       
 +}
 +
 +void MESH_OT_subdivide_multi(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name= "Subdivide Multi";
 +      ot->idname= "MESH_OT_subdivide_multi";
 +      
 +      /* api callbacks */
 +      ot->exec= subdivide_multi_exec;
 +      ot->poll= ED_operator_editmesh;
 +      
 +      /* flags */
 +      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 +      
 +      /* props */
 +      RNA_def_int(ot->srna, "number_cuts", 4, 1, 100, "Number of Cuts", "", 1, INT_MAX);
 +}
 +
 +static int subdivide_multi_fractal_exec(bContext *C, wmOperator *op)
 +{
 +      Object *obedit= CTX_data_edit_object(C);
 +      Scene *scene = CTX_data_scene(C);
 +      BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
 +
 +      BM_esubdivideflag(obedit, em->bm, 1, -(RNA_float_get(op->ptr, "random_factor")/100), scene->toolsettings->editbutflag, RNA_int_get(op->ptr, "number_cuts"), 0);
 +              
 +      WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
 +      
 +      DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 +
 +      return OPERATOR_FINISHED;       
 +}
 +
 +void MESH_OT_subdivide_multi_fractal(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name= "Subdivide Multi Fractal";
 +      ot->idname= "MESH_OT_subdivide_multi_fractal";
 +      
 +      /* api callbacks */
 +      ot->exec= subdivide_multi_fractal_exec;
 +      ot->poll= ED_operator_editmesh;
 +
 +      /* flags */
 +      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 +      
 +      /* properties */
 +      RNA_def_int(ot->srna, "number_cuts", 4, 1, 100, "Number of Cuts", "", 1, INT_MAX);
 +      RNA_def_float(ot->srna, "random_factor", 5.0, 0.0f, FLT_MAX, "Random Factor", "", 0.0f, 1000.0f);
 +}
 +
 +static int subdivide_smooth_exec(bContext *C, wmOperator *op)
 +{
 +      Object *obedit= CTX_data_edit_object(C);
 +      Scene *scene = CTX_data_scene(C);
 +      BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
 +
 +      BM_esubdivideflag(obedit, em->bm, 1, 0.292f*RNA_float_get(op->ptr, "smoothness"), scene->toolsettings->editbutflag | B_SMOOTH, 1, 0);
 +              
 +      WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
 +      
 +      DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 +
 +      return OPERATOR_FINISHED;       
 +}
 +
 +void MESH_OT_subdivide_smooth(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name= "Subdivide Smooth";
 +      ot->idname= "MESH_OT_subdivide_smooth";
 +      
 +      /* api callbacks */
 +      ot->exec= subdivide_smooth_exec;
 +      ot->poll= ED_operator_editmesh;
 +
 +      /* flags */
 +      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 +      
 +      /* props */
 +      RNA_def_float(ot->srna, "smoothness", 1.0f, 0.0f, 1000.0f, "Smoothness", "", 0.0f, FLT_MAX);
 +}
 +
 +static int subdivs_invoke(bContext *C, wmOperator *op, wmEvent *event)
 +{
 +      uiPopupMenu *pup;
 +      uiLayout *layout;
 +
 +      pup= uiPupMenuBegin(C, "Subdivision Type", 0);
 +      layout= uiPupMenuLayout(pup);
 +      uiItemsEnumO(layout, "MESH_OT_subdivs", "type");
 +      uiPupMenuEnd(C, pup);
 +      
 +      return OPERATOR_CANCELLED;
 +}
 +
 +static int subdivs_exec(bContext *C, wmOperator *op)
 +{     
 +      switch(RNA_int_get(op->ptr, "type"))
 +      {
 +              case 0: // simple
 +                      subdivide_exec(C,op);
 +                      break;
 +              case 1: // multi
 +                      subdivide_multi_exec(C,op);
 +                      break;
 +              case 2: // fractal;
 +                      subdivide_multi_fractal_exec(C,op);
 +                      break;
 +              case 3: //smooth
 +                      subdivide_smooth_exec(C,op);
 +                      break;
 +      }
 +                                       
 +      return OPERATOR_FINISHED;
 +}
 +
 +void MESH_OT_subdivs(wmOperatorType *ot)
 +{
 +      static EnumPropertyItem type_items[]= {
- void EDBM_Extrude_Mesh(Object *obedit, BMEditMesh *em, wmOperator *op)
++              {0, "SIMPLE", 0, "Simple", ""},
++              {1, "MULTI", 0, "Multi", ""},
++              {2, "FRACTAL", 0, "Fractal", ""},
++              {3, "SMOOTH", 0, "Smooth", ""},
 +              {0, NULL, NULL}};
 +
 +      /* identifiers */
 +      ot->name= "subdivs";
 +      ot->idname= "MESH_OT_subdivs";
 +      
 +      /* api callbacks */
 +      ot->invoke= subdivs_invoke;
 +      ot->exec= subdivs_exec;
 +      
 +      ot->poll= ED_operator_editmesh;
 +      
 +      /* flags */
 +      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 +      
 +      /*props */
 +      RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
 +      
 +      /* this is temp, the ops are different, but they are called from subdivs, so all the possible props should be here as well*/
 +      RNA_def_int(ot->srna, "number_cuts", 4, 1, 10, "Number of Cuts", "", 1, INT_MAX);
 +      RNA_def_float(ot->srna, "random_factor", 5.0, 0.0f, FLT_MAX, "Random Factor", "", 0.0f, 1000.0f);
 +      RNA_def_float(ot->srna, "smoothness", 1.0f, 0.0f, 1000.0f, "Smoothness", "", 0.0f, FLT_MAX);            
 +}
++#endif
 +
 +/* individual face extrude */
 +/* will use vertex normals for extrusion directions, so *nor is unaffected */
 +short EDBM_Extrude_face_indiv(BMEditMesh *em, short flag, float *nor)
 +{
 +#if 0
 +      EditVert *eve, *v1, *v2, *v3, *v4;
 +      EditEdge *eed;
 +      EditFace *efa, *nextfa;
 +      
 +      if(em==NULL) return 0;
 +      
 +      /* selected edges with 1 or more selected face become faces */
 +      /* selected faces each makes new faces */
 +      /* always remove old faces, keeps volumes manifold */
 +      /* select the new extrusion, deselect old */
 +      
 +      /* step 1; init, count faces in edges */
 +      recalc_editnormals(em);
 +      
 +      for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;      // new select flag
 +
 +      for(eed= em->edges.first; eed; eed= eed->next) {
 +              eed->f2= 0; // amount of unselected faces
 +      }
 +      for(efa= em->faces.first; efa; efa= efa->next) {
 +              if(efa->f & SELECT);
 +              else {
 +                      efa->e1->f2++;
 +                      efa->e2->f2++;
 +                      efa->e3->f2++;
 +                      if(efa->e4) efa->e4->f2++;
 +              }
 +      }
 +
 +      /* step 2: make new faces from faces */
 +      for(efa= em->faces.last; efa; efa= efa->prev) {
 +              if(efa->f & SELECT) {
 +                      v1= addvertlist(em, efa->v1->co, efa->v1);
 +                      v2= addvertlist(em, efa->v2->co, efa->v2);
 +                      v3= addvertlist(em, efa->v3->co, efa->v3);
 +                      
 +                      v1->f1= v2->f1= v3->f1= 1;
 +                      VECCOPY(v1->no, efa->n);
 +                      VECCOPY(v2->no, efa->n);
 +                      VECCOPY(v3->no, efa->n);
 +                      if(efa->v4) {
 +                              v4= addvertlist(em, efa->v4->co, efa->v4); 
 +                              v4->f1= 1;
 +                              VECCOPY(v4->no, efa->n);
 +                      }
 +                      else v4= NULL;
 +                      
 +                      /* side faces, clockwise */
 +                      addfacelist(em, efa->v2, v2, v1, efa->v1, efa, NULL);
 +                      addfacelist(em, efa->v3, v3, v2, efa->v2, efa, NULL);
 +                      if(efa->v4) {
 +                              addfacelist(em, efa->v4, v4, v3, efa->v3, efa, NULL);
 +                              addfacelist(em, efa->v1, v1, v4, efa->v4, efa, NULL);
 +                      }
 +                      else {
 +                              addfacelist(em, efa->v1, v1, v3, efa->v3, efa, NULL);
 +                      }
 +                      /* top face */
 +                      addfacelist(em, v1, v2, v3, v4, efa, NULL);
 +              }
 +      }
 +      
 +      /* step 3: remove old faces */
 +      efa= em->faces.first;
 +      while(efa) {
 +              nextfa= efa->next;
 +              if(efa->f & SELECT) {
 +                      BLI_remlink(&em->faces, efa);
 +                      free_editface(em, efa);
 +              }
 +              efa= nextfa;
 +      }
 +
 +      /* step 4: redo selection */
 +      EM_clear_flag_all(em, SELECT);
 +      
 +      for(eve= em->verts.first; eve; eve= eve->next) {
 +              if(eve->f1)  eve->f |= SELECT;
 +      }
 +      
 +      EM_select_flush(em);
 +      
 +      return 'n';
 +#endif
 +}
 +
 +
 +/* extrudes individual edges */
 +/* nor is filled with constraint vector */
 +short EDBM_Extrude_edges_indiv(BMEditMesh *em, short flag, float *nor) 
 +{
 +#if 0
 +      EditVert *eve;
 +      EditEdge *eed;
 +      EditFace *efa;
 +      
 +      for(eve= em->verts.first; eve; eve= eve->next) eve->tmp.v = NULL;
 +      for(eed= em->edges.first; eed; eed= eed->next) {
 +              eed->tmp.f = NULL;
 +              eed->f2= ((eed->f & flag)!=0);
 +      }
 +      
 +      set_edge_directions_f2(em, 2);
 +
 +      /* sample for next loop */
 +      for(efa= em->faces.first; efa; efa= efa->next) {
 +              efa->e1->tmp.f = efa;
 +              efa->e2->tmp.f = efa;
 +              efa->e3->tmp.f = efa;
 +              if(efa->e4) efa->e4->tmp.f = efa;
 +      }
 +      /* make the faces */
 +      for(eed= em->edges.first; eed; eed= eed->next) {
 +              if(eed->f & flag) {
 +                      if(eed->v1->tmp.v == NULL)
 +                              eed->v1->tmp.v = addvertlist(em, eed->v1->co, eed->v1);
 +                      if(eed->v2->tmp.v == NULL)
 +                              eed->v2->tmp.v = addvertlist(em, eed->v2->co, eed->v2);
 +
 +                      if(eed->dir==1) 
 +                              addfacelist(em, eed->v1, eed->v2, 
 +                                                      eed->v2->tmp.v, eed->v1->tmp.v, 
 +                                                      eed->tmp.f, NULL);
 +                      else 
 +                              addfacelist(em, eed->v2, eed->v1, 
 +                                                      eed->v1->tmp.v, eed->v2->tmp.v, 
 +                                                      eed->tmp.f, NULL);
 +
 +                      /* for transform */
 +                      if(eed->tmp.f) {
 +                              efa = eed->tmp.f;
 +                              if (efa->f & SELECT) add_normal_aligned(nor, efa->n);
 +                      }
 +              }
 +      }
 +      Normalize(nor);
 +      
 +      /* set correct selection */
 +      EM_clear_flag_all(em, SELECT);
 +      for(eve= em->verts.last; eve; eve= eve->prev) {
 +              if(eve->tmp.v) {
 +                      eve->tmp.v->f |= flag;
 +              }
 +      }
 +
 +      for(eed= em->edges.first; eed; eed= eed->next) {
 +              if(eed->v1->f & eed->v2->f & flag) eed->f |= flag;
 +      }
 +      
 +      if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // g is grab
 +#endif
 +      return 'n';  // n is for normal constraint
 +}
 +
 +/* extrudes individual vertices */
 +short EDBM_Extrude_verts_indiv(BMEditMesh *em, wmOperator *op, short flag, float *nor) 
 +{
 +      BMOperator bmop;
 +      BMOIter siter;
 +      BMVert *v;
 +
 +      EDBM_InitOpf(em, &bmop, op, "extrude_vert_indiv verts=%hv", flag);
 +
 +      /*deselect original verts*/
 +      v = BMO_IterNew(&siter, em->bm, &bmop, "verts", BM_VERT);
 +      for (; v; v=BMO_IterStep(&siter)) {
 +              BM_Select(em->bm, v, 0);
 +      }
 +
 +      BMO_Exec_Op(em->bm, &bmop);
 +
 +      v = BMO_IterNew(&siter, em->bm, &bmop, "vertout", BM_VERT);
 +      for (; v; v=BMO_IterStep(&siter)) {
 +              BM_Select(em->bm, v, 1);
 +      }
 +
 +      if (!EDBM_FinishOp(em, &bmop, op, 1)) return 0;
 +
 +      return 'g'; // g is grab
 +}
 +
 +short EDBM_Extrude_edge(Object *obedit, BMEditMesh *em, int flag, float *nor)
 +{
 +      BMesh *bm = em->bm;
 +      BMIter iter;
 +      BMOIter siter;
 +      BMOperator extop;
 +      BMVert *vert;
 +      BMEdge *edge;
 +      BMFace *f;
 +      ModifierData *md;
 +      BMHeader *el;
 +      
 +      BMO_Init_Op(&extop, "extrudefaceregion");
 +      BMO_HeaderFlag_To_Slot(bm, &extop, "edgefacein",
 +                             flag, BM_VERT|BM_EDGE|BM_FACE);
 +
 +      BM_ITER(vert, &iter, bm, BM_VERTS_OF_MESH, NULL) {
 +              BM_Select(bm, vert, 0);
 +      }
 +
 +      BM_ITER(edge, &iter, bm, BM_EDGES_OF_MESH, NULL) {
 +              BM_Select(bm, edge, 0);
 +      }
 +
 +      BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
 +              BM_Select(bm, f, 0);
 +      }
 +
 +      /* If a mirror modifier with clipping is on, we need to adjust some 
 +       * of the cases above to handle edges on the line of symmetry.
 +       */
 +      md = obedit->modifiers.first;
 +      for (; md; md=md->next) {
 +              if (md->type==eModifierType_Mirror) {
 +                      MirrorModifierData *mmd = (MirrorModifierData*) md;     
 +              
 +                      if(mmd->flag & MOD_MIR_CLIPPING) {
 +                              float mtx[4][4];
 +                              if (mmd->mirror_ob) {
 +                                      float imtx[4][4];
 +                                      Mat4Invert(imtx, mmd->mirror_ob->obmat);
 +                                      Mat4MulMat4(mtx, obedit->obmat, imtx);
 +                              }
 +
 +                              for (edge=BMIter_New(&iter,bm,BM_EDGES_OF_MESH,NULL);
 +                                   edge; edge=BMIter_Step(&iter))
 +                              {
 +                                      if(edge->head.flag & flag) {
 +                                              float co1[3], co2[3];
 +
 +                                              VecCopyf(co1, edge->v1->co);
 +                                              VecCopyf(co2, edge->v2->co);
 +
 +                                              if (mmd->mirror_ob) {
 +                                                      VecMat4MulVecfl(co1, mtx, co1);
 +                                                      VecMat4MulVecfl(co2, mtx, co2);
 +                                              }
 +
 +                                              if (mmd->flag & MOD_MIR_AXIS_X)
 +                                                      if ( (fabs(co1[0]) < mmd->tolerance) &&
 +                                                               (fabs(co2[0]) < mmd->tolerance) )
 +                                                              BMO_Insert_MapPointer(bm, &extop, "exclude", edge, NULL);
 +
 +                                              if (mmd->flag & MOD_MIR_AXIS_Y)
 +                                                      if ( (fabs(co1[1]) < mmd->tolerance) &&
 +                                                               (fabs(co2[1]) < mmd->tolerance) )
 +                                                              BMO_Insert_MapPointer(bm, &extop, "exclude", edge, NULL);
 +
 +                                              if (mmd->flag & MOD_MIR_AXIS_Z)
 +                                                      if ( (fabs(co1[2]) < mmd->tolerance) &&
 +                                                               (fabs(co2[2]) < mmd->tolerance) )
 +                                                              BMO_Insert_MapPointer(bm, &extop, "exclude", edge, NULL);
 +                                      }
 +                              }
 +                      }
 +              }
 +      }
 +
 +      BMO_Exec_Op(bm, &extop);
 +
 +      nor[0] = nor[1] = nor[2] = 0.0f;
 +      
 +      BMO_ITER(el, &siter, bm, &extop, "geomout", BM_ALL) {
 +              BM_Select(bm, el, 1);
 +
 +              if (el->type == BM_FACE) {
 +                      f = (BMFace*)el;
 +                      add_normal_aligned(nor, f->no);
 +              };
 +      }
 +
 +      Normalize(nor);
 +
 +      BMO_Finish_Op(bm, &extop);
 +
 +      if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // grab
 +      return 'n'; // normal constraint 
 +
 +}
 +short EDBM_Extrude_vert(Object *obedit, BMEditMesh *em, short flag, float *nor)
 +{
 +              BMIter iter;
 +              BMEdge *eed;
 +              
 +              /*ensure vert flags are consistent for edge selections*/
 +              eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
 +              for ( ; eed; eed=BMIter_Step(&iter)) {
 +                      if (BM_TestHFlag(eed, flag)) {
 +                              if (flag != BM_SELECT) {
 +                                      BM_SetHFlag(eed->v1, flag);
 +                                      BM_SetHFlag(eed->v2, flag);
 +                              } else {
 +                                      BM_Select(em->bm, eed->v1, 1);
 +                                      BM_Select(em->bm, eed->v2, 1);
 +                              }
 +                      } else {
 +                              if (BM_TestHFlag(eed->v1, flag) && BM_TestHFlag(eed->v2, flag)) {
 +                                      if (flag != BM_SELECT)
 +                                              BM_SetHFlag(eed, flag);
 +                                      else BM_Select(em->bm, eed, 1);
 +                              }
 +                      }
 +              }
 +
 +              return EDBM_Extrude_edge(obedit, em, flag, nor);
 +
 +}
 +
 +static int extrude_repeat_mesh(bContext *C, wmOperator *op)
 +{
 +      Object *obedit= CTX_data_edit_object(C);
 +      Scene *scene = CTX_data_scene(C);
 +      BMEditMesh *em = ((Mesh *)obedit->data)->edit_btmesh;
 +      RegionView3D *rv3d = CTX_wm_region_view3d(C);           
 +              
 +      int steps = RNA_int_get(op->ptr,"steps");
 +      
 +      float offs = RNA_float_get(op->ptr,"offset");
 +
 +      float dvec[3], tmat[3][3], bmat[3][3], nor[3]= {0.0, 0.0, 0.0};
 +      short a;
 +
 +      /* dvec */
 +      dvec[0]= rv3d->persinv[2][0];
 +      dvec[1]= rv3d->persinv[2][1];
 +      dvec[2]= rv3d->persinv[2][2];
 +      Normalize(dvec);
 +      dvec[0]*= offs;
 +      dvec[1]*= offs;
 +      dvec[2]*= offs;
 +
 +      /* base correction */
 +      Mat3CpyMat4(bmat, obedit->obmat);
 +      Mat3Inv(tmat, bmat);
 +      Mat3MulVecfl(tmat, dvec);
 +
 +      for(a=0; a<steps; a++) {
 +              EDBM_Extrude_edge(obedit, em, BM_SELECT, nor);
 +              //BMO_CallOpf(em->bm, "extrudefaceregion edgefacein=%hef", BM_SELECT);
 +              BMO_CallOpf(em->bm, "translate vec=%v verts=%hv", (float*)dvec, BM_SELECT);
 +              //extrudeflag(obedit, em, SELECT, nor);
 +              //translateflag(em, SELECT, dvec);
 +      }
 +      
 +      EDBM_RecalcNormals(em);
 +
 +      WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
 +
 +      DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 +      return OPERATOR_FINISHED;
 +}
 +
 +void MESH_OT_extrude_repeat(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name= "Extrude Repeat Mesh";
 +      ot->idname= "MESH_OT_extrude_repeat";
 +      
 +      /* api callbacks */
 +      ot->exec= extrude_repeat_mesh;
 +      ot->poll= ED_operator_editmesh;
 +      
 +      /* flags */
 +      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 +      
 +      /* props */
 +      RNA_def_float(ot->srna, "offset", 2.0f, 0.0f, 100.0f, "Offset", "", 0.0f, FLT_MAX);
 +      RNA_def_int(ot->srna, "steps", 10, 0, 180, "Steps", "", 0, INT_MAX);
 +}
 +
 +/* generic extern called extruder */
-       float nor[3]= {0.0, 0.0, 0.0};
++int EDBM_Extrude_Mesh(Object *obedit, BMEditMesh *em, wmOperator *op, float *norin)
 +{
 +      Scene *scene= NULL;             // XXX CTX!
-       if(nr<1) return;
 +      short nr, transmode= 0;
++      float stacknor[3] = {0.0f, 0.0f, 0.0f};
++      float *nor = norin ? norin : stacknor;
 +
++      nor[0] = nor[1] = nor[2] = 0.0f;
 +      if(em->selectmode & SCE_SELECT_VERTEX) {
 +              if(em->bm->totvertsel==0) nr= 0;
 +              else if(em->bm->totvertsel==1) nr= 4;
 +              else if(em->bm->totedgesel==0) nr= 4;
 +              else if(em->bm->totfacesel==0) 
 +                      nr= 3; // pupmenu("Extrude %t|Only Edges%x3|Only Vertices%x4");
 +              else if(em->bm->totfacesel==1)
 +                      nr= 1; // pupmenu("Extrude %t|Region %x1|Only Edges%x3|Only Vertices%x4");
 +              else 
 +                      nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3|Only Vertices%x4");
 +      }
 +      else if(em->selectmode & SCE_SELECT_EDGE) {
 +              if (em->bm->totedgesel==0) nr = 0;
 +              
 +              nr = 1;
 +              /*else if (em->totedgesel==1) nr = 3;
 +              else if(em->totfacesel==0) nr = 3;
 +              else if(em->totfacesel==1)
 +                      nr= 1; // pupmenu("Extrude %t|Region %x1|Only Edges%x3");
 +              else
 +                      nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3");
 +              */
 +      }
 +      else {
 +              if (em->bm->totfacesel == 0) nr = 0;
 +              else if (em->bm->totfacesel == 1) nr = 1;
 +              else
 +                      nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2");
 +      }
 +              
++      if(nr<1) return 'g';
 +
 +      if(nr==1 && em->selectmode & SCE_SELECT_VERTEX) 
 +              transmode= EDBM_Extrude_vert(obedit, em, SELECT, nor);
 +      else if (nr == 1) transmode= EDBM_Extrude_edge(obedit, em, SELECT, nor);
 +      else if(nr==4) transmode= EDBM_Extrude_verts_indiv(em, op, SELECT, nor);
 +      else if(nr==3) transmode= EDBM_Extrude_edges_indiv(em, SELECT, nor);
 +      else transmode= EDBM_Extrude_face_indiv(em, SELECT, nor);
 +      
 +      if(transmode==0) {
 +              BKE_report(op->reports, RPT_ERROR, "Not a valid selection for extrude");
 +      }
 +      else {
 +              
 +                      /* We need to force immediate calculation here because 
 +                      * transform may use derived objects (which are now stale).
 +                      *
 +                      * This shouldn't be necessary, derived queries should be
 +                      * automatically building this data if invalid. Or something.
 +                      */
 +//            DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); 
 +              object_handle_update(scene, obedit);
 +
 +              /* individual faces? */
 +//            BIF_TransformSetUndo("Extrude");
 +              if(nr==2) {
 +//                    initTransform(TFM_SHRINKFATTEN, CTX_NO_PET|CTX_NO_MIRROR);
 +//                    Transform();
 +              }
 +              else {
 +//                    initTransform(TFM_TRANSLATION, CTX_NO_PET|CTX_NO_MIRROR);
 +                      if(transmode=='n') {
 +                              Mat4MulVecfl(obedit->obmat, nor);
 +                              VecSubf(nor, nor, obedit->obmat[3]);
 +//                            BIF_setSingleAxisConstraint(nor, "along normal");
 +                      }
 +//                    Transform();
 +              }
 +      }
- // XXX should be a menu item
++      
++      return transmode;
 +}
 +
-       EDBM_Extrude_Mesh(obedit,em, op);
-       
-       RNA_int_set(op->ptr, "mode", TFM_TRANSLATION);
-       WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
 +static int mesh_extrude_invoke(bContext *C, wmOperator *op, wmEvent *event)
 +{
++      Scene *scene= CTX_data_scene(C);
 +      Object *obedit= CTX_data_edit_object(C);
 +      BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
++      int constraint_axis[3] = {0, 0, 1};
++      int tmode;
 +
-       
-       return OPERATOR_FINISHED;       
++      tmode = EDBM_Extrude_Mesh(obedit, em, op, NULL);
 +
++      DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 +      WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
-       EDBM_Extrude_Mesh(obedit, em, op);
++
++      RNA_enum_set(op->ptr, "proportional", 0);
++      RNA_boolean_set(op->ptr, "mirror", 0);
++
++      if (tmode == 'n') {
++              RNA_enum_set(op->ptr, "constraint_orientation", V3D_MANIP_NORMAL);
++              RNA_boolean_set_array(op->ptr, "constraint_axis", constraint_axis);
++      }
++      WM_operator_name_call(C, "TFM_OT_translation", WM_OP_INVOKE_REGION_WIN, op->ptr);
++
++      return OPERATOR_FINISHED;
 +}
 +
 +/* extrude without transform */
 +static int mesh_extrude_exec(bContext *C, wmOperator *op)
 +{
 +      Object *obedit= CTX_data_edit_object(C);
 +      BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
 +      
-       ot->name= "Extrude Mesh";
++      EDBM_Extrude_Mesh(obedit, em, op, NULL);
 +      
 +      WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
 +      
 +      return OPERATOR_FINISHED;       
 +}
 +
 +
 +void MESH_OT_extrude(wmOperatorType *ot)
 +{
 +      /* identifiers */
-       RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
++      ot->name= "Extrude";
 +      ot->idname= "MESH_OT_extrude";
 +      
 +      /* api callbacks */
 +      ot->invoke= mesh_extrude_invoke;
 +      ot->exec= mesh_extrude_exec;
 +      ot->poll= ED_operator_editmesh;
 +      
 +      /* flags */
 +      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 +
 +      /* to give to transform */
-       ot->name= "Select or Deselect All";
++      Properties_Proportional(ot);
++      Properties_Constraints(ot);
++      RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
 +}
 +
 +/* ******************** (de)select all operator **************** */
 +
 +void EDBM_toggle_select_all(BMEditMesh *em) /* exported for UV */
 +{
 +      if(em->bm->totvertsel || em->bm->totedgesel || em->bm->totfacesel)
 +              EDBM_clear_flag_all(em, SELECT);
 +      else 
 +              EDBM_set_flag_all(em, SELECT);
 +}
 +
 +static int toggle_select_all_exec(bContext *C, wmOperator *op)
 +{
 +      Object *obedit= CTX_data_edit_object(C);
 +      BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
 +      
 +      EDBM_toggle_select_all(em);
 +      
 +      WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
 +
 +      return OPERATOR_FINISHED;
 +}
 +
 +void MESH_OT_select_all_toggle(wmOperatorType *ot)
 +{
 +      /* identifiers */
-       {7, "DISSOLVE",         "Dissolve", ""},
-       {10,"VERT",             "Vertices", ""},
-       {1, "EDGE",             "Edges", ""},
-       {2, "FACE",             "Faces", ""},
-       {11, "EDGE_LOOP", "Edge Loop", ""},
-       {4, "EDGE_FACE","Edges & Faces", ""},
-       {5, "ONLY_FACE","Only Faces", ""},
-       {0, NULL, NULL, NULL}
++      ot->name= "Select/Deselect All";
 +      ot->idname= "MESH_OT_select_all_toggle";
 +      
 +      /* api callbacks */
 +      ot->exec= toggle_select_all_exec;
 +      ot->poll= ED_operator_editmesh;
 +      
 +      /* flags */
 +      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 +}
 +
 +/* *************** add-click-mesh (extrude) operator ************** */
 +
 +static int dupli_extrude_cursor(bContext *C, wmOperator *op, wmEvent *event)
 +{
 +      ViewContext vc;
 +      BMVert *eve, *v1;
 +      BMIter iter;
 +      float min[3], max[3];
 +      int done= 0;
 +      
 +      em_setup_viewcontext(C, &vc);
 +      
 +      INIT_MINMAX(min, max);
 +      
 +      BM_ITER(v1, &iter, vc.em->bm, BM_VERTS_OF_MESH, NULL) {
 +              if(BM_TestHFlag(v1, BM_SELECT)) {
 +                      DO_MINMAX(v1->co, min, max);
 +                      done= 1;
 +              }
 +      }
 +
 +      /* call extrude? */
 +      if(done) {
 +              BMEdge *eed;
 +              float vec[3], cent[3], mat[3][3];
 +              float nor[3]= {0.0, 0.0, 0.0};
 +              
 +              /* check for edges that are half selected, use for rotation */
 +              done= 0;
 +              BM_ITER(eed, &iter, vc.em->bm, BM_EDGES_OF_MESH, NULL) {
 +                      if (BM_TestHFlag(eed->v1, BM_SELECT) ^ BM_TestHFlag(eed->v2, BM_SELECT)) {
 +                              if(BM_TestHFlag(eed->v1, BM_SELECT)) 
 +                                      VecSubf(vec, eed->v1->co, eed->v2->co);
 +                              else 
 +                                      VecSubf(vec, eed->v2->co, eed->v1->co);
 +                              VecAddf(nor, nor, vec);
 +                              done= 1;
 +                      }
 +              }
 +              if(done) Normalize(nor);
 +              
 +              /* center */
 +              VecAddf(cent, min, max);
 +              VecMulf(cent, 0.5f);
 +              VECCOPY(min, cent);
 +              
 +              Mat4MulVecfl(vc.obedit->obmat, min);    // view space
 +              view3d_get_view_aligned_coordinate(&vc, min, event->mval);
 +              Mat4Invert(vc.obedit->imat, vc.obedit->obmat); 
 +              Mat4MulVecfl(vc.obedit->imat, min); // back in object space
 +              
 +              VecSubf(min, min, cent);
 +              
 +              /* calculate rotation */
 +              Mat3One(mat);
 +              if(done) {
 +                      float dot;
 +                      
 +                      VECCOPY(vec, min);
 +                      Normalize(vec);
 +                      dot= INPR(vec, nor);
 +
 +                      if( fabs(dot)<0.999) {
 +                              float cross[3], si, q1[4];
 +                              
 +                              Crossf(cross, nor, vec);
 +                              Normalize(cross);
 +                              dot= 0.5f*saacos(dot);
 +                              si= (float)sin(dot);
 +                              q1[0]= (float)cos(dot);
 +                              q1[1]= cross[0]*si;
 +                              q1[2]= cross[1]*si;
 +                              q1[3]= cross[2]*si;
 +                              
 +                              QuatToMat3(q1, mat);
 +                      }
 +              }
 +              
 +
 +              EDBM_Extrude_edge(vc.obedit, vc.em, SELECT, nor);
 +              EDBM_CallOpf(vc.em, op, "rotate verts=%hv cent=%v mat=%m3",
 +                      BM_SELECT, cent, mat);
 +              EDBM_CallOpf(vc.em, op, "translate verts=%hv vec=%v",
 +                      BM_SELECT, min);
 +      }
 +      else {
 +              float *curs= give_cursor(vc.scene, vc.v3d);
 +              BMOperator bmop;
 +              BMOIter oiter;
 +              
 +              VECCOPY(min, curs);
 +
 +              view3d_get_view_aligned_coordinate(&vc, min, event->mval);
 +              Mat4Invert(vc.obedit->imat, vc.obedit->obmat); 
 +              Mat4MulVecfl(vc.obedit->imat, min); // back in object space
 +              
 +              EDBM_InitOpf(vc.em, &bmop, op, "makevert co=%v", min);
 +              BMO_Exec_Op(vc.em->bm, &bmop);
 +
 +              BMO_ITER(v1, &oiter, vc.em->bm, &bmop, "newvertout", BM_VERT) {
 +                      BM_Select(vc.em->bm, v1, 1);
 +              }
 +
 +              if (!EDBM_FinishOp(vc.em, &bmop, op, 1))
 +                      return OPERATOR_CANCELLED;
 +      }
 +
 +      //retopo_do_all();
 +      WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, vc.obedit); 
 +      DAG_object_flush_update(vc.scene, vc.obedit, OB_RECALC_DATA);
 +      
 +      return OPERATOR_FINISHED;
 +}
 +
 +void MESH_OT_dupli_extrude_cursor(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name= "Duplicate or Extrude at 3D Cursor";
 +      ot->idname= "MESH_OT_dupli_extrude_cursor";
 +      
 +      /* api callbacks */
 +      ot->invoke= dupli_extrude_cursor;
 +      ot->poll= ED_operator_editmesh;
 +      
 +      /* flags */
 +      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 +}
 +
 +static int delete_mesh(Object *obedit, wmOperator *op, int event, Scene *scene)
 +{
 +      BMEditMesh *bem = ((Mesh*)obedit->data)->edit_btmesh;
 +      
 +      if(event<1) return OPERATOR_CANCELLED;
 +
 +      if(event==10 ) {
 +              //"Erase Vertices";
 +
 +              if (!EDBM_CallOpf(bem, op, "del geom=%hv context=%i", BM_SELECT, DEL_VERTS))
 +                      return OPERATOR_CANCELLED;
 +      } 
 +      else if(event==11) {
 +              //"Edge Loop"
 +              if (!EDBM_CallOpf(bem, op, "dissolveedgeloop edges=%he", BM_SELECT))
 +                      return OPERATOR_CANCELLED;
 +      }
 +      else if(event==7) {
 +              //"Dissolve"
 +              if (bem->selectmode & SCE_SELECT_FACE) {
 +                      if (!EDBM_CallOpf(bem, op, "dissolvefaces faces=%hf",BM_SELECT))
 +                              return OPERATOR_CANCELLED;
 +              } else if (bem->selectmode & SCE_SELECT_EDGE) {
 +                      if (!EDBM_CallOpf(bem, op, "dissolveedges edges=%he",BM_SELECT))
 +                              return OPERATOR_CANCELLED;
 +              } else if (bem->selectmode & SCE_SELECT_VERTEX) {
 +                      if (!EDBM_CallOpf(bem, op, "dissolveverts verts=%hv",BM_SELECT))
 +                              return OPERATOR_CANCELLED;
 +              }
 +      }
 +      else if(event==4) {
++              //Edges and Faces
 +              if (!EDBM_CallOpf(bem, op, "del geom=%hef context=%i", BM_SELECT, DEL_EDGESFACES))
 +                      return OPERATOR_CANCELLED;
 +      } 
 +      else if(event==1) {
 +              //"Erase Edges"
 +              if (!EDBM_CallOpf(bem, op, "del geom=%he context=%i", BM_SELECT, DEL_EDGES))
 +                      return OPERATOR_CANCELLED;
 +      }
 +      else if(event==2) {
 +              //"Erase Faces";
 +              if (!EDBM_CallOpf(bem, op, "del geom=%hf context=%i", BM_SELECT, DEL_FACES))
 +                      return OPERATOR_CANCELLED;
 +      }
 +      else if(event==5) {
 +              //"Erase Only Faces";
 +              if (!EDBM_CallOpf(bem, op, "del geom=%hf context=%d",
 +                                BM_SELECT, DEL_ONLYFACES))
 +                      return OPERATOR_CANCELLED;
 +      }
 +      
 +      DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 +
 +      return OPERATOR_FINISHED;
 +}
 +
 +/* Note, these values must match delete_mesh() event values */
 +static EnumPropertyItem prop_mesh_delete_types[] = {
-       {1, "VERT", "Vertices", ""},
-       {2, "EDGE", "Edges", ""},
-       {3, "FACE", "Faces", ""},
-       {0, NULL, NULL, NULL}
++      {7, "DISSOLVE",         0, "Dissolve", ""},
++      {10,"VERT",             0, "Vertices", ""},
++      {1, "EDGE",             0, "Edges", ""},
++      {2, "FACE",             0, "Faces", ""},
++      {11, "EDGE_LOOP", 0, "Edge Loop", ""},
++      {4, "EDGE_FACE", 0, "Edges & Faces", ""},
++      {5, "ONLY_FACE", 0, "Only Faces", ""},
++      {0, NULL, 0, NULL, NULL}
 +};
 +
 +static int delete_mesh_exec(bContext *C, wmOperator *op)
 +{
 +      Object *obedit= CTX_data_edit_object(C);
 +      Scene *scene = CTX_data_scene(C);
 +
 +      delete_mesh(obedit, op, RNA_enum_get(op->ptr, "type"), scene);
 +      
 +      WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA|ND_GEOM_SELECT, obedit);
 +      
 +      return OPERATOR_FINISHED;
 +}
 +
 +void MESH_OT_delete(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name= "Delete";
 +      ot->idname= "MESH_OT_delete";
 +      
 +      /* api callbacks */
 +      ot->invoke= WM_menu_invoke;
 +      ot->exec= delete_mesh_exec;
 +      
 +      ot->poll= ED_operator_editmesh;
 +      
 +      /* flags */
 +      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 +      
 +      /*props */
 +      RNA_def_enum(ot->srna, "type", prop_mesh_delete_types, 10, "Type", "Method used for deleting mesh data");
 +}
 +
 +
 +static int addedgeface_mesh_exec(bContext *C, wmOperator *op)
 +{
 +      BMOperator bmop;
 +      Object *obedit= CTX_data_edit_object(C);
 +      BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
 +      
 +      if (!EDBM_InitOpf(em, &bmop, op, "contextual_create geom=%hfev", BM_SELECT))
 +              return OPERATOR_CANCELLED;
 +      
 +      BMO_Exec_Op(em->bm, &bmop);
 +      BMO_HeaderFlag_Buffer(em->bm, &bmop, "faceout", BM_SELECT);
 +
 +      if (!EDBM_FinishOp(em, &bmop, op, 1))
 +              return OPERATOR_CANCELLED;
 +
 +      WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
 +      DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);     
 +      
 +      return OPERATOR_FINISHED;
 +}
 +
 +void MESH_OT_edge_face_add(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name= "Make Edge/Face";
 +      ot->idname= "MESH_OT_edge_face_add";
 +      
 +      /* api callbacks */
 +      ot->exec= addedgeface_mesh_exec;
 +      ot->poll= ED_operator_editmesh;
 +      
 +      /* flags */
 +      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 +      
 +}
 +
 +static EnumPropertyItem prop_mesh_edit_types[] = {
-       CTX_data_scene(C)->selectmode = em->selectmode;
++      {1, "VERT", 0, "Vertices", ""},
++      {2, "EDGE", 0, "Edges", ""},
++      {3, "FACE", 0, "Faces", ""},
++      {0, NULL, 0, NULL, NULL}
 +};
 +
 +static int mesh_selection_type_exec(bContext *C, wmOperator *op)
 +{             
 +      
 +      Object *obedit= CTX_data_edit_object(C);
 +      BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
 +      int type = RNA_enum_get(op->ptr,"type");
 +
 +      switch (type) {
 +              case 1:
 +                      em->selectmode = SCE_SELECT_VERTEX;
 +                      break;
 +              case 2:
 +                      em->selectmode = SCE_SELECT_EDGE;
 +                      break;
 +              case 3:
 +                      em->selectmode = SCE_SELECT_FACE;
 +                      break;
 +      }
 +
 +      EDBM_selectmode_set(em);
++      CTX_data_scene(C)->toolsettings->selectmode = em->selectmode;
 +
 +      WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
 +      
 +      return OPERATOR_FINISHED;
 +}
 +
 +void MESH_OT_selection_type(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name= "Selection Mode";
 +      ot->idname= "MESH_OT_selection_type";
 +      
 +      /* api callbacks */
 +      ot->invoke= WM_menu_invoke;
 +      ot->exec= mesh_selection_type_exec;
 +      
 +      ot->poll= ED_operator_editmesh;
 +      
 +      /* flags */
 +      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 +      
 +      /* props */
 +      RNA_def_enum(ot->srna, "type", prop_mesh_edit_types, 0, "Type", "Set the mesh selection type");
 +      RNA_def_boolean(ot->srna, "inclusive", 0, "Inclusive", "Selects geometry around selected geometry, occording to selection mode");       
 +}
++
++/* ************************* SEAMS AND EDGES **************** */
++
++static int editbmesh_mark_seam(bContext *C, wmOperator *op)
++{
++      Scene *scene = CTX_data_scene(C);
++      Object *obedit= CTX_data_edit_object(C);
++      Mesh *me= ((Mesh *)obedit->data);
++      BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
++      BMesh *bm = em->bm;
++      BMEdge *eed;
++      BMIter iter;
++      int clear = RNA_boolean_get(op->ptr, "clear");
++      
++      /* auto-enable seams drawing */
++      if(clear==0) {
++              me->drawflag |= ME_DRAWSEAMS;
++      }
++
++      if(clear) {
++              BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
++                      if (BM_TestHFlag(eed, BM_HIDDEN) == 0 &&
++                          BM_TestHFlag(eed, BM_SELECT) != 0)
++                      {
++                              BM_ClearHFlag(eed, BM_SEAM);
++                      }
++              }
++      }
++      else {
++              BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
++                      if (BM_TestHFlag(eed, BM_HIDDEN) == 0 &&
++                          BM_TestHFlag(eed, BM_SELECT) != 0)
++                      {
++                              BM_SetHFlag(eed, BM_SEAM);
++                      }
++              }
++      }
++
++      DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
++      WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
++
++      return OPERATOR_FINISHED;
++}
++
++void MESH_OT_mark_seam(wmOperatorType *ot)
++{
++      /* identifiers */
++      ot->name= "Mark Seam";
++      ot->idname= "MESH_OT_mark_seam";
++      
++      /* api callbacks */
++      ot->exec= editbmesh_mark_seam;
++      ot->poll= ED_operator_editmesh;
++      
++      /* flags */
++      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
++      
++      RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
++}
++
++static int editbmesh_mark_sharp(bContext *C, wmOperator *op)
++{
++      Scene *scene = CTX_data_scene(C);
++      Object *obedit= CTX_data_edit_object(C);
++      Mesh *me= ((Mesh *)obedit->data);
++      BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
++      BMesh *bm = em->bm;
++      BMEdge *eed;
++      BMIter iter;
++      int clear = RNA_boolean_get(op->ptr, "clear");
++
++      /* auto-enable sharp edge drawing */
++      if(clear == 0) {
++              me->drawflag |= ME_DRAWSHARP;
++      }
++
++      if(!clear) {
++              BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
++                      if (BM_TestHFlag(eed, BM_HIDDEN) == 0 &&
++                          BM_TestHFlag(eed, BM_SELECT) != 0)
++                      {
++                              BM_SetHFlag(eed, BM_SHARP);
++                      }
++              }
++      } else {
++              BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
++                      if (BM_TestHFlag(eed, BM_HIDDEN) == 0 &&
++                          BM_TestHFlag(eed, BM_SELECT) != 0)
++                      {
++                              BM_ClearHFlag(eed, BM_SHARP);
++                      }
++              }
++      }
++
++
++      DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
++      WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
++
++      return OPERATOR_FINISHED;
++}
++
++void MESH_OT_mark_sharp(wmOperatorType *ot)
++{
++      /* identifiers */
++      ot->name= "Mark Sharp";
++      ot->idname= "MESH_OT_mark_sharp";
++      
++      /* api callbacks */
++      ot->exec= editbmesh_mark_sharp;
++      ot->poll= ED_operator_editmesh;
++      
++      /* flags */
++      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
++      
++      RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
++}
index c90fc95fa51e459dfee126402da4b80a85669173,0000000000000000000000000000000000000000..e3ec1c16ce3254bd92bfcada82fbd9031ea37d83
mode 100644,000000..100644
--- /dev/null
@@@ -1,524 -1,0 +1,523 @@@
- #include "BIF_transform.h"
 + /* $Id: bmeshutils.c
 + *
 + * ***** BEGIN GPL LICENSE BLOCK *****
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software Foundation,
 + * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 + *
 + * The Original Code is Copyright (C) 2004 by Blender Foundation.
 + * All rights reserved.
 + *
 + * The Original Code is: all of this file.
 + *
 + * Contributor(s): Joseph Eagar
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +#include <stdlib.h>
 +#include <stdarg.h>
 +#include <string.h>
 +#include <math.h>
 +#include <float.h>
 +
 +#include "MEM_guardedalloc.h"
 +#include "PIL_time.h"
 +
 +#include "BLO_sys_types.h" // for intptr_t support
 +
 +#include "DNA_mesh_types.h"
 +#include "DNA_material_types.h"
 +#include "DNA_meshdata_types.h"
 +#include "DNA_modifier_types.h"
 +#include "DNA_object_types.h"
 +#include "DNA_scene_types.h"
 +#include "DNA_screen_types.h"
 +#include "DNA_view3d_types.h"
 +#include "DNA_key_types.h"
 +#include "DNA_windowmanager_types.h"
 +
 +#include "RNA_types.h"
 +#include "RNA_define.h"
 +#include "RNA_access.h"
 +
 +#include "BLI_blenlib.h"
 +#include "BLI_arithb.h"
 +#include "BLI_editVert.h"
 +#include "BLI_rand.h"
 +#include "BLI_ghash.h"
 +#include "BLI_linklist.h"
 +#include "BLI_heap.h"
 +
 +#include "BKE_context.h"
 +#include "BKE_customdata.h"
 +#include "BKE_depsgraph.h"
 +#include "BKE_global.h"
 +#include "BKE_library.h"
 +#include "BKE_mesh.h"
 +#include "BKE_object.h"
 +#include "BKE_utildefines.h"
 +#include "BKE_bmesh.h"
 +#include "BKE_report.h"
 +#include "BKE_tessmesh.h"
 +
 +#include "BIF_gl.h"
 +#include "BIF_glutil.h"
 +
 +#include "WM_api.h"
 +#include "WM_types.h"
 +
 +#include "ED_mesh.h"
 +#include "ED_view3d.h"
 +#include "ED_util.h"
 +#include "ED_screen.h"
-       me->edit_btmesh->selectmode = scene->selectmode;
 +
 +#include "UI_interface.h"
 +
 +#include "mesh_intern.h"
 +#include "bmesh.h"
 +
 +void EDBM_RecalcNormals(BMEditMesh *em)
 +{
 +      BM_Compute_Normals(em->bm);
 +}
 +
 +void EDBM_stats_update(BMEditMesh *em)
 +{
 +      BMIter iter;
 +      BMHeader *ele;
 +      int types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
 +      int *tots[3];
 +      int i;
 +
 +      tots[0] = &em->bm->totvertsel;
 +      tots[1] = &em->bm->totedgesel;
 +      tots[2] = &em->bm->totfacesel;
 +      
 +      em->bm->totvertsel = em->bm->totedgesel = em->bm->totfacesel = 0;
 +
 +      for (i=0; i<3; i++) {
 +              ele = BMIter_New(&iter, em->bm, types[i], NULL);
 +              for ( ; ele; ele=BMIter_Step(&iter)) {
 +                      if (BM_TestHFlag(ele, BM_SELECT)) {
 +                              *tots[i]++;
 +                      }
 +              }
 +      }
 +}
 +
 +/*this function is defunct, dead*/
 +void EDBM_Tesselate(EditMesh *em)
 +{
 +      EditMesh *em2;
 +      EditFace *efa;
 +      BMesh *bm;
 +      int found=0;
 +      
 +      for (efa=em->faces.first; efa; efa=efa->next) {
 +              if ((efa->e1->h & EM_FGON) || (efa->e2->h & EM_FGON) ||
 +                  (efa->e3->h & EM_FGON) || (efa->e4&&(efa->e4->h&EM_FGON)))
 +              {
 +                      found = 1;
 +                      break;
 +              }
 +      }
 +
 +      if (found) {
 +              bm = editmesh_to_bmesh(em);
 +              em2 = bmesh_to_editmesh(bm);
 +              set_editMesh(em, em2);
 +
 +              MEM_freeN(em2);
 +              BM_Free_Mesh(bm);
 +      }
 +}
 +
 +int EDBM_InitOpf(BMEditMesh *em, BMOperator *bmop, wmOperator *op, char *fmt, ...)
 +{
 +      BMesh *bm = em->bm;
 +      va_list list;
 +
 +      va_start(list, fmt);
 +
 +      if (!BMO_VInitOpf(bm, bmop, fmt, list)) {
 +              BKE_report(op->reports, RPT_ERROR,
 +                         "Parse error in EDBM_CallOpf");
 +              va_end(list);
 +              return 0;
 +      }
 +
 +      em->emcopy = BMEdit_Copy(em);
 +
 +      va_end(list);
 +}
 +
 +
 +/*returns 0 on error, 1 on success.  executes and finishes a bmesh operator*/
 +int EDBM_FinishOp(BMEditMesh *em, BMOperator *bmop, wmOperator *op, int report) {
 +      char *errmsg;
 +      
 +      BMO_Finish_Op(em->bm, bmop);
 +
 +      if (BMO_GetError(em->bm, &errmsg, NULL)) {
 +              BMEditMesh *emcopy = em->emcopy;
 +
 +              if (report) BKE_report(op->reports, RPT_ERROR, errmsg);
 +
 +              BMEdit_Free(em);
 +              *em = *emcopy;
 +
 +              MEM_freeN(emcopy);
 +              return 0;
 +      } else {
 +              BMEdit_Free(em->emcopy);
 +              MEM_freeN(em->emcopy);
 +              em->emcopy = NULL;
 +      }
 +
 +      return 1;
 +}
 +
 +int EDBM_CallOpf(BMEditMesh *em, wmOperator *op, char *fmt, ...)
 +{
 +      BMesh *bm = em->bm;
 +      BMOperator bmop;
 +      va_list list;
 +
 +      va_start(list, fmt);
 +
 +      if (!BMO_VInitOpf(bm, &bmop, fmt, list)) {
 +              BKE_report(op->reports, RPT_ERROR,
 +                         "Parse error in EDBM_CallOpf");
 +              va_end(list);
 +              return 0;
 +      }
 +
 +      em->emcopy = BMEdit_Copy(em);
 +
 +      BMO_Exec_Op(bm, &bmop);
 +
 +      va_end(list);
 +      return EDBM_FinishOp(em, &bmop, op, 1);
 +}
 +
 +int EDBM_CallOpfSilent(BMEditMesh *em, char *fmt, ...)
 +{
 +      BMesh *bm = em->bm;
 +      BMOperator bmop;
 +      va_list list;
 +
 +      va_start(list, fmt);
 +
 +      if (!BMO_VInitOpf(bm, &bmop, fmt, list)) {
 +              va_end(list);
 +              return 0;
 +      }
 +
 +      em->emcopy = BMEdit_Copy(em);
 +
 +      BMO_Exec_Op(bm, &bmop);
 +
 +      va_end(list);
 +      return EDBM_FinishOp(em, &bmop, NULL, 0);
 +}
 +
 +void EDBM_MakeEditBMesh(Scene *scene, Object *ob)
 +{
 +      Mesh *me = ob->data;
 +      EditMesh *em;
 +      BMesh *bm;
 +
 +      if (!me->mpoly && me->totface) {
 +              em = make_editMesh(scene, ob);
 +              bm = editmesh_to_bmesh(em);
 +      
 +              free_editMesh(em);
 +      } else {
 +              bm = BKE_mesh_to_bmesh(me);
 +      }
 +
 +      me->edit_btmesh = BMEdit_Create(bm);
++      me->edit_btmesh->selectmode = scene->toolsettings->selectmode;
 +}
 +
 +void EDBM_LoadEditBMesh(Scene *scene, Object *ob)
 +{
 +      Mesh *me = ob->data;
 +      BMesh *bm = me->edit_btmesh->bm;
 +
 +      BMO_CallOpf(bm, "object_load_bmesh scene=%p object=%p", scene, ob);
 +
 +#if 0
 +      EditMesh *em = bmesh_to_editmesh(me->edit_btmesh->bm);
 +      
 +      load_editMesh(scene, ob, em);
 +      free_editMesh(em);
 +      MEM_freeN(em);
 +#endif
 +}
 +
 +void EDBM_FreeEditBMesh(BMEditMesh *tm)
 +{
 +      BMEdit_Free(tm);
 +}
 +
 +void EDBM_init_index_arrays(BMEditMesh *tm, int forvert, int foredge, int forface)
 +{
 +      EDBM_free_index_arrays(tm);
 +
 +      if (forvert) {
 +              BMIter iter;
 +              BMVert *ele;
 +              int i=0;
 +              
 +              tm->vert_index = MEM_mallocN(sizeof(void**)*tm->bm->totvert, "tm->vert_index");
 +
 +              ele = BMIter_New(&iter, tm->bm, BM_VERTS_OF_MESH, NULL);
 +              for ( ; ele; ele=BMIter_Step(&iter)) {
 +                      tm->vert_index[i++] = ele;
 +              }
 +      }
 +
 +      if (foredge) {
 +              BMIter iter;
 +              BMEdge *ele;
 +              int i=0;
 +              
 +              tm->edge_index = MEM_mallocN(sizeof(void**)*tm->bm->totedge, "tm->edge_index");
 +
 +              ele = BMIter_New(&iter, tm->bm, BM_EDGES_OF_MESH, NULL);
 +              for ( ; ele; ele=BMIter_Step(&iter)) {
 +                      tm->edge_index[i++] = ele;
 +              }
 +      }
 +
 +      if (forface) {
 +              BMIter iter;
 +              BMFace *ele;
 +              int i=0;
 +              
 +              tm->face_index = MEM_mallocN(sizeof(void**)*tm->bm->totface, "tm->face_index");
 +
 +              ele = BMIter_New(&iter, tm->bm, BM_FACES_OF_MESH, NULL);
 +              for ( ; ele; ele=BMIter_Step(&iter)) {
 +                      tm->face_index[i++] = ele;
 +              }
 +      }
 +}
 +
 +void EDBM_free_index_arrays(BMEditMesh *tm)
 +{
 +      if (tm->vert_index) {
 +              MEM_freeN(tm->vert_index);
 +              tm->vert_index = NULL;
 +      }
 +
 +      if (tm->edge_index) {
 +              MEM_freeN(tm->edge_index);
 +              tm->edge_index = NULL;
 +      }
 +
 +      if (tm->face_index) {
 +              MEM_freeN(tm->face_index);
 +              tm->face_index = NULL;
 +      }
 +}
 +
 +BMVert *EDBM_get_vert_for_index(BMEditMesh *tm, int index)
 +{
 +      return tm->vert_index?tm->vert_index[index]:NULL;
 +}
 +
 +BMEdge *EDBM_get_edge_for_index(BMEditMesh *tm, int index)
 +{
 +      return tm->edge_index?tm->edge_index[index]:NULL;
 +}
 +
 +BMFace *EDBM_get_face_for_index(BMEditMesh *tm, int index)
 +{
 +      return tm->face_index?tm->face_index[index]:NULL;
 +}
 +
 +/* this replaces the active flag used in uv/face mode */
 +void EDBM_set_actFace(BMEditMesh *em, BMFace *efa)
 +{
 +      em->bm->act_face = efa;
 +}
 +
 +BMFace *EDBM_get_actFace(BMEditMesh *em, int sloppy)
 +{
 +      if (em->bm->act_face) {
 +              return em->bm->act_face;
 +      } else if (sloppy) {
 +              BMFace *efa= NULL;
 +              BMEditSelection *ese;
 +              
 +              ese = em->selected.last;
 +              for (; ese; ese=ese->prev){
 +                      if(ese->type == BM_FACE) {
 +                              efa = (BMFace *)ese->data;
 +                              
 +                              if (BM_TestHFlag(efa, BM_HIDDEN)) efa= NULL;
 +                              else break;
 +                      }
 +              }
 +              if (efa==NULL) {
 +                      BMIter iter;
 +                      efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
 +                      for ( ; efa; efa=BMIter_Step(&iter)) {
 +                              if (BM_TestHFlag(efa, BM_SELECT))
 +                                      break;
 +                      }
 +              }
 +              return efa; /* can still be null */
 +      }
 +      return NULL;
 +
 +}
 +
 +void EDBM_selectmode_flush(BMEditMesh *em)
 +{
 +      em->bm->selectmode = em->selectmode;
 +      BM_SelectMode_Flush(em->bm);
 +}
 +
 +
 +int EDBM_get_actSelection(BMEditMesh *em, BMEditSelection *ese)
 +{
 +      BMEditSelection *ese_last = em->selected.last;
 +      BMFace *efa = EDBM_get_actFace(em, 0);
 +
 +      ese->next = ese->prev = NULL;
 +      
 +      if (ese_last) {
 +              if (ese_last->type == BM_FACE) { /* if there is an active face, use it over the last selected face */
 +                      if (efa) {
 +                              ese->data = (void *)efa;
 +                      } else {
 +                              ese->data = ese_last->data;
 +                      }
 +                      ese->type = BM_FACE;
 +              } else {
 +                      ese->data = ese_last->data;
 +                      ese->type = ese_last->type;
 +              }
 +      } else if (efa) { /* no */
 +              ese->data = (void *)efa;
 +              ese->type = BM_FACE;
 +      } else {
 +              ese->data = NULL;
 +              return 0;
 +      }
 +      return 1;
 +}
 +
 +void EDBM_clear_flag_all(BMEditMesh *em, int flag)
 +{
 +      BMIter iter;
 +      BMHeader *ele;
 +      int i, type;
 +
 +      for (i=0; i<3; i++) {
 +              switch (i) {
 +                      case 0:
 +                              type = BM_VERTS_OF_MESH;
 +                              break;
 +                      case 1:
 +                              type = BM_EDGES_OF_MESH;
 +                              break;
 +                      case 2:
 +                              type = BM_FACES_OF_MESH;
 +                              break;
 +              }
 +              ele = BMIter_New(&iter, em->bm, type, NULL);
 +              for ( ; ele; ele=BMIter_Step(&iter)) {
 +                      if (flag & BM_SELECT) BM_Select(em->bm, ele, 0);
 +                      BM_ClearHFlag(ele, flag);
 +              }
 +      }
 +}
 +
 +
 +void EDBM_set_flag_all(BMEditMesh *em, int flag)
 +{
 +      BMIter iter;
 +      BMHeader *ele;
 +      int i, type;
 +
 +      for (i=0; i<3; i++) {
 +              switch (i) {
 +                      case 0:
 +                              type = BM_VERTS_OF_MESH;
 +                              break;
 +                      case 1:
 +                              type = BM_EDGES_OF_MESH;
 +                              break;
 +                      case 2:
 +                              type = BM_FACES_OF_MESH;
 +                              break;
 +              }
 +              ele = BMIter_New(&iter, em->bm, type, NULL);
 +              for ( ; ele; ele=BMIter_Step(&iter)) {
 +                      if (flag & BM_SELECT) BM_Select(em->bm, ele, 1);
 +                      BM_SetHFlag(ele, flag);
 +              }
 +      }
 +}
 +
 +/**************-------------- Undo ------------*****************/
 +
 +/* for callbacks */
 +
 +static void *getEditMesh(bContext *C)
 +{
 +      Object *obedit= CTX_data_edit_object(C);
 +      if(obedit && obedit->type==OB_MESH) {
 +              Mesh *me= obedit->data;
 +              return me->edit_btmesh;
 +      }
 +      return NULL;
 +}
 +
 +/*undo simply makes copies of a bmesh*/
 +static void *editbtMesh_to_undoMesh(void *emv)
 +{
 +      /*we recalc the tesselation here, to avoid seeding calls to
 +        BMEdit_RecalcTesselation throughout the code.*/
 +      BMEdit_RecalcTesselation(emv);
 +
 +      return BMEdit_Copy(emv);
 +}
 +
 +static void undoMesh_to_editbtMesh(void *umv, void *emv)
 +{
 +      BMEditMesh *bm1 = umv, *bm2 = emv;
 +
 +      BMEdit_Free(bm2);
 +
 +      *bm2 = *BMEdit_Copy(bm1);
 +}
 +
 +
 +static void free_undo(void *umv)
 +{
 +      BMEditMesh *em = umv;
 +
 +      BMEdit_Free(em);
 +}
 +
 +/* and this is all the undo system needs to know */
 +void undo_push_mesh(bContext *C, char *name)
 +{
 +      undo_editmode_push(C, name, getEditMesh, free_undo, undoMesh_to_editbtMesh, editbtMesh_to_undoMesh, NULL);
 +}
index 5cf0a0b1de6bf5f295caf7890e1aaa38539063d7,6c66ae468fa5597d8a9370a4727a100e2f77b067..49872eae8972335161c697e9275dab893c43ae65
@@@ -796,9 -833,15 +796,9 @@@ EditMesh *make_editMesh(Scene *scene, O
        float cacheco[3], cachemat[4][4], *co;
        int tot, a, cacheedit= 0, eekadoodle= 0;
  
 -      if(me->edit_mesh==NULL)
 -              me->edit_mesh= MEM_callocN(sizeof(EditMesh), "editmesh");
 -      else 
 -              /* because of reload */
 -              free_editMesh(me->edit_mesh);
 -      
 -      em= me->edit_mesh;
 +      em= MEM_callocN(sizeof(EditMesh), "editmesh");
        
-       em->selectmode= scene->selectmode; // warning needs to be synced
+       em->selectmode= scene->toolsettings->selectmode; // warning needs to be synced
        em->act_face = NULL;
        em->totvert= tot= me->totvert;
        em->totedge= me->totedge;
index 405d2a19d414bbd99734b56062720cdf4aa2eb08,c24670aa8564fbee2c69189aeb5b07799dfee1a5..4b891843f5e8bdbe1eb1fcb00a52f8a07b66916a
  #include "BKE_object.h"
  #include "BKE_utildefines.h"
  #include "BKE_report.h"
 +#include "BKE_tessmesh.h"
  
- #include "BIF_retopo.h"
  #include "WM_api.h"
  #include "WM_types.h"
  
  #include "ED_mesh.h"
+ #include "ED_retopo.h"
+ #include "ED_screen.h"
+ #include "ED_transform.h"
  #include "ED_util.h"
  #include "ED_view3d.h"
- #include "ED_screen.h"
  
 +#include "bmesh.h"
 +
  #include "mesh_intern.h"
  
  /* bpymenu removed XXX */
@@@ -1001,7 -1104,7 +1001,9 @@@ static void make_prim(Object *obedit, i
                        }
  
                        dia*=200;
-                       for(a=1; a<subdiv; a++) esubdivideflag(obedit, em, 2, dia, 0,1,0);
 -                      for(a=1; a<subdiv; a++) esubdivideflag(obedit, em, 2, dia, 0, B_SPHERE,1,0);
++
++                      for(a=1; a<subdiv; a++) esubdivideflag(obedit, em, 2, dia, 0.0, 0, 1, 0);
++                      
                        /* and now do imat */
                        eve= em->verts.first;
                        while(eve) {
index 7f1d56aee73df22dce000ea02e55498dc006afc0,7fc3753eefb5285dee5a1823967b697ac2d79074..9b5de48a644099ec8a6f2dc912d3f27f729bd9bb
@@@ -784,14 -624,12 +784,15 @@@ static float bm_seg_intersect(BMEdge *e
  
  static int knife_cut_exec(bContext *C, wmOperator *op)
  {
+       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;
 +      BMesh *bm = em->bm;
        ARegion *ar= CTX_wm_region(C);
 -      EditEdge *eed;
 -      EditVert *eve;
 +      BMVert *bv;
 +      BMIter iter;
 +      BMEdge **edges = NULL, *be;
 +      BMOperator bmop;
        CutCurve curve[MAX_CUTS];
        struct GHash *gh;
        float isect=0.0;
                co[3]= 1.0;
                Mat4MulVec4fl(obedit->obmat, co);
                project_float(ar, co, scr);
 -              BLI_ghash_insert(gh, eve, scr);
 -              eve->f1 = 0; /*store vertex intersection flag here*/
 -      
 +              BLI_ghash_insert(gh, bv, scr);
        }
        
 -      eed= em->edges.first;           
 -      while(eed) {    
 -              if( eed->v1->f & eed->v2->f & SELECT ){         // NOTE: uses vertex select, subdiv doesnt do edges yet
 -                      isect= seg_intersect(eed, curve, len, mode, gh);
 -                      if (isect!=0.0f) eed->f2= 1;
 -                      else eed->f2=0;
 -                      eed->tmp.fp= isect;
 -                      //printf("isect=%i\n", isect);
 -              }
 -              else {
 -                      eed->f2=0;
 -                      eed->f1=0;
 +      BMO_Init_Op(&bmop, "esubd");
 +      
 +      i = 0;
 +      /*store percentage of edge cut for KNIFE_EXACT here.*/
 +      for (be=BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); be; be=BMIter_Step(&iter)) {
 +              if( BM_Is_Selected(bm, be) ) {
 +                      isect= bm_seg_intersect(be, curve, len, mode, gh, &isected);
 +                      
 +                      if (isect != 0.0f) {
-                               if (mode != KNIFE_MULTICUT) {
++                              if (mode != KNIFE_MULTICUT && mode != KNIFE_MIDPOINT) {
 +                                      BMO_Insert_MapFloat(bm, &bmop, 
 +                                             "edgepercents",
 +                                             be, isect);
 +
 +                              }
 +                              BMO_SetFlag(bm, be, 1);
 +                      }
                }
 -              eed= eed->next;
        }
        
 -      if (mode==KNIFE_MIDPOINT) esubdivideflag(obedit, em, SELECT, 0, 0, B_KNIFE, 1, SUBDIV_SELECT_ORIG);
 -      else if (mode==KNIFE_MULTICUT) esubdivideflag(obedit, em, SELECT, 0, 0, B_KNIFE, numcuts, SUBDIV_SELECT_ORIG);
 -      else esubdivideflag(obedit, em, SELECT, 0, 0, B_KNIFE|B_PERCENTSUBD, 1, SUBDIV_SELECT_ORIG);
 +      BMO_Flag_To_Slot(bm, &bmop, "edges", 1, BM_EDGE);
  
 -      eed=em->edges.first;
 -      while(eed){
 -              eed->f2=0;
 -              eed->f1=0;
 -              eed=eed->next;
 -      }       
 +      BMO_Set_Int(&bmop, "numcuts", numcuts);
 +      flag = B_KNIFE;
 +      if (mode == KNIFE_MIDPOINT) numcuts = 1;
 +      BMO_Set_Int(&bmop, "flag", flag);
 +      BMO_Set_Float(&bmop, "radius", 0);
        
 -      BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN);
 +      BMO_Exec_Op(bm, &bmop);
 +      BMO_Finish_Op(bm, &bmop);
        
 -      BKE_mesh_end_editmesh(obedit->data, em);
 +      V_FREE(edges);
 +      V_FREE(percents);
 +
 +      //if (mode==KNIFE_MIDPOINT) esubdivideflag(obedit, em, SELECT, 0, B_KNIFE, 1, SUBDIV_SELECT_ORIG);
 +      //else if (mode==KNIFE_MULTICUT) esubdivideflag(obedit, em, SELECT, 0, B_KNIFE, numcuts, SUBDIV_SELECT_ORIG);
 +      //else esubdivideflag(obedit, em, SELECT, 0, B_KNIFE|B_PERCENTSUBD, 1, SUBDIV_SELECT_ORIG);
 +      
 +      BLI_ghash_free(gh, NULL, (GHashValFreeFP)WMEM_freeN);
 +
+       DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
        return OPERATOR_FINISHED;
  }
  
index 23f8d5364d652591185272eb3f17c170e9366c54,5fc2ce467921a9299bd222d5bc5df9ff57996a77..aa7a5e6b2925568d3b97bc5d0f7682a5f73b0f4d
@@@ -329,28 -326,341 +329,27 @@@ int EM_init_backbuf_circle(ViewContext 
        
  }
  
 -static void findnearestvert__doClosest(void *userData, EditVert *eve, int x, int y, int index)
 -{
 -      struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; EditVert *closest; } *data = userData;
 -
 -      if (data->pass==0) {
 -              if (index<=data->lastIndex)
 -                      return;
 -      } else {
 -              if (index>data->lastIndex)
 -                      return;
 -      }
 -
 -      if (data->dist>3) {
 -              int temp = abs(data->mval[0] - x) + abs(data->mval[1]- y);
 -              if ((eve->f&1) == data->select) {
 -                      if (data->strict == 1)
 -                              return;
 -                      else
 -                              temp += 5;
 -              }
 -
 -              if (temp<data->dist) {
 -                      data->dist = temp;
 -                      data->closest = eve;
 -                      data->closestIndex = index;
 -              }
 -      }
 -}
 -
 -
 -
 -
 -static unsigned int findnearestvert__backbufIndextest(void *handle, unsigned int index)
 -{
 -      EditMesh *em= (EditMesh *)handle;
 -      EditVert *eve = BLI_findlink(&em->verts, index-1);
 -
 -      if(eve && (eve->f & SELECT)) return 0;
 -      return 1; 
 -}
 -/**
 - * findnearestvert
 - * 
 - * dist (in/out): minimal distance to the nearest and at the end, actual distance
 - * sel: selection bias
 - *            if SELECT, selected vertice are given a 5 pixel bias to make them farter than unselect verts
 - *            if 0, unselected vertice are given the bias
 - * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased 
 - */
 -EditVert *findnearestvert(ViewContext *vc, int *dist, short sel, short strict)
 -{
 -      if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)){
 -              int distance;
 -              unsigned int index;
 -              EditVert *eve;
 -              
 -              if(strict) index = view3d_sample_backbuf_rect(vc, vc->mval, 50, em_wireoffs, 0xFFFFFF, &distance, strict, vc->em, findnearestvert__backbufIndextest); 
 -              else index = view3d_sample_backbuf_rect(vc, vc->mval, 50, em_wireoffs, 0xFFFFFF, &distance, 0, NULL, NULL); 
 -              
 -              eve = BLI_findlink(&vc->em->verts, index-1);
 -              
 -              if(eve && distance < *dist) {
 -                      *dist = distance;
 -                      return eve;
 -              } else {
 -                      return NULL;
 -              }
 -                      
 -      }
 -      else {
 -              struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; EditVert *closest; } data;
 -              static int lastSelectedIndex=0;
 -              static EditVert *lastSelected=NULL;
 -
 -              if (lastSelected && BLI_findlink(&vc->em->verts, lastSelectedIndex)!=lastSelected) {
 -                      lastSelectedIndex = 0;
 -                      lastSelected = NULL;
 -              }
 -
 -              data.lastIndex = lastSelectedIndex;
 -              data.mval[0] = vc->mval[0];
 -              data.mval[1] = vc->mval[1];
 -              data.select = sel;
 -              data.dist = *dist;
 -              data.strict = strict;
 -              data.closest = NULL;
 -              data.closestIndex = 0;
 -
 -              data.pass = 0;
 -              mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, 1);
 -
 -              if (data.dist>3) {
 -                      data.pass = 1;
 -                      mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, 1);
 -              }
 -
 -              *dist = data.dist;
 -              lastSelected = data.closest;
 -              lastSelectedIndex = data.closestIndex;
 -
 -              return data.closest;
 -      }
 -}
 -
 -/* returns labda for closest distance v1 to line-piece v2-v3 */
 -static float labda_PdistVL2Dfl( float *v1, float *v2, float *v3) 
 -{
 -      float rc[2], len;
 -      
 -      rc[0]= v3[0]-v2[0];
 -      rc[1]= v3[1]-v2[1];
 -      len= rc[0]*rc[0]+ rc[1]*rc[1];
 -      if(len==0.0f)
 -              return 0.0f;
 -      
 -      return ( rc[0]*(v1[0]-v2[0]) + rc[1]*(v1[1]-v2[1]) )/len;
 -}
 -
 -/* note; uses v3d, so needs active 3d window */
 -static void findnearestedge__doClosest(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index)
 -{
 -      struct { ViewContext vc; float mval[2]; int dist; EditEdge *closest; } *data = userData;
 -      float v1[2], v2[2];
 -      int distance;
 -              
 -      v1[0] = x0;
 -      v1[1] = y0;
 -      v2[0] = x1;
 -      v2[1] = y1;
 -              
 -      distance= PdistVL2Dfl(data->mval, v1, v2);
 -              
 -      if(eed->f & SELECT) distance+=5;
 -      if(distance < data->dist) {
 -              if(data->vc.rv3d->rflag & RV3D_CLIPPING) {
 -                      float labda= labda_PdistVL2Dfl(data->mval, v1, v2);
 -                      float vec[3];
 -
 -                      vec[0]= eed->v1->co[0] + labda*(eed->v2->co[0] - eed->v1->co[0]);
 -                      vec[1]= eed->v1->co[1] + labda*(eed->v2->co[1] - eed->v1->co[1]);
 -                      vec[2]= eed->v1->co[2] + labda*(eed->v2->co[2] - eed->v1->co[2]);
 -                      Mat4MulVecfl(data->vc.obedit->obmat, vec);
 -
 -                      if(view3d_test_clipping(data->vc.rv3d, vec)==0) {
 -                              data->dist = distance;
 -                              data->closest = eed;
 -                      }
 -              }
 -              else {
 -                      data->dist = distance;
 -                      data->closest = eed;
 -              }
 -      }
 -}
 -EditEdge *findnearestedge(ViewContext *vc, int *dist)
 -{
 -
 -      if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
 -              int distance;
 -              unsigned int index = view3d_sample_backbuf_rect(vc, vc->mval, 50, em_solidoffs, em_wireoffs, &distance,0, NULL, NULL);
 -              EditEdge *eed = BLI_findlink(&vc->em->edges, index-1);
 -
 -              if (eed && distance<*dist) {
 -                      *dist = distance;
 -                      return eed;
 -              } else {
 -                      return NULL;
 -              }
 -      }
 -      else {
 -              struct { ViewContext vc; float mval[2]; int dist; EditEdge *closest; } data;
 -
 -              data.vc= *vc;
 -              data.mval[0] = vc->mval[0];
 -              data.mval[1] = vc->mval[1];
 -              data.dist = *dist;
 -              data.closest = NULL;
 -
 -              mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, 2);
 -
 -              *dist = data.dist;
 -              return data.closest;
 -      }
 -}
 -
 -static void findnearestface__getDistance(void *userData, EditFace *efa, int x, int y, int index)
 -{
 -      struct { short mval[2]; int dist; EditFace *toFace; } *data = userData;
 -
 -      if (efa==data->toFace) {
 -              int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
 -
 -              if (temp<data->dist)
 -                      data->dist = temp;
 -      }
 -}
 -static void findnearestface__doClosest(void *userData, EditFace *efa, int x, int y, int index)
 -{
 -      struct { short mval[2], pass; int dist, lastIndex, closestIndex; EditFace *closest; } *data = userData;
 -
 -      if (data->pass==0) {
 -              if (index<=data->lastIndex)
 -                      return;
 -      } else {
 -              if (index>data->lastIndex)
 -                      return;
 -      }
 -
 -      if (data->dist>3) {
 -              int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
 -
 -              if (temp<data->dist) {
 -                      data->dist = temp;
 -                      data->closest = efa;
 -                      data->closestIndex = index;
 -              }
 -      }
 -}
 -static EditFace *findnearestface(ViewContext *vc, int *dist)
 -{
 -
 -      if(vc->v3d->drawtype>OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
 -              unsigned int index = view3d_sample_backbuf(vc, vc->mval[0], vc->mval[1]);
 -              EditFace *efa = BLI_findlink(&vc->em->faces, index-1);
 -
 -              if (efa) {
 -                      struct { short mval[2]; int dist; EditFace *toFace; } data;
 -
 -                      data.mval[0] = vc->mval[0];
 -                      data.mval[1] = vc->mval[1];
 -                      data.dist = 0x7FFF;             /* largest short */
 -                      data.toFace = efa;
 -
 -                      mesh_foreachScreenFace(vc, findnearestface__getDistance, &data);
 -
 -                      if(vc->em->selectmode == SCE_SELECT_FACE || data.dist<*dist) {  /* only faces, no dist check */
 -                              *dist= data.dist;
 -                              return efa;
 -                      }
 -              }
 -              
 -              return NULL;
 -      }
 -      else {
 -              struct { short mval[2], pass; int dist, lastIndex, closestIndex; EditFace *closest; } data;
 -              static int lastSelectedIndex=0;
 -              static EditFace *lastSelected=NULL;
 -
 -              if (lastSelected && BLI_findlink(&vc->em->faces, lastSelectedIndex)!=lastSelected) {
 -                      lastSelectedIndex = 0;
 -                      lastSelected = NULL;
 -              }
 -
 -              data.lastIndex = lastSelectedIndex;
 -              data.mval[0] = vc->mval[0];
 -              data.mval[1] = vc->mval[1];
 -              data.dist = *dist;
 -              data.closest = NULL;
 -              data.closestIndex = 0;
 -
 -              data.pass = 0;
 -              mesh_foreachScreenFace(vc, findnearestface__doClosest, &data);
 -
 -              if (data.dist>3) {
 -                      data.pass = 1;
 -                      mesh_foreachScreenFace(vc, findnearestface__doClosest, &data);
 -              }
 -
 -              *dist = data.dist;
 -              lastSelected = data.closest;
 -              lastSelectedIndex = data.closestIndex;
 -
 -              return data.closest;
 -      }
 -}
 -
 -/* best distance based on screen coords. 
 -   use em->selectmode to define how to use 
 -   selected vertices and edges get disadvantage
 -   return 1 if found one
 -*/
 -static int unified_findnearest(ViewContext *vc, EditVert **eve, EditEdge **eed, EditFace **efa) 
 -{
 -      EditMesh *em= vc->em;
 -      int dist= 75;
 -      
 -      *eve= NULL;
 -      *eed= NULL;
 -      *efa= NULL;
 -      
 -      /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
 -      view3d_validate_backbuf(vc);
 -      
 -      if(em->selectmode & SCE_SELECT_VERTEX)
 -              *eve= findnearestvert(vc, &dist, SELECT, 0);
 -      if(em->selectmode & SCE_SELECT_FACE)
 -              *efa= findnearestface(vc, &dist);
 -
 -      dist-= 20;      /* since edges select lines, we give dots advantage of 20 pix */
 -      if(em->selectmode & SCE_SELECT_EDGE)
 -              *eed= findnearestedge(vc, &dist);
 -
 -      /* return only one of 3 pointers, for frontbuffer redraws */
 -      if(*eed) {
 -              *efa= NULL; *eve= NULL;
 -      }
 -      else if(*efa) {
 -              *eve= NULL;
 -      }
 -      
 -      return (*eve || *eed || *efa);
 -}
 -
 -
  /* ****************  SIMILAR "group" SELECTS. FACE, EDGE AND VERTEX ************** */
  
- /* selects new faces/edges/verts based on the
-  existing selection
- FACES GROUP
-  mode 1: same material
-  mode 2: same image
-  mode 3: same area
-  mode 4: same perimeter
-  mode 5: same normal
-  mode 6: same co-planer
- */
+ /* selects new faces/edges/verts based on the existing selection */
+ /* FACES GROUP */
+ #define SIMFACE_MATERIAL      201
+ #define SIMFACE_IMAGE         202
+ #define SIMFACE_AREA          203
+ #define SIMFACE_PERIMETER     204
+ #define SIMFACE_NORMAL                205
+ #define SIMFACE_COPLANAR      206
  
  static EnumPropertyItem prop_simface_types[] = {
-       {1, "MATERIAL", "Material", ""},
-       {2, "IMAGE", "Image", ""},
-       {3, "AREA", "Area", ""},
-       {4, "PERIMETER", "Perimeter", ""},
-       {5, "NORMAL", "Normal", ""},
-       {6, "COPLANAR", "Co-planar", ""},
-       {0, NULL, NULL, NULL}
+       {SIMFACE_MATERIAL, "MATERIAL", 0, "Material", ""},
+       {SIMFACE_IMAGE, "IMAGE", 0, "Image", ""},
+       {SIMFACE_AREA, "AREA", 0, "Area", ""},
+       {SIMFACE_PERIMETER, "PERIMETER", 0, "Perimeter", ""},
+       {SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""},
+       {SIMFACE_COPLANAR, "COPLANAR", 0, "Co-planar", ""},
+       {0, NULL, 0, NULL, NULL}
  };
  
  
@@@ -2998,273 -3584,158 +3047,7 @@@ static void mesh_selection_type(Scene *
  //            if (EM_texFaceCheck())
        }
  }
- /* ************************* SEAMS AND EDGES **************** */
- static int editmesh_mark_seam(bContext *C, wmOperator *op)
- {
-       Object *obedit= CTX_data_edit_object(C);
-       EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
-       Mesh *me= ((Mesh *)obedit->data);
-       EditEdge *eed;
-       int clear = RNA_boolean_get(op->ptr, "clear");
-       
-       /* auto-enable seams drawing */
-       if(clear==0) {
-               me->drawflag |= ME_DRAWSEAMS;
-       }
-       if(clear) {
-               eed= em->edges.first;
-               while(eed) {
-                       if((eed->h==0) && (eed->f & SELECT)) {
-                               eed->seam = 0;
-                       }
-                       eed= eed->next;
-               }
-       }
-       else {
-               eed= em->edges.first;
-               while(eed) {
-                       if((eed->h==0) && (eed->f & SELECT)) {
-                               eed->seam = 1;
-                       }
-                       eed= eed->next;
-               }
-       }
-       WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
-       BKE_mesh_end_editmesh(obedit->data, em);
-       return OPERATOR_FINISHED;
- }
- void MESH_OT_mark_seam(wmOperatorType *ot)
- {
-       /* identifiers */
-       ot->name= "Mark seam";
-       ot->idname= "MESH_OT_mark_seam";
-       
-       /* api callbacks */
-       ot->exec= editmesh_mark_seam;
-       ot->poll= ED_operator_editmesh;
-       
-       /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-       
-       RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
- }
- static int editmesh_mark_sharp(bContext *C, wmOperator *op)
- {
-       Object *obedit= CTX_data_edit_object(C);
-       EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
-       Mesh *me= ((Mesh *)obedit->data);
-       int set = RNA_boolean_get(op->ptr, "set");
-       EditEdge *eed;
-       /* auto-enable sharp edge drawing */
-       if(set) {
-               me->drawflag |= ME_DRAWSHARP;
-       }
-       if(set) {
-               eed= em->edges.first;
-               while(eed) {
-                       if(!eed->h && (eed->f & SELECT)) eed->sharp = 1;
-                       eed = eed->next;
-               }
-       } else {
-               eed= em->edges.first;
-               while(eed) {
-                       if(!eed->h && (eed->f & SELECT)) eed->sharp = 0;
-                       eed = eed->next;
-               }
-       }
-       WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
-       BKE_mesh_end_editmesh(obedit->data, em);
-       return OPERATOR_FINISHED;
- }
- void MESH_OT_mark_sharp(wmOperatorType *ot)
- {
-       /* identifiers */
-       ot->name= "Mark sharp";
-       ot->idname= "MESH_OT_mark_sharp";
-       
-       /* api callbacks */
-       ot->exec= editmesh_mark_sharp;
-       ot->poll= ED_operator_editmesh;
-       
-       /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-       
-       RNA_def_boolean(ot->srna, "set", 0, "Set", "");
- }
- void BME_Menu()       {
-       short ret;
-       ret= pupmenu("BME modeller%t|Select Edges of Vert%x1");
-       
-       switch(ret)
-       {
-               case 1:
-               //BME_edges_of_vert();
-               break;
-       }
- }
- void Vertex_Menu(EditMesh *em) 
- {
-       short ret;
-       ret= pupmenu("Vertex Specials%t|Remove Doubles%x1|Merge%x2|Smooth %x3|Select Vertex Path%x4|Blend From Shape%x5|Propagate To All Shapes%x6");
-       switch(ret)
-       {
-               case 1:
- // XXX                        notice("Removed %d Vertices", removedoublesflag(1, 0, scene->toolsettings->doublimit));
-                       break;
-               case 2: 
- // XXX                        mergemenu(em);
-                       break;
-               case 3:
- // XXX                        vertexsmooth(em);
-                       break;
-               case 4:
- // XXX                        pathselect(em);
-                       break;
-               case 5: 
- // XXX                        shape_copy_select_from(em);
-                       break;
-               case 6: 
- // XXX                        shape_propagate(em);
-                       break;
-       }
-       /* some items crashed because this is in the original W menu but not here. should really manage this better */
- //    DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
- }
- void Edge_Menu(EditMesh *em) 
- {
-       short ret;
-       ret= pupmenu("Edge Specials%t|Mark Seam %x1|Clear Seam %x2|Rotate Edge CW%x3|Rotate Edge CCW%x4|Loopcut%x6|Edge Slide%x5|Edge Loop Select%x7|Edge Ring Select%x8|Loop to Region%x9|Region to Loop%x10|Mark Sharp%x11|Clear Sharp%x12");
-       switch(ret)
-       {
-       case 1:
-               //editmesh_mark_seam(em, 0);
-               break;
-       case 2:
-               //editmesh_mark_seam(em, 1);
-               break;
-       case 3:
- //            edge_rotate_selected(em, 2);
-               break;
-       case 4:
- //            edge_rotate_selected(em, 1);
-               break;
-       case 5:
- //            EdgeSlide(em, 0,0.0);
-               break;
-       case 6:
- //            CutEdgeloop(em, 1);
-               break;
-       case 7:
- //            loop_multiselect(em, 0);
-               break;
-       case 8:
- //            loop_multiselect(em, 1);
-               break;
-       case 9:
- //            loop_to_region(em);
-               break;
-       case 10:
- //            region_to_loop(em);
-               break;
-       case 11:
- //            editmesh_mark_sharp(em, 1);
- //            DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
-               break;
-       case 12: 
- //            editmesh_mark_sharp(em, 0);
- //            DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
-               break;
-       }
-       /* some items crashed because this is in the original W menu but not here. should really manage this better */
- //    DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
- }
- void Face_Menu(EditMesh *em) 
- {
-       short ret;
-       ret= pupmenu(
-               "Face Specials%t|Flip Normals%x1|Bevel%x2|Shade Smooth%x3|Shade Flat%x4|"
-               "Triangulate (Ctrl T)%x5|Quads from Triangles (Alt J)%x6|Flip Triangle Edges (Ctrl Shift F)%x7|%l|"
-               "Face Mode Set%x8|Face Mode Clear%x9|%l|"
-               "UV Rotate (Shift - CCW)%x10|UV Mirror (Shift - Switch Axis)%x11|"
-               "Color Rotate (Shift - CCW)%x12|Color Mirror (Shift - Switch Axis)%x13");
-       switch(ret)
-       {
-               case 1:
- //                    flip_editnormals(em);
- //                    DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
-                       break;
-               case 2:
- //                    bevel_menu(em);
-                       break;
-               case 3:
- //                    mesh_set_smooth_faces(em, 1);
-                       break;
-               case 4:
- //                    mesh_set_smooth_faces(em, 0);
-                       break;
-                       
-               case 5: /* Quads to Tris */
- //                    convert_to_triface(em, 0);
- //                    DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
-                       break;
-               case 6: /* Tris to Quads */
- //                    join_triangles(em);
-                       break;
-               case 7: /* Flip triangle edges */
- //                    edge_flip(em);
-                       break;
-               case 8:
- //                    mesh_set_face_flags(em, 1);
-                       break;
-               case 9:
- //                    mesh_set_face_flags(em, 0);
-                       break;
-                       
-               /* uv texface options */
-               case 10:
- //                    mesh_rotate_uvs(em);
-                       break;
-               case 11:
- //                    mesh_mirror_uvs(em);
-                       break;
-               case 12:
- //                    mesh_rotate_colors(em);
-                       break;
-               case 13:
- //                    mesh_mirror_colors(em);
-                       break;
-       }
-       /* some items crashed because this is in the original W menu but not here. should really manage this better */
- //    DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
- }
  
 -static EnumPropertyItem prop_mesh_edit_types[] = {
 -      {1, "VERT", 0, "Vertices", ""},
 -      {2, "EDGE", 0, "Edges", ""},
 -      {3, "FACE", 0, "Faces", ""},
 -      {0, NULL, 0, NULL, NULL}
 -};
 -
 -static int mesh_selection_type_exec(bContext *C, wmOperator *op)
 -{             
 -      
 -      Object *obedit= CTX_data_edit_object(C);
 -      EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
 -
 -      mesh_selection_type(CTX_data_scene(C), em, RNA_enum_get(op->ptr,"type"));
 -
 -      WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
 -      
 -      BKE_mesh_end_editmesh(obedit->data, em);
 -      return OPERATOR_FINISHED;
 -}
 -
 -void MESH_OT_selection_type(wmOperatorType *ot)
 -{
 -      /* identifiers */
 -      ot->name= "Selection Mode";
 -      ot->idname= "MESH_OT_selection_type";
 -      
 -      /* api callbacks */
 -      ot->invoke= WM_menu_invoke;
 -      ot->exec= mesh_selection_type_exec;
 -      
 -      ot->poll= ED_operator_editmesh;
 -      
 -      /* flags */
 -      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 -      
 -      /* props */
 -      RNA_def_enum(ot->srna, "type", prop_mesh_edit_types, 0, "Type", "Set the mesh selection type");
 -      
 -}
 -/* ************************* SEAMS AND EDGES **************** */
 -
 -static int editmesh_mark_seam(bContext *C, wmOperator *op)
 -{
 -      Scene *scene = CTX_data_scene(C);
 -      Object *obedit= CTX_data_edit_object(C);
 -      EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
 -      Mesh *me= ((Mesh *)obedit->data);
 -      EditEdge *eed;
 -      int clear = RNA_boolean_get(op->ptr, "clear");
 -      
 -      /* auto-enable seams drawing */
 -      if(clear==0) {
 -              me->drawflag |= ME_DRAWSEAMS;
 -      }
 -
 -      if(clear) {
 -              eed= em->edges.first;
 -              while(eed) {
 -                      if((eed->h==0) && (eed->f & SELECT)) {
 -                              eed->seam = 0;
 -                      }
 -                      eed= eed->next;
 -              }
 -      }
 -      else {
 -              eed= em->edges.first;
 -              while(eed) {
 -                      if((eed->h==0) && (eed->f & SELECT)) {
 -                              eed->seam = 1;
 -                      }
 -                      eed= eed->next;
 -              }
 -      }
 -
 -      BKE_mesh_end_editmesh(obedit->data, em);
 -
 -      DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 -      WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
 -
 -      return OPERATOR_FINISHED;
 -}
 -
 -void MESH_OT_mark_seam(wmOperatorType *ot)
 -{
 -      /* identifiers */
 -      ot->name= "Mark Seam";
 -      ot->idname= "MESH_OT_mark_seam";
 -      
 -      /* api callbacks */
 -      ot->exec= editmesh_mark_seam;
 -      ot->poll= ED_operator_editmesh;
 -      
 -      /* flags */
 -      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 -      
 -      RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
 -}
 -
 -static int editmesh_mark_sharp(bContext *C, wmOperator *op)
 -{
 -      Scene *scene = CTX_data_scene(C);
 -      Object *obedit= CTX_data_edit_object(C);
 -      EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
 -      Mesh *me= ((Mesh *)obedit->data);
 -      int clear = RNA_boolean_get(op->ptr, "clear");
 -      EditEdge *eed;
 -
 -      /* auto-enable sharp edge drawing */
 -      if(clear == 0) {
 -              me->drawflag |= ME_DRAWSHARP;
 -      }
 -
 -      if(!clear) {
 -              eed= em->edges.first;
 -              while(eed) {
 -                      if(!eed->h && (eed->f & SELECT)) eed->sharp = 1;
 -                      eed = eed->next;
 -              }
 -      } else {
 -              eed= em->edges.first;
 -              while(eed) {
 -                      if(!eed->h && (eed->f & SELECT)) eed->sharp = 0;
 -                      eed = eed->next;
 -              }
 -      }
 -
 -      BKE_mesh_end_editmesh(obedit->data, em);
 -
 -      DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 -      WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
 -
 -      return OPERATOR_FINISHED;
 -}
 -
 -void MESH_OT_mark_sharp(wmOperatorType *ot)
 -{
 -      /* identifiers */
 -      ot->name= "Mark Sharp";
 -      ot->idname= "MESH_OT_mark_sharp";
 -      
 -      /* api callbacks */
 -      ot->exec= editmesh_mark_sharp;
 -      ot->poll= ED_operator_editmesh;
 -      
 -      /* flags */
 -      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 -      
 -      RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
 -}
 -
  /* **************** NORMALS ************** */
  
  /* XXX value of select is messed up, it means two things */
@@@ -3481,8 -3952,8 +3264,9 @@@ void righthandfaces(EditMesh *em, int s
  
  static int righthandfaces_exec(bContext *C, wmOperator *op)
  {
+       Scene *scene = CTX_data_scene(C);
        Object *obedit= CTX_data_edit_object(C);
 +
        EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
        
        /* 'standard' behaviour - check if selected, then apply relevant selection */
@@@ -3690,25 -4163,16 +3476,22 @@@ void editmesh_align_view_to_selected(Ob
  
  static int smooth_vertex(bContext *C, wmOperator *op)
  {
 +#if 0 //BMESH_TODO
        Scene *scene= CTX_data_scene(C);
        Object *obedit= CTX_data_edit_object(C);
-       Mesh *me= obedit->data;
-       EditMesh *em= (EditMesh *)me; 
+       EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
        EditVert *eve, *eve_mir = NULL;
        EditEdge *eed;
        float *adror, *adr, fac;
        float fvec[3];
        int teller=0;
-       ModifierData *md= obedit->modifiers.first;
+       ModifierData *md;
  
 +      if(em==NULL) {
 +              BKE_mesh_end_editmesh(obedit->data, em);
 +              return OPERATOR_CANCELLED;
 +      }
 +
        /* count */
        eve= em->verts.first;
        while(eve) {
  
        recalc_editnormals(em);
  
-       WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+       BKE_mesh_end_editmesh(obedit->data, em);
  
- //    DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+       DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
  
-       BKE_mesh_end_editmesh(obedit->data, em);
 +#endif
        return OPERATOR_FINISHED;
  }
  
index 8b817b4b3331aa434ee43cbc3198ba92aafce0b5,efb68f69dac8eba4862407e0b615f33dba1be419..50ac789412013ebb05c321da39bd4948858265ca
@@@ -559,11 -556,11 +560,11 @@@ void xsortvert_flag(bContext *C, int fl
                        BLI_addtail(&tbase, eve);
                }
        }
-       
        addlisttolist(&vc.em->verts, &tbase);
-       
        MEM_freeN(sortblock);
 -
 +#endif
  }
  
  /* called from buttons */
@@@ -702,10 -696,6 +703,8 @@@ void extrude_mesh(Object *obedit, EditM
  
  }
  
- <<<<<<< .working
- =======
 +#if 0 
 +//need to see if this really had new stuff I should merge over
  // XXX should be a menu item
  static int mesh_extrude_invoke(bContext *C, wmOperator *op, wmEvent *event)
  {
@@@ -753,9 -749,9 +758,10 @@@ void MESH_OT_extrude(wmOperatorType *ot
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
  
        /* to give to transform */
-       RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
+       Properties_Proportional(ot);
+       RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
  }
 +#endif
  
  static int split_mesh(bContext *C, wmOperator *op)
  {
@@@ -793,11 -790,10 +800,12 @@@ void MESH_OT_split(wmOperatorType *ot
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
  }
  
 -
 +#if 0
 +//this also showed up in a merge, need to check if it
 +//needs changes ported over to new extrude code too
  static int extrude_repeat_mesh(bContext *C, wmOperator *op)
  {
+       Scene *scene= CTX_data_scene(C);
        Object *obedit= CTX_data_edit_object(C);
        EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
  
@@@ -1195,22 -1382,20 +1210,20 @@@ static void alter_co(float *co, EditEdg
                co[1] += vec1[1];
                co[2] += vec1[2];
        }
-       else {
-               if(rad > 0.0) {   /* subdivide sphere */
-                       Normalize(co);
-                       co[0]*= rad;
-                       co[1]*= rad;
-                       co[2]*= rad;
-               }
-               else if(rad< 0.0) {  /* fractal subdivide */
-                       fac= rad* VecLenf(edge->v1->co, edge->v2->co);
-                       vec1[0]= fac*(float)(0.5-BLI_drand());
-                       vec1[1]= fac*(float)(0.5-BLI_drand());
-                       vec1[2]= fac*(float)(0.5-BLI_drand());
-                       VecAddf(co, co, vec1);
-               }
 -      else if(beauty & B_SPHERE) { /* subdivide sphere */
++      /*else if(beauty & B_SPHERE) { // subdivide sphere
+               Normalize(co);
+               co[0]*= smooth;
+               co[1]*= smooth;
+               co[2]*= smooth;
        }
 -      }
+       if(beauty & B_FRACTAL) {
+               fac= fractal*VecLenf(edge->v1->co, edge->v2->co);
+               vec1[0]= fac*(float)(0.5-BLI_drand());
+               vec1[1]= fac*(float)(0.5-BLI_drand());
+               vec1[2]= fac*(float)(0.5-BLI_drand());
+               VecAddf(co, co, vec1);
++      }*/
  }
  
  /* assumes in the edge is the correct interpolated vertices already */
@@@ -2055,18 -2240,18 +2068,18 @@@ static void fill_quad_quadruple(EditMes
                innerverts[0][i]                  = verts[0][(numcuts+1)-i];
                innerverts[numcuts+1][i]  = verts[2][(numcuts+1)-i];
        }
-       
        for(i=1;i<=numcuts;i++) {
                /* we create a fake edge for the next loop */
 -              temp.v2 = innerverts[i][0]                      = verts[1][i];
 +              temp.v2 = innerverts[i][0] = verts[1][i];
                temp.v1 = innerverts[i][numcuts+1]  = verts[3][i];
-               
-               for(j=1;j<=numcuts;j++) { 
+               for(j=1;j<=numcuts;j++) {
                        float percent= (float)j/(float)(numcuts+1);
  
-                       innerverts[i][(numcuts+1)-j]= subdivide_edge_addvert(em, &temp, rad, beauty, percent);
-               }       
-       }       
+                       innerverts[i][(numcuts+1)-j]= subdivide_edge_addvert(em, &temp, smooth, fractal, beauty, percent);
+               }
+       }
        // Fill with faces
        for(i=0;i<numcuts+1;i++) {
                for(j=0;j<numcuts+1;j++) {
@@@ -4608,7 -4780,7 +4608,8 @@@ static void mesh_rip_setface(EditMesh *
  /* based on mouse cursor position, it defines how is being ripped */
  static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
  {
 +#if 0 //BMESH_TODO
+       Scene *scene= CTX_data_scene(C);
        ARegion *ar= CTX_wm_region(C);
        RegionView3D *rv3d= ar->regiondata;
        Object *obedit= CTX_data_edit_object(C);
                        free_editvert(em, eve);
                }
        }
-       
-       RNA_int_set(op->ptr, "mode", TFM_TRANSLATION);
-       WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
  
//    scene->prop_mode = propmode;
// XXX        scene->proportional = prop;
      DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
      WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
  
        BKE_mesh_end_editmesh(obedit->data, em);
+       RNA_enum_set(op->ptr, "proportional", 0);
+       RNA_boolean_set(op->ptr, "mirror", 0);
+       WM_operator_name_call(C, "TFM_OT_translation", WM_OP_INVOKE_REGION_WIN, op->ptr);
 +#endif
        return OPERATOR_FINISHED;
  }
  
@@@ -4959,10 -5126,9 +4957,10 @@@ void shape_copy_from_lerp(EditMesh *em
                for(ev = em->verts.first; ev ; ev = ev->next){
                        if(ev->f & SELECT){
                                VECCOPY(ev->co, odata+(ev->keyindex*3));
-                       }               
+                       }
                }
        return;
 +#endif
  }
  
  
@@@ -6316,13 -6637,60 +6469,14 @@@ void MESH_OT_colors_mirror(wmOperatorTy
        /* api callbacks */
        ot->exec= mesh_mirror_colors;
        ot->poll= ED_operator_editmesh;
-       
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
- }
  
- /* ************************************* */
+       /* props */
+       RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror colors around.");
+ }
  
 -/********************** Subdivide Operator *************************/
 -
 -static int subdivide_exec(bContext *C, wmOperator *op)
 -{
 -      Scene *scene = CTX_data_scene(C);
 -      Object *obedit= CTX_data_edit_object(C);
 -      EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
 -      int cuts= RNA_int_get(op->ptr,"number_cuts");
 -      float smooth= 0.292f*RNA_float_get(op->ptr, "smoothness");
 -      float fractal= RNA_float_get(op->ptr, "fractal")/100;
 -      int flag= 0;
 -
 -      if(smooth != 0.0f)
 -              flag |= B_SMOOTH;
 -      if(fractal != 0.0f)
 -              flag |= B_FRACTAL;
 -
 -      esubdivideflag(obedit, em, 1, smooth, fractal, scene->toolsettings->editbutflag|flag, cuts, 0);
 -
 -      DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 -      WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
 -
 -      return OPERATOR_FINISHED;
 -}
 -
 -void MESH_OT_subdivide(wmOperatorType *ot)
 -{
 -      /* identifiers */
 -      ot->name= "Subdivide";
 -      ot->idname= "MESH_OT_subdivide";
 -
 -      /* api callbacks */
 -      ot->exec= subdivide_exec;
 -      ot->poll= ED_operator_editmesh;
 -
 -      /* flags */
 -      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 -
 -      /* properties */
 -      RNA_def_int(ot->srna, "number_cuts", 1, 1, 10, "Number of Cuts", "", 1, INT_MAX);
 -      RNA_def_float(ot->srna, "fractal", 0.0, 0.0f, FLT_MAX, "Fractal", "Fractal randomness factor.", 0.0f, 1000.0f);
 -      RNA_def_float(ot->srna, "smoothness", 0.0f, 0.0f, 1000.0f, "Smoothness", "Smoothness factor.", 0.0f, FLT_MAX);
 -}
 -
 -/********************** Fill Operators *************************/
 -
  /* note; the EM_selectmode_set() calls here illustrate how badly constructed it all is... from before the
  edge/face flags, with very mixed results.... */
  static void beauty_fill(EditMesh *em)
@@@ -6624,17 -6996,20 +6782,21 @@@ void MESH_OT_beauty_fill(wmOperatorTyp
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
  }
  
+ /********************** Quad/Tri Operators *************************/
  static int quads_convert_to_tris_exec(bContext *C, wmOperator *op)
  {
+       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;
-       
 -      convert_to_triface(em,0);
 +      //convert_to_triface(em,0);
 +      if (!EDBM_CallOpf(em, op, "triangulate faces=%hf", BM_SELECT))
 +              return OPERATOR_CANCELLED;
-       
+       DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
        WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
-       
 -      BKE_mesh_end_editmesh(obedit->data, em);
        return OPERATOR_FINISHED;
  }
  
index c256f9427f6dc4b82be4f324d241d8c522b5c0a6,6e098e04a14022cdb6d0c451f09a2cd949225784..7f974a532d8b8c9e886aa0f8c56734ddc4da4dcc
@@@ -196,10 -149,9 +199,10 @@@ void MESH_OT_knife_cut(struct wmOperato
  /* ******************* editmesh_mods.c */
  void MESH_OT_loop_select(struct wmOperatorType *ot);
  void MESH_OT_select_all_toggle(struct wmOperatorType *ot);
 +void MESH_OT_bmesh_test(struct wmOperatorType *ot);
  void MESH_OT_select_more(struct wmOperatorType *ot);
  void MESH_OT_select_less(struct wmOperatorType *ot);
- void MESH_OT_select_invert(struct wmOperatorType *ot);
+ void MESH_OT_select_inverse(struct wmOperatorType *ot);
  void MESH_OT_select_non_manifold(struct wmOperatorType *ot);
  void MESH_OT_select_linked(struct wmOperatorType *ot);
  void MESH_OT_select_linked_pick(struct wmOperatorType *ot);
@@@ -219,9 -170,9 +221,9 @@@ void MESH_OT_loop_multi_select(struct w
  void MESH_OT_mark_seam(struct wmOperatorType *ot);
  void MESH_OT_mark_sharp(struct wmOperatorType *ot);
  void MESH_OT_vertices_smooth(struct wmOperatorType *ot);
- void MESH_OT_flip_editnormals(struct wmOperatorType *ot);
+ void MESH_OT_flip_normals(struct wmOperatorType *ot);
  
 -extern EditEdge *findnearestedge(ViewContext *vc, int *dist);
 +extern EditEdge *findnearestedge(struct ViewContext *vc, int *dist);
  extern void EM_automerge(int update);
  void editmesh_select_by_material(EditMesh *em, int index);
  void righthandfaces(EditMesh *em, int select);        /* makes faces righthand turning */
@@@ -250,14 -201,11 +252,11 @@@ extern EditVert *findnearestvert(struc
  
  void join_triangles(EditMesh *em);
  int removedoublesflag(EditMesh *em, short flag, short automerge, float limit);                /* return amount */
- void esubdivideflag(Object *obedit, EditMesh *em, int flag, float rad, int beauty, int numcuts, int seltype);
+ void esubdivideflag(Object *obedit, EditMesh *em, int flag, float smooth, float fractal, int beauty, int numcuts, int seltype);
 -int EdgeSlide(EditMesh *em, wmOperator *op, short immediate, float imperc);
 +int EdgeSlide(EditMesh *em, struct wmOperator *op, short immediate, float imperc);
  
+ void MESH_OT_merge(struct wmOperatorType *ot);
  void MESH_OT_subdivide(struct wmOperatorType *ot);
- void MESH_OT_subdivs(struct wmOperatorType *ot);
- void MESH_OT_subdivide_multi(struct wmOperatorType *ot);
- void MESH_OT_subdivide_multi_fractal(struct wmOperatorType *ot);
- void MESH_OT_subdivide_smooth(struct wmOperatorType *ot);
  void MESH_OT_remove_doubles(struct wmOperatorType *ot);
  void MESH_OT_extrude(struct wmOperatorType *ot);
  void MESH_OT_spin(struct wmOperatorType *ot);
index 0000000000000000000000000000000000000000,99d50d1a9b0a9f22347042c462d2b0cf5861e4c8..bad2fa99434ed542d5e99720eaa4921b8e5bb15a
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,424 +1,434 @@@
 -      CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
+ /**
+  * $Id$
+  *
+  * ***** BEGIN GPL LICENSE BLOCK *****
+  *
+  * This program is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU General Public License
+  * as published by the Free Software Foundation; either version 2
+  * of the License, or (at your option) any later version. 
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU General Public License for more details.
+  *
+  * You should have received a copy of the GNU General Public License
+  * along with this program; if not, write to the Free Software Foundation,
+  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+  *
+  * The Original Code is Copyright (C) 2009 Blender Foundation.
+  * All rights reserved.
+  *
+  * 
+  * Contributor(s): Blender Foundation
+  *
+  * ***** END GPL LICENSE BLOCK *****
+  */
+ #include <stdlib.h>
+ #include <math.h>
+ #include "MEM_guardedalloc.h"
+ #include "DNA_customdata_types.h"
+ #include "DNA_mesh_types.h"
+ #include "DNA_meshdata_types.h"
+ #include "DNA_object_types.h"
+ #include "DNA_scene_types.h"
+ #include "DNA_windowmanager_types.h"
+ #include "BKE_context.h"
+ #include "BKE_customdata.h"
+ #include "BKE_depsgraph.h"
+ #include "BKE_displist.h"
+ #include "BKE_global.h"
+ #include "BKE_mesh.h"
++#include "BKE_tessmesh.h"
+ #include "BLI_editVert.h"
+ #include "RNA_access.h"
+ #include "RNA_define.h"
+ #include "WM_api.h"
+ #include "WM_types.h"
+ #include "ED_mesh.h"
+ #include "ED_view3d.h"
+ #include "mesh_intern.h"
++#include "bmesh.h"
+ static void delete_customdata_layer(Mesh *me, CustomDataLayer *layer)
+ {
 -      if(me->edit_mesh) {
 -              EM_free_data_layer(me->edit_mesh, data, type);
++      CustomData *data= (me->edit_btmesh)? &me->edit_btmesh->bm->pdata: &me->pdata;
+       void *actlayerdata, *rndlayerdata, *clonelayerdata, *masklayerdata, *layerdata=layer->data;
+       int type= layer->type;
+       int index= CustomData_get_layer_index(data, type);
+       int i, actindex, rndindex, cloneindex, maskindex;
+       
+       /* ok, deleting a non-active layer needs to preserve the active layer indices.
+         to do this, we store a pointer to the .data member of both layer and the active layer,
+         (to detect if we're deleting the active layer or not), then use the active
+         layer data pointer to find where the active layer has ended up.
+         
+         this is necassary because the deletion functions only support deleting the active
+         layer. */
+       actlayerdata = data->layers[CustomData_get_active_layer_index(data, type)].data;
+       rndlayerdata = data->layers[CustomData_get_render_layer_index(data, type)].data;
+       clonelayerdata = data->layers[CustomData_get_clone_layer_index(data, type)].data;
+       masklayerdata = data->layers[CustomData_get_mask_layer_index(data, type)].data;
+       CustomData_set_layer_active(data, type, layer - &data->layers[index]);
 -              if(type == CD_MCOL && (G.f & G_VERTEXPAINT))
++      if(me->edit_btmesh) {
++              BM_free_data_layer(me->edit_btmesh->bm, data, type);
+       }
+       else {
+               CustomData_free_layer_active(data, type, me->totface);
+               mesh_update_customdata_pointers(me);
+       }
+       if(!CustomData_has_layer(data, type))
 -      EditMesh *em;
++              if(type == CD_MLOOPCOL && (G.f & G_VERTEXPAINT))
+                       G.f &= ~G_VERTEXPAINT; /* get out of vertexpaint mode */
+       /* reconstruct active layer */
+       if (actlayerdata != layerdata) {
+               /* find index */
+               actindex = CustomData_get_layer_index(data, type);
+               for (i=actindex; i<data->totlayer; i++) {
+                       if (data->layers[i].data == actlayerdata) {
+                               actindex = i - actindex;
+                               break;
+                       }
+               }
+               
+               /* set index */
+               CustomData_set_layer_active(data, type, actindex);
+       }
+       
+       if (rndlayerdata != layerdata) {
+               /* find index */
+               rndindex = CustomData_get_layer_index(data, type);
+               for (i=rndindex; i<data->totlayer; i++) {
+                       if (data->layers[i].data == rndlayerdata) {
+                               rndindex = i - rndindex;
+                               break;
+                       }
+               }
+               
+               /* set index */
+               CustomData_set_layer_render(data, type, rndindex);
+       }
+       
+       if (clonelayerdata != layerdata) {
+               /* find index */
+               cloneindex = CustomData_get_layer_index(data, type);
+               for (i=cloneindex; i<data->totlayer; i++) {
+                       if (data->layers[i].data == clonelayerdata) {
+                               cloneindex = i - cloneindex;
+                               break;
+                       }
+               }
+               
+               /* set index */
+               CustomData_set_layer_clone(data, type, cloneindex);
+       }
+       
+       if (masklayerdata != layerdata) {
+               /* find index */
+               maskindex = CustomData_get_layer_index(data, type);
+               for (i=maskindex; i<data->totlayer; i++) {
+                       if (data->layers[i].data == masklayerdata) {
+                               maskindex = i - maskindex;
+                               break;
+                       }
+               }
+               
+               /* set index */
+               CustomData_set_layer_mask(data, type, maskindex);
+       }
+ }
+ /*********************** UV texture operators ************************/
+ static int uv_texture_add_exec(bContext *C, wmOperator *op)
+ {
+       Scene *scene= CTX_data_scene(C);
+       Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+       Mesh *me;
 -              em= me->edit_mesh;
++      BMEditMesh *em;
+       int layernum;
+       if(!ob || ob->type!=OB_MESH)
+               return OPERATOR_CANCELLED;
+       
+       me= (Mesh*)ob->data;
+       if(scene->obedit == ob) {
 -              layernum= CustomData_number_of_layers(&em->fdata, CD_MTFACE);
++              em= me->edit_btmesh;
 -              EM_add_data_layer(em