merge with 2.5 at r18796. note I've customized the
authorJoseph Eagar <joeedh@gmail.com>
Tue, 3 Feb 2009 06:22:30 +0000 (06:22 +0000)
committerJoseph Eagar <joeedh@gmail.com>
Tue, 3 Feb 2009 06:22:30 +0000 (06:22 +0000)
vc9 project files a bit, they won't compile blender by
themselves anymore (I use scons for that).

1  2 
source/blender/bmesh/bmesh_operators.h
source/blender/bmesh/intern/bmesh_mods.c
source/blender/bmesh/intern/editmesh_to_bmesh.c
source/blender/bmesh/operators/subdivideop.c
source/blender/editors/mesh/editmesh_mods.c
source/blender/editors/mesh/mesh_intern.h

index 390283393c7b4032bc0dcedcf2eea094f6281e52,0000000000000000000000000000000000000000..ed12cf3b81152c15e55365a690ee75d5d47f8b6b
mode 100644,000000..100644
--- /dev/null
@@@ -1,210 -1,0 +1,213 @@@
- void BMOP_DupeFromFlag(struct BMesh *bm, int etypeflag, int flag);
 +#ifndef BM_OPERATORS_H
 +#define BM_OPERATORS_H
 +
 +#include "BLI_memarena.h"
 +
 +#define BMOP_OPSLOT_INT                       0
 +#define BMOP_OPSLOT_FLT                       1
 +#define BMOP_OPSLOT_PNT                       2
 +#define BMOP_OPSLOT_VEC                       6
 +
 +/*after BMOP_OPSLOT_VEC, everything is 
 +  dynamically allocated arrays.  we
 +  leave a space in the identifiers
 +  for future growth.*/
 +#define BMOP_OPSLOT_INT_BUF           7
 +#define BMOP_OPSLOT_FLT_BUF           8               
 +#define BMOP_OPSLOT_PNT_BUF           9
 +#define BMOP_OPSLOT_TYPES             10
 +
 +typedef struct BMOpSlot{
 +      int slottype;
 +      int len;
 +      int index; /*index within slot array*/
 +      union {
 +              int i;
 +              float f;                                        
 +              void *p;                                        
 +              float vec[3];                           /*vector*/
 +              void *buf;                              /*buffer*/
 +      } data;
 +}BMOpSlot;
 +
 +/*operators represent logical, executable mesh modules.*/
 +#define BMOP_MAX_SLOTS                        16              /*way more than probably needed*/
 +
 +typedef struct BMOperator{
 +      int type;
 +      int slottype;
 +      int needflag;
 +      struct BMOpSlot slots[BMOP_MAX_SLOTS];
 +      void (*exec)(struct BMesh *bm, struct BMOperator *op);
 +      MemArena *arena;
 +}BMOperator;
 +
 +/*need to refactor code to use this*/
 +typedef struct BMOpDefine {
 +      int slottypes[BMOP_MAX_SLOTS];
 +      void (*exec)(BMesh *bm, BMOperator *op);
 +      int totslot;
 +      int flag;
 +} BMOpDefine;
 +
 +/*BMOpDefine->flag*/
 +//doesn't do anything at the moment.
 +
 +/*API for operators*/
 +void BMO_Init_Op(struct BMOperator *op, int opcode);
 +void BMO_Exec_Op(struct BMesh *bm, struct BMOperator *op);
 +void BMO_Finish_Op(struct BMesh *bm, struct BMOperator *op);
 +BMOpSlot *BMO_GetSlot(struct BMOperator *op, int slotcode);
 +void BMO_CopySlot(struct BMOperator *source_op, struct BMOperator *dest_op, int src, int dst);
 +void BMO_Set_Float(struct BMOperator *op, int slotcode, float f);
 +void BMO_Set_Int(struct BMOperator *op, int slotcode, int i);
 +void BMO_Set_PntBuf(struct BMOperator *op, int slotcode, void *p, int len);
 +void BMO_Set_Pnt(struct BMOperator *op, int slotcode, void *p);
 +void BMO_Set_Vec(struct BMOperator *op, int slotcode, float *vec);
 +void BMO_SetFlag(struct BMesh *bm, void *element, int flag);
 +void BMO_ClearFlag(struct BMesh *bm, void *element, int flag);
 +int BMO_TestFlag(struct BMesh *bm, void *element, int flag);
 +int BMO_CountFlag(struct BMesh *bm, int flag, int type);
 +void BMO_Flag_To_Slot(struct BMesh *bm, struct BMOperator *op, int slotcode, int flag, int type);
 +void BMO_Flag_Buffer(struct BMesh *bm, struct BMOperator *op, int slotcode, int flag);
 +void BMO_HeaderFlag_To_Slot(struct BMesh *bm, struct BMOperator *op, int slotcode, int flag, int type);
 +
 +/*if msg is null, then the default message for the errorcode is used*/
 +void BMOP_RaiseError(BMesh *bm, int errcode, char *msg);
 +/*returns error code or 0 if no error*/
 +int BMOP_GetError(BMesh *bm, char **msg);
 +/*returns 1 if there was an error*/
 +int BMOP_CheckError(BMesh *bm);
 +int BMOP_PopError(BMesh *bm, char **msg);
 +
 +/*------ error code defines -------*/
 +
 +/*error messages*/
 +#define BMERR_SELF_INTERSECTING        1
 +
 +static char *bmop_error_messages[] = {
 +       0,
 +       "Self intersection error",
 +};
 +
 +/*------------begin operator defines (see bmesh_opdefines.c too)------------*/
 +/*split op*/
 +#define BMOP_SPLIT                            0
 +
 +enum {
 +      BMOP_SPLIT_MULTIN,
 +      BMOP_SPLIT_MULTOUT,
 +      BMOP_SPLIT_TOTSLOT,
 +};
 +
 +/*dupe op*/
 +#define BMOP_DUPE     1
 +
 +enum {
 +      BMOP_DUPE_MULTIN,
 +      BMOP_DUPE_ORIG,
 +      BMOP_DUPE_NEW,
 +      BMOP_DUPE_TOTSLOT
 +};
 +
 +/*delete op*/
 +#define BMOP_DEL      2
 +
 +enum {
 +      BMOP_DEL_MULTIN,
 +      BMOP_DEL_CONTEXT,
 +      BMOP_DEL_TOTSLOT,
 +};
 +
 +#define DEL_VERTS             1
 +#define DEL_EDGES             2
 +#define DEL_ONLYFACES 3
 +#define DEL_EDGESFACES        4
 +#define DEL_FACES             5
 +#define DEL_ALL                       6
 +
 +/*BMOP_DEL_CONTEXT*/
 +enum {
 +      BMOP_DEL_VERTS = 1,
 +      BMOP_DEL_EDGESFACES,
 +      BMOP_DEL_ONLYFACES,
 +      BMOP_DEL_FACES,
 +      BMOP_DEL_ALL,
 +};
 +
 +/*editmesh->bmesh op*/
 +#define BMOP_FROM_EDITMESH            3
 +enum {
 +      BMOP_FROM_EDITMESH_EM,
 +      BMOP_FROM_EDITMESH_TOTSLOT,
 +};
 +
 +#define BMOP_TO_EDITMESH              4
 +/*bmesh->editmesh op*/
 +enum {
 +      BMOP_TO_EDITMESH_EMOUT,
 +      BMOP_TO_EDITMESH_TOTSLOT,
 +};
 +
 +/*edge subdivide op*/
 +#define BMOP_ESUBDIVIDE                       5
 +enum {
 +      BMOP_ESUBDIVIDE_EDGES,
 +      BMOP_ESUBDIVIDE_NUMCUTS,
 +      BMOP_ESUBDIVIDE_FLAG, //beauty flag in esubdivide
 +      BMOP_ESUBDIVIDE_RADIUS,
 +      BMOP_ESUBDIVIDE_SELACTION,
 +      BMOP_ESUBDIVIDE_TOTSLOT,
 +};
 +/*
 +SUBDIV_SELECT_INNER
 +SUBDIV_SELECT_ORIG
 +SUBDIV_SELECT_INNER_SEL
 +SUBDIV_SELECT_LOOPCUT
 +DOUBLEOPFILL
 +*/
 +
 +/*triangulate*/
 +#define BMOP_TRIANGULATE              6
 +
 +enum {
 +      BMOP_TRIANG_FACEIN,
 +      BMOP_TRIANG_NEW_EDGES,
 +      BMOP_TRIANG_NEW_FACES,
 +      BMOP_TRIANG_TOTSLOT,
 +};
 +
 +/*dissolve faces*/
 +#define BMOP_DISSOLVE_FACES           7
 +
 +#define BMOP_DISFACES_FACEIN  0
 +#define BMOP_DISFACES_TOTSLOT 1
 +
 +/*dissolve verts*/
 +#define BMOP_DISSOLVE_VERTS           8
 +
 +#define BMOP_DISVERTS_VERTIN  0
 +#define BMOP_DISVERTS_TOTSLOT 1
 +
 +#define BMOP_MAKE_FGONS                       9
 +#define BMOP_MAKE_FGONS_TOTSLOT       0
 +
 +/*keep this updated!*/
 +#define BMOP_TOTAL_OPS                        10
 +/*-------------------------------end operator defines-------------------------------*/
 +
 +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;
 +
++void BMOP_DupeFromFlag(struct BMesh *bm, int etypeflag, int flag);
++void BM_esubdivideflag(struct Object *obedit, struct BMesh *bm, int selflag, float rad, 
++                     int flag, int numcuts, int seltype);
 +#endif
index 15ef76eb5bb42c844a580945ef5eeba65584fc92,0000000000000000000000000000000000000000..8334876395c513c70acc222d05d2f684c5019446
mode 100644,000000..100644
--- /dev/null
@@@ -1,341 -1,0 +1,331 @@@
-       float percent, step,length, vt1[3], v2[3];
 +#include <limits.h>
 +#include "MEM_guardedalloc.h"
 +
 +#include "DNA_listBase.h"
 +#include "BKE_utildefines.h"
 +#include "BLI_blenlib.h"
 +#include "BLI_linklist.h"
 +#include "BLI_ghash.h"
 +#include "BLI_arithb.h"
 +
 +#include "bmesh.h"
 +#include "bmesh_private.h"
 +
 +
 +/*
 + * BME_MODS.C
 + *
 + * This file contains functions for locally modifying
 + * the topology of existing mesh data. (split, join, flip ect).
 + *
 +*/
 +
 +/**
 + *                    bmesh_dissolve_disk
 + *
 + *  Turns the face region surrounding a manifold vertex into 
 + *  A single polygon.
 + *
 + * 
 + * Example:
 + * 
 + *          |=========|             |=========|
 + *          |  \   /  |             |         |
 + * Before:  |    V    |      After: |         |
 + *          |  /   \  |             |         |
 + *          |=========|             |=========|
 + * 
 + * 
 + *  Returns -
 + *    1 for success, 0 for failure.
 + */
 +#if 1
 +void BM_Dissolve_Disk(BMesh *bm, BMVert *v) {
 +      BMFace *f, *f2;
 +      BMEdge *e, *keepedge=NULL, *baseedge=NULL;
 +      BMLoop *loop;
 +      int done, len;
 +
 +      if(BM_Nonmanifold_Vert(bm, v)) return;
 +      
 +      if(v->edge){
 +              /*v->edge we keep, what else?*/
 +              e = v->edge;
 +              len = 0;
 +              do{
 +                      e = bmesh_disk_nextedge(e,v);
 +                      if(!(BM_Edge_Share_Faces(e, v->edge))){
 +                              keepedge = e;
 +                              baseedge = v->edge;
 +                              break;
 +                      }
 +                      len++;
 +              }while(e != v->edge);
 +      }
 +      
 +      /*this code for handling 2 and 3-valence verts
 +        may be totally bad.*/
 +      if (keepedge == NULL && len == 3) {
 +              /*handle specific case for three-valence.  solve it by
 +                increasing valence to four.  this may be hackish. . .*/
 +              loop = e->loop;
 +              if (loop->v == v) loop = (BMLoop*) loop->head.next;
 +              BM_Split_Face(bm, loop->f, v, loop->v, NULL, NULL, 0);
 +
 +              BM_Dissolve_Disk(bm, v);
 +              return;
 +      } else if (keepedge == NULL && len == 2) {
 +              /*handle two-valence*/
 +              f = v->edge->loop->f;
 +              f2 = ((BMLoop*)v->edge->loop->radial.next->data)->f;
 +              /*collapse the vertex*/
 +              BM_Collapse_Vert(bm, v->edge, v, 1.0, 0);
 +              BM_Join_Faces(bm, f, f2, NULL, 0, 0);
 +      }
 +
 +      if(keepedge){
 +              done = 0;
 +              while(!done){
 +                      done = 1;
 +                      e = v->edge;
 +                      do{
 +                              f = NULL;
 +                              len = bmesh_cycle_length(&(e->loop->radial));
 +                              if(len == 2 && (e!=baseedge) && (e!=keepedge))
 +                                      f = BM_Join_Faces(bm, e->loop->f, ((BMLoop*)(e->loop->radial.next->data))->f, e, 0, 0); 
 +                              if(f){
 +                                      done = 0;
 +                                      break;
 +                              }
 +                              e = bmesh_disk_nextedge(e, v);
 +                      }while(e != v->edge);
 +              }
 +
 +              /*get remaining two faces*/
 +              f = v->edge->loop->f;
 +              f2 = ((BMLoop*)v->edge->loop->radial.next->data)->f;
 +              /*collapse the vertex*/
 +              BM_Collapse_Vert(bm, baseedge, v, 1.0, 0);
 +
 +              /*join two remaining faces*/
 +              BM_Join_Faces(bm, f, f2, NULL, 0, 0);
 +      }
 +}
 +#else
 +void BM_Dissolve_Disk(BMesh *bm, BMVert *v){
 +      BMFace *f;
 +      BMEdge *e;
 +      BMIter iter;
 +      int done, len;
 +      
 +      if(v->edge){
 +              done = 0;
 +              while(!done){
 +                      done = 1;
 +                      
 +                      /*loop the edges looking for an edge to dissolve*/
 +                      for (e=BMIter_New(&iter, bm, BM_EDGES_OF_VERT, v); e;
 +                           e = BMIter_Step(&iter)) {
 +                              f = NULL;
 +                              len = bmesh_cycle_length(&(e->loop->radial));
 +                              if(len == 2){
 +                                      f = BM_Join_Faces(bm,e->loop->f,((BMLoop*)
 +                                            (e->loop->radial.next->data))->f, 
 +                                             e, 1, 0);
 +                              }
 +                              if(f){ 
 +                                      done = 0;
 +                                      break;
 +                              }
 +                      };
 +              }
 +              BM_Collapse_Vert(bm, v->edge, v, 1.0, 1);
 +      }
 +}
 +#endif
 +
 +/**
 + *                    bmesh_join_faces
 + *
 + *  joins two adjacenct faces togather. If weldUVs == 1
 + *  and the uv/vcols of the two faces are non-contigous, the
 + *  per-face properties of f2 will be transformed into place
 + *  around f1.
 + * 
 + *  Returns -
 + *    BMFace pointer
 + */
 + 
 +BMFace *BM_Join_Faces(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e, int calcnorm, int weldUVs) {
 +
 +      BMLoop *l1, *l2;
 +      BMEdge *jed=NULL;
 +      
 +      jed = e;
 +      if(!jed){
 +              /*search for an edge that has both these faces in its radial cycle*/
 +              l1 = f1->loopbase;
 +              do{
 +                      if( ((BMLoop*)l1->radial.next->data)->f == f2 ){
 +                              jed = l1->e;
 +                              break;
 +                      }
 +                      l1 = ((BMLoop*)(l1->head.next));
 +              }while(l1!=f1->loopbase);
 +      }
 +
 +      l1 = jed->loop;
 +      l2 = l1->radial.next->data;
 +      if (l1->v == l2->v) {
 +              bmesh_loop_reverse(bm, f2);
 +      }
 +
 +      return bmesh_jfke(bm, f1, f2, jed);
 +}
 +
 +/*connects two verts together, automatically (if very naively) finding the
 +  face they both share (if there is one) and splittling it.  use this at your 
 +  own risk, as it doesn't handle the many complex cases it should (like zero-area faces,
 +  multiple faces, etc).
 +
 +  this is really only meant for cases where you don't know before hand the face
 +  the two verts belong to for splitting (e.g. the subdivision operator).
 +*/
 +
 +BMEdge *BM_Connect_Verts(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **nf) {
 +      BMIter iter, iter2;
 +      BMVert *v;
 +      BMLoop *nl;
 +      BMFace *face;
 +
 +      /*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) {
 +                              face = BM_Split_Face(bm, face, v1, v2, &nl, NULL, 1);
 +
 +                              if (nf) *nf = face;
 +                              return nl->e;
 +                      }
 +              }
 +      }
 +
 +      return NULL;
 +}
 +
 +/**
 + *                    BM_split_face
 + *
 + *  Splits a single face into two.
 + * 
 + *  Returns -
 + *    BMFace pointer
 + */
 + 
 +BMFace *BM_Split_Face(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **nl, BMEdge *example, int calcnorm)
 +{
 +      BMFace *nf;
 +      nf = bmesh_sfme(bm,f,v1,v2,nl);
 +      
 +      /*
 +      nf->flag = f->flag;
 +      if (example->flag & SELECT) f->flag |= BM_SELECT;
 +      nf->h = f->h;
 +      nf->mat_nr = f->mat_nr;
 +      if (nl && example) {
 +              (*nl)->e->flag = example->flag;
 +              (*nl)->e->h = example->h;
 +              (*nl)->e->crease = example->crease;
 +              (*nl)->e->bweight = example->bweight;
 +      }
 +      */
 +      return nf;
 +}
 +
 +/**
 + *                    bmesh_collapse_vert
 + *
 + *  Collapses a vertex that has only two manifold edges
 + *  onto a vertex it shares an edge with. Fac defines
 + *  the amount of interpolation for Custom Data.
 + *
 + *  Note that this is not a general edge collapse function. For
 + *  that see BM_manifold_edge_collapse 
 + *
 + *  TODO:
 + *    Insert error checking for KV valance.
 + *
 + *  Returns -
 + *    Nothing
 + */
 + 
 +void BM_Collapse_Vert(BMesh *bm, BMEdge *ke, BMVert *kv, float fac, int calcnorm){
 +      void *src[2];
 +      float w[2];
 +      BMLoop *l=NULL, *kvloop=NULL, *tvloop=NULL;
 +      BMVert *tv = bmesh_edge_getothervert(ke,kv);
 +
 +      w[0] = 1.0f - fac;
 +      w[1] = fac;
 +
 +      if(ke->loop){
 +              l = ke->loop;
 +              do{
 +                      if(l->v == tv && ((BMLoop*)(l->head.next))->v == kv){
 +                              tvloop = l;
 +                              kvloop = ((BMLoop*)(l->head.next));
 +
 +                              src[0] = kvloop->data;
 +                              src[1] = tvloop->data;
 +                              CustomData_bmesh_interp(&bm->ldata, src,w, NULL, 2, kvloop->data);                                                              
 +                      }
 +                      l=l->radial.next->data;
 +              }while(l!=ke->loop);
 +      }
 +      BM_Data_Interp_From_Verts(bm, kv, tv, kv, fac);   
 +      bmesh_jekv(bm,ke,kv);
 +}
 +
 +/**
 + *                    BM_split_edge
 + *    
 + *    Splits an edge. v should be one of the vertices in e and
 + *  defines the direction of the splitting operation for interpolation
 + *  purposes.
 + *
 + *  Returns -
 + *    the new vert
 + */
 +
 +BMVert *BM_Split_Edge(BMesh *bm, BMVert *v, BMEdge *e, BMEdge **ne, float percent, int calcnorm) {
 +      BMVert *nv, *v2;
 +
 +      v2 = bmesh_edge_getothervert(e,v);
 +      nv = bmesh_semv(bm,v,e,ne);
 +      if (nv == NULL) return NULL;
 +      VECSUB(nv->co,v2->co,v->co);
 +      VECADDFAC(nv->co,v->co,nv->co,percent);
 +      if (ne) {
 +              if(bmesh_test_sysflag(&(e->head), BM_SELECT)) bmesh_set_sysflag(&((*ne)->head), BM_SELECT);
 +              if(bmesh_test_sysflag(&(e->head), BM_HIDDEN)) bmesh_set_sysflag(&((*ne)->head), BM_HIDDEN);
 +      }
 +      /*v->nv->v2*/
 +      BM_Data_Facevert_Edgeinterp(bm,v2, v, nv, e, percent);  
 +      BM_Data_Interp_From_Verts(bm, v2, v, nv, percent);
 +      return nv;
 +}
 +
 +BMVert  *BM_Split_Edge_Multi(BMesh *bm, BMEdge *e, int numcuts)
 +{
 +      int i;
-       percent = 0.0;
-       step = (1.0/((float)numcuts+1));
-       
-       length = VecLenf(e->v1->co,e->v2->co);
-       VECCOPY(v2,e->v2->co);
-       VecSubf(vt1, e->v1->co,  e->v2->co);
-       
++      float percent;
 +      BMVert *nv = NULL;
 +      
-               percent += step;
 +      for(i=0; i < numcuts; i++){
-               VECCOPY(nv->co,vt1);
-               VecMulf(nv->co,percent);
-               VecAddf(nv->co,v2,nv->co);
++              percent = 1.0 / (float)(numcuts + 1 - i);
 +              nv = BM_Split_Edge(bm, e->v2, e, NULL, percent, 0);
 +      }
 +      return nv;
 +}
index e328f7791338c37dbf498adab34e351a9f247b24,0000000000000000000000000000000000000000..12b5f55f9eeb5acea9f496964554188da1d3e937
mode 100644,000000..100644
--- /dev/null
@@@ -1,413 -1,0 +1,414 @@@
-               
 +#include "MEM_guardedalloc.h"
 +#include "BKE_customdata.h" 
 +#include "DNA_listBase.h"
 +#include "DNA_meshdata_types.h"
 +#include "DNA_object_types.h"
 +#include "DNA_scene_types.h"
 +#include <string.h>
 +#include "BKE_utildefines.h"
 +#include "BKE_mesh.h"
 +#include "BKE_global.h"
 +#include "BKE_DerivedMesh.h"
 +#include "BKE_cdderivedmesh.h"
 +
 +#include "BLI_editVert.h"
 +#include "mesh_intern.h"
 +#include "ED_mesh.h"
 +
 +#include "BLI_blenlib.h"
 +#include "BLI_edgehash.h"
 +
 +#include "bmesh.h"
 +
 +/*
 + * EDITMESH TO BMESH.C
 + *
 + * This file contains functions
 + * for converting an editmesh
 + * into a Bmesh
 + *
 +*/
 +
 +/*
 + * EDITMESH CORNERS TO LOOPS
 + * 
 + * Converts editmesh face corner data
 + * (UVs, Vert colors, ect) to N-Gon 
 + * face-edge ('loop') data.
 + *
 +*/
 +
 +static void editmesh_corners_to_loops(BMesh *bm, CustomData *facedata, void *face_block, BMFace *f,int numCol, int numTex){
 +      int i, j;
 +      BMLoop *l;
 +      MTFace *texface;
 +      MTexPoly *texpoly;
 +      MCol *mcol;
 +      MLoopCol *mloopcol;
 +      MLoopUV *mloopuv;
 +      BMIter iter;
 +
 +      for(i=0; i < numTex; i++){
 +              texface = CustomData_em_get_n(facedata, face_block, CD_MTFACE, i);
 +              texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i);
 +              
 +              texpoly->tpage = texface->tpage;
 +              texpoly->flag = texface->flag;
 +              texpoly->transp = texface->transp;
 +              texpoly->mode = texface->mode;
 +              texpoly->tile = texface->tile;
 +              texpoly->unwrap = texface->unwrap;
 +              
 +              for (j=0, l=BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, f); l; j++, l=BMIter_Step(&iter)) {
 +                      mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i);
 +                      mloopuv->uv[0] = texface->uv[j][0];
 +                      mloopuv->uv[1] = texface->uv[j][1];
 +              }
 +
 +      }
 +      for(i=0; i < numCol; i++){
 +              mcol = CustomData_em_get_n(facedata, face_block, CD_MCOL, i);
 +              for (j=0, l=BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, f); l; j++, l=BMIter_Step(&iter)) {
 +                      mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i);
 +                      mloopcol->r = mcol[j].r;
 +                      mloopcol->g = mcol[j].g;
 +                      mloopcol->b = mcol[j].b;
 +                      mloopcol->a = mcol[j].a;
 +              }
 +      }
 +}
 +
 +/*
 + * EDITVERT TO BMVert
 + *
 + * Converts an editvert to
 + * a BMVert.
 + *
 +*/
 +
 +static BMVert *editvert_to_BMVert(BMesh *bm, EditMesh *em, EditVert *eve)
 +{
 +              BMVert *v = NULL;
 +
 +              v = BM_Make_Vert(bm, eve->co, NULL);
++              VECCOPY(v->no, eve->no);
++
 +              /*transfer flags*/
 +              v->head.flag = eve->h ? BM_HIDDEN : 0;
 +              if(eve->f & SELECT) BM_Select_Vert(bm, v, 1);
 +              v->bweight = eve->bweight;
 +
 +              /*Copy Custom Data*/
 +              CustomData_bmesh_copy_data(&em->vdata, &bm->vdata, eve->data, &v->data);
 +              
 +              return v;
 +}     
 +
 +/*
 + * EDITEDGE TO BMEdge
 + *
 + * Converts an editedge to 
 + * a BMEdge
 + *
 +*/
 +
 +static void editedge_to_BMEdge_internal(BMesh *bm, EditMesh *em, BMEdge *e, EditEdge *eed)
 +{
 +      e->crease = eed->crease;
 +      e->bweight = eed->bweight;
 +      
 +      e->head.flag = eed->f & SELECT ? BM_SELECT : 0;
 +      e->head.flag |= eed->seam ? BM_SEAM : 0;
 +      e->head.flag |= eed->h & 1 ? BM_HIDDEN : 0;
 +      e->head.flag |= eed->h & EM_FGON ? BM_FGON : 0;
 +      e->head.flag |= eed->sharp ? BM_SHARP : 0;
 +
 +      CustomData_bmesh_copy_data(&em->edata, &bm->edata, eed->data, &e->data);
 +}
 +
 +static BMEdge *editedge_to_BMEdge(BMesh *bm, EditMesh *em, EditEdge *eed)
 +{
 +              BMVert *v1 = NULL, *v2 = NULL;
 +              BMEdge *e = NULL;
 +              
 +              v1 = eed->v1->tmp.p;
 +              v2 = eed->v2->tmp.p;
 +      
 +              e = BM_Make_Edge(bm, v1, v2,NULL, 0); 
 +
 +              editedge_to_BMEdge_internal(bm, em, e, eed);
 +
 +              return e;
 +}
 +/*
 + * EDITFACE TO BMFace
 + *
 + * Converts an editface to a BMFace.
 + * Note that this also convert per-face
 + * corner data as well.
 + *
 +*/
 +
 +static BMFace *editface_to_BMFace(BMesh *bm, EditMesh *em, EditFace *efa, int numCol, int numTex)
 +{
 +              BMVert *v1 = NULL, *v2 = NULL;
 +              BMFace *f = NULL;
 +              BMEdge *edar[4];
 +              int len;
 +
 +              edar[0] = BM_Make_Edge(bm, efa->v1->tmp.p, efa->v2->tmp.p, NULL, 1); 
 +              edar[1] = BM_Make_Edge(bm, efa->v2->tmp.p, efa->v3->tmp.p, NULL, 1); 
 +              if(efa->v4){
 +                      edar[2] = BM_Make_Edge(bm, efa->v3->tmp.p, efa->v4->tmp.p, NULL, 1); 
 +                      edar[3] = BM_Make_Edge(bm, efa->v4->tmp.p, efa->v1->tmp.p, NULL, 1); 
 +              }else{
 +                      edar[2] = BM_Make_Edge(bm, efa->v3->tmp.p, efa->v1->tmp.p, NULL, 1); 
 +              }
 +
 +              editedge_to_BMEdge_internal(bm, em, edar[0], efa->e1);
 +              editedge_to_BMEdge_internal(bm, em, edar[1], efa->e2);
 +              editedge_to_BMEdge_internal(bm, em, edar[2], efa->e3);
 +              if(efa->v4)
 +                      editedge_to_BMEdge_internal(bm, em, edar[3], efa->e4);
 +
 +
 +              if(efa->e1->fgoni) edar[0]->head.flag |= BM_FGON;
 +              if(efa->e2->fgoni) edar[1]->head.flag |= BM_FGON;
 +              if(efa->e3->fgoni) edar[2]->head.flag |= BM_FGON;
 +              if(efa->v4 && efa->e4->fgoni) edar[3]->head.flag |= BM_FGON;
 +
 +              if(efa->v4) len = 4;
 +              else len = 3;
 +
 +              /*find v1 and v2*/
 +              v1 = efa->v1->tmp.p;
 +              v2 = efa->v2->tmp.p;
 +
 +              f = BM_Make_Ngon(bm, v1, v2, edar, len, 0);
 +              f->head.flag = 0;
 +              f->mat_nr = efa->mat_nr;
 +              if(efa->f & SELECT) BM_Select_Face(bm, f, 1);
 +              if(efa->h) f->head.flag |= BM_HIDDEN;
 +              
 +              CustomData_bmesh_copy_data(&em->fdata, &bm->pdata, efa->data, &f->data);
 +              editmesh_corners_to_loops(bm, &em->fdata, efa->data, f,numCol,numTex);
 +
 +              return f;
 +}
 +
 +/*
 + * BMESH FGONCONVERT
 + *
 + * This function and its associated structures
 + * /helpers (fgonsort, sortfgon, fuse_fgon) are
 + * used to convert f-gons to bmesh n-gons. This
 + * is accomplished by sorting a list of fgon faces
 + * such that faces that are part of the same fgon
 + * are next to each other. These faces are then
 + * converted as is into bmesh faces and
 + * fused togather.
 + *
 + * Note that currently, there is no support for 
 + * holes in faces in the bmesh structure, so 
 + * f-gons with holes will only partially convert.
 + *
 +*/
 +
 +typedef struct fgonsort {
 +      unsigned long x;
 +      struct EditFace *efa;
 +      struct BMFace *f;
 +      int done;
 +}fgonsort;
 +
 +static int sortfgon(const void *v1, const void *v2)
 +{
 +      const struct fgonsort *x1=v1, *x2=v2;
 +      
 +      if( x1->x > x2->x ) return 1;
 +      else if( x1->x < x2->x) return -1;
 +      return 0;
 +}
 +
 +static void fuse_fgon(BMesh *bm, BMFace *f)
 +{
 +      BMFace *sf;
 +      BMLoop *l;
 +      int done;
 +
 +      sf = f;
 +      done = 0;
 +      while(!done){
 +              done = 1;
 +              l = sf->loopbase;
 +              do{
 +                      if(l->e->head.flag & BM_FGON){ 
 +                              sf = BM_Join_Faces(bm,l->f, ((BMLoop*)l->radial.next->data)->f, l->e, 0,0);
 +                              if(sf){
 +                                      done = 0;
 +                                      break;
 +                              } else { /*we have to get out of here...*/
 +                                      return;
 +                              }
 +                      }
 +                      l = ((BMLoop*)(l->head.next));
 +              }while(l != sf->loopbase);
 +      }
 +}
 +
 +static BM_fgonconvert(BMesh *bm, EditMesh *em, int numCol, int numTex)
 +{
 +      EditFace *efa;
 +      struct fgonsort *sortblock, *sb, *sb1;
 +      int a, b, amount=0;
 +
 +      /*zero out efa->tmp, we store fgon index here*/
 +      for(efa = em->faces.first; efa; efa = efa->next){ 
 +              efa->tmp.l = 0;
 +              amount++;
 +      }
 +      /*go through and give each editface an fgon index*/
 +      for(efa = em->faces.first; efa; efa = efa->next){
 +              if(efa->e1->fgoni) efa->tmp.l = efa->e1->fgoni;
 +              else if(efa->e2->fgoni) efa->tmp.l = efa->e2->fgoni;
 +              else if(efa->e3->fgoni) efa->tmp.l = efa->e3->fgoni;
 +              else if(efa->e4 && efa->e4->fgoni) efa->tmp.l = efa->e4->fgoni;
 +      }
 +
 +      sb= sortblock= MEM_mallocN(sizeof(fgonsort)* amount,"fgon sort block");
 +
 +      for(efa = em->faces.first; efa; efa=efa->next){
 +              sb->x = efa->tmp.l;
 +              sb->efa = efa;
 +              sb->done = 0;
 +              sb++;
 +      }
 +
 +      qsort(sortblock, amount, sizeof(fgonsort), sortfgon);
 +
 +      sb = sortblock;
 +      for(a=0; a<amount; a++, sb++) {
 +              if(sb->x && sb->done == 0){
 +                      /*first pass: add in faces for this fgon*/
 +                      for(b=a, sb1 = sb; b<amount && sb1->x == sb->x; b++, sb1++){
 +                              efa = sb1->efa;
 +                              sb1->f = editface_to_BMFace(bm, em, efa, numCol, numTex);
 +                              sb1->done = 1;
 +                      }
 +                      /*fuse fgon*/
 +                      fuse_fgon(bm, sb->f);
 +              }
 +      }
 +      MEM_freeN(sortblock);
 +}
 +
 +/*
 + * TAG WIRE EDGES
 + *
 + * Flags editedges 'f1' member
 + * if the edge has no faces.
 + *
 +*/
 +
 +static void tag_wire_edges(EditMesh *em){
 +      EditFace *efa;
 +      EditEdge *eed;
 +      for(eed = em->edges.first; eed; eed = eed->next) eed->f1 = 1;
 +      for(efa = em->faces.first; efa; efa = efa->next){
 +              efa->e1->f1 = 0;
 +              efa->e2->f1 = 0;
 +              efa->e3->f1 = 0;
 +              if(efa->e4) efa->e4->f1 = 0;
 +      }
 +}
 +
 +/*
 + * EDITMESH TO BMESH
 + *
 + * Function to convert an editmesh to a bmesh
 + * Currently all custom data as well as 
 + * f-gons should be converted correctly.
 + *
 +*/
 +
 +BMesh *editmesh_to_bmesh_intern(EditMesh *em, BMesh *bm) {
 +      BMVert *v;
 +      EditVert *eve;
 +      EditEdge *eed;
 +      EditFace *efa;
 +      int allocsize[4] = {512,512,2048,512}, numTex, numCol;
 +
 +      /*make sure to update FGon flags*/
 +      EM_fgon_flags(em);
 +
 +      /*copy custom data layout*/
 +      CustomData_copy(&em->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
 +      CustomData_copy(&em->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
 +      CustomData_copy(&em->fdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
 +
 +      /*copy face corner data*/
 +      CustomData_to_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata);
 +      /*initialize memory pools*/
 +      CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
 +      CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
 +      CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]);
 +      CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]);
 +      /*needed later*/
 +      numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
 +      numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
 +
 +      /*copy over selection mode*/
 +      bm->selectmode = 0;
 +      if(em->selectmode & SCE_SELECT_VERTEX) bm->selectmode |= BM_VERT;
 +      if(em->selectmode & SCE_SELECT_EDGE) bm->selectmode |= BM_EDGE;
 +      if(em->selectmode & SCE_SELECT_FACE) bm->selectmode |= BM_FACE;
 +
 +
 +      /*begin editloop*/
 +      //BM_Begin_Edit(bm);
 +
 +      /*tag wire edges*/
 +      tag_wire_edges(em);
 +
 +      /*add verts*/
 +      for(eve = em->verts.first; eve; eve = eve->next){
 +              v = editvert_to_BMVert(bm, em, eve);
 +              eve->tmp.p = v;
 +      }
 +      /*convert f-gons*/
 +      BM_fgonconvert(bm, em, numCol, numTex);
 +      
 +      /*do quads + triangles*/
 +      for(efa = em->faces.first; efa; efa = efa->next){
 +              if(!efa->tmp.l) editface_to_BMFace(bm, em, efa, numCol, numTex);
 +      }
 +
 +      /*add wire edges*/      
 +      for(eed = em->edges.first; eed; eed = eed->next){
 +              if(eed->f1) editedge_to_BMEdge(bm, em, eed);
 +      }
 +      //BM_end_edit(bm, BM_CALC_NORM);
 +      return bm;
 +}
 +
 +void edit2bmesh_exec(BMesh *bmesh, BMOperator *op)
 +{
 +      editmesh_to_bmesh_intern(op->slots[BMOP_FROM_EDITMESH_EM].data.p, bmesh);
 +}
 +
 +BMesh *editmesh_to_bmesh(EditMesh *em)
 +{
 +      BMOperator conv;
 +      BMesh *bm;
 +      int allocsize[4] = {512,512,2048,512}, numTex, numCol;
 +
 +      /*allocate a bmesh*/
 +      bm = BM_Make_Mesh(allocsize);
 +
 +      BMO_Init_Op(&conv, BMOP_FROM_EDITMESH);
 +      BMO_Set_Pnt(&conv, BMOP_FROM_EDITMESH_EM, em);
 +      BMO_Exec_Op(bm, &conv);
 +      BMO_Finish_Op(bm, &conv);
 +
 +      return bm;
 +}
index e47dfa7de815b5756a46e9de0564431ac480a271,0000000000000000000000000000000000000000..e8da75996423eb1a13db1894f2f2ffb909400d49
mode 100644,000000..100644
--- /dev/null
@@@ -1,529 -1,0 +1,549 @@@
-                           int numcuts, int beauty, float rad);
 +#include "MEM_guardedalloc.h"
 +
 +#include "BKE_utildefines.h"
 +
 +#include "BLI_arithb.h"
 +#include "BLI_rand.h"
 +
 +#include "DNA_object_types.h"
 +
 +#include "ED_mesh.h"
 +
 +#include "bmesh.h"
 +#include "mesh_intern.h"
 +
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <string.h>
 +#include <math.h>
 +
 +#define SUBD_SPLIT    1
 +#define FACE_NEW      1
 +#define MAX_FACE      800
 +
++/*
++NOTE: beauty has been renamed to flag!
++*/
++
 +/*
 +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*/
 +      void (*connectexec)(BMesh *bm, BMFace *face, BMVert **verts, 
- static void alter_co(float *co, BMEdge *edge, float rad, int beauty, float perc)
++                          int numcuts, int flag, float rad);
 +      int len; /*total number of verts*/
 +} 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?
 +*/
 +
 +
 +/* calculates offset for co, based on fractal, sphere or smooth settings  */
-       if(beauty & B_SMOOTH) {
++static void alter_co(float *co, BMEdge *edge, float rad, int flag, float perc,
++                   BMVert *vsta, BMVert *vend)
 +{
 +      float vec1[3], fac;
 +      
-               VecSubf(nor, edge->v1->co, edge->v2->co);
++      if(flag & B_SMOOTH) {
 +              /* we calculate an offset vector vec1[], to be added to *co */
 +              float len, fac, nor[3], nor1[3], nor2[3];
 +              
-               VECCOPY(nor1, edge->v1->no);
-               VECCOPY(nor2, edge->v2->no);
++              VecSubf(nor, vsta->co, vend->co);
 +              len= 0.5f*Normalize(nor);
 +      
-                       fac= rad* VecLenf(edge->v1->co, edge->v2->co);
++              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]+= fac*nor2[0];
 +              vec1[1]+= fac*nor2[1];
 +              vec1[2]+= fac*nor2[2];
 +              
 +              vec1[0]*= rad*len;
 +              vec1[1]*= rad*len;
 +              vec1[2]*= rad*len;
 +              
 +              co[0] += vec1[0];
 +              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 */
- /* percent defines the interpolation, rad and beauty are for special options */
++                      fac= 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);
 +              }
 +
 +      }
 +}
 +
 +/* assumes in the edge is the correct interpolated vertices already */
-                                        int beauty, float percent, BMEdge **out)
++/* 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, float rad, 
-       alter_co(ev->co, edge, rad, beauty, percent);
++                                       int flag, float percent, BMEdge **out,
++                                       BMVert *vsta, BMVert *vend)
 +{
 +      BMVert *ev;
 +//    float co[3];
 +      
 +      ev = BM_Split_Edge(bm, edge->v1, edge, out, percent, 1);
 +
 +      /* offset for smooth or sphere or fractal */
-                               int beauty, BMEdge **newe)
++      alter_co(ev->co, edge, rad, flag, percent, 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, 
 +                              int curpoint, int totpoint, float rad, 
-       if (beauty & (B_PERCENTSUBD) && totpoint == 1)
++                              int flag, BMEdge **newe,
++                              BMVert *vsta, BMVert *vend)
 +{
 +      BMVert *ev;
 +      float percent;
 +       
-               ev= bm_subdivide_edge_addvert(bm, edge, rad, beauty, percent, newe);
++      if (flag & (B_PERCENTSUBD) && totpoint == 1)
 +              /*I guess the idea is vertices store what
 +                percent to use?*/
 +              //percent=(float)(edge->tmp.l)/32768.0f;
 +              percent= 1.0; //edge->tmp.fp;
 +      else {
 +              percent= 1.0f/(float)(totpoint+1-curpoint);
 +
 +      }
 +      
 +      /*{
 +              float co[3], co2[3];
 +              VecSubf(co, edge->v2->co, edge->v1->co);
 +              VecMulf(co, 1.0f/(float)(totpoint+1-curpoint));
 +              VecAddf(co2, edge->v1->co, co);
 +*/
-                                 int beauty, int numcuts) {
++              ev= bm_subdivide_edge_addvert(bm, edge, rad, flag, percent, 
++                                     newe, vsta, vend);
 +/*            VECCOPY(ev->co, co2);
 +      }
 +*/    
 +      return ev;
 +}
 +
 +static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, float rad,
-               v = subdivideedgenum(bm, eed, i, numcuts, rad, beauty, &newe);
++                                int flag, int numcuts, 
++                                BMVert *vsta, BMVert *vend) {
 +      BMEdge *eed = edge, *newe;
 +      BMVert *v;
 +      int i;
 +
 +      for(i=0;i<numcuts;i++) {
-                         int beauty, float rad) {
++              v = subdivideedgenum(bm, eed, i, numcuts, rad, 
++                      flag, &newe, vsta, vend);
 +              BMO_SetFlag(bm, v, SUBD_SPLIT);
 +              BMO_SetFlag(bm, eed, SUBD_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 **vlist, int numcuts,
-                            int numcuts, int beauty, float rad) {
++                        int flag, float rad) {
 +      BMFace *nf;
 +      int i, add;
 +
 +      /*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;
 +                      BM_Connect_Verts(bm, vlist[i], vlist[numcuts+add], &nf);
 +              }
 +      } else {
 +              add = 2;
 +              for (i=0; i<numcuts; i++) {
 +                      BM_Connect_Verts(bm, vlist[i], vlist[numcuts+add], &nf);
 +                      if (i == numcuts/2) {
 +                              add -= 1;
 +                              BM_Connect_Verts(bm, vlist[i], vlist[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 **vlist, 
-                            int numcuts, int beauty, float rad) {
++                           int numcuts, int flag, float rad) {
 +      BMFace *nf;
 +      int i;
 +      
 +      for (i=0; i<numcuts; i++) {
 +              BM_Connect_Verts(bm, vlist[i], vlist[(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 **vlist, 
-                            int numcuts, int beauty, float rad) {
++                           int numcuts, int flag, float rad) {
 +      BMFace *nf;
 +      int i;
 +      
 +      for (i=0; i<numcuts; i++) {
 +              BM_Connect_Verts(bm, vlist[i], vlist[numcuts+(numcuts-i)], &nf);
 +      }
 +      BM_Connect_Verts(bm, vlist[numcuts*2+3], vlist[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 **vlist, 
-                         int beauty, float rad) {
++                           int numcuts, int flag, float rad) {
 +      BMFace *nf;
 +      int i, add=0;
 +      
 +      for (i=0; i<numcuts; i++) {
 +              if (i == numcuts/2) {
 +                      if (numcuts % 2 != 0) {
 +                              BM_Connect_Verts(bm, vlist[numcuts-i-1+add], vlist[i+numcuts+1], &nf);
 +                      }
 +                      add = numcuts*2+2;
 +              }
 +              BM_Connect_Verts(bm, vlist[numcuts-i-1+add], vlist[i+numcuts+1], &nf);
 +      }
 +
 +      for (i=0; i<numcuts/2+1; i++) {
 +              BM_Connect_Verts(bm, vlist[i], vlist[(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 **vlist, int numcuts,
-       BMVert *v;
++                        int flag, float rad) {
 +      BMFace *nf;
-               lines[(i+1)*s] = vlist[a];
-               lines[(i+1)*s + s-1] = vlist[b];
++      BMVert *v, *v1, *v2;
 +      BMEdge *e, *ne;
 +      BMVert **lines = MEM_callocN(sizeof(BMVert*)*(numcuts+2)*(numcuts+2),
 +                                   "q_4edge_split");
 +      int i, j, a, b, s=numcuts+2, totv=numcuts*4+4;
 +
 +      /*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] = vlist[numcuts*3+2+(numcuts-i+1)];
 +      }
 +
 +      /*last line*/
 +      for (i=0; i<numcuts+2; i++) {
 +              lines[(s-1)*s+i] = vlist[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 = BM_Connect_Verts(bm, vlist[a], vlist[b], &nf);
 +              
-                       v = subdivideedgenum(bm, e, a, numcuts, rad, beauty, &ne);
++              v1 = lines[(i+1)*s] = vlist[a];
++              v2 = lines[(i+1)*s + s-1] = vlist[b];
 +
 +              for (a=0; a<numcuts; a++) {
-       /*
-       for (i=0; i<numcuts; i++) {
-               a = i;
-               b = numcuts + 1 + numcuts + 1 + (numcuts - i - 1);
-               BM_Connect_Verts(bm, vlist[a], vlist[b], &nf);
-       }*/
++                      v = subdivideedgenum(bm, e, a, numcuts, rad, flag, &ne,
++                                           v1, v2);
 +                      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;
 +                      BM_Connect_Verts(bm, lines[a], lines[b], &nf);
 +              }
 +      }
 +
-               bm_subdivide_multicut(bmesh, edge, rad, flag, numcuts);
 +      MEM_freeN(lines);
 +}
 +
 +subdpattern q_4edge = {
 +      {1, 1, 1, 1},
 +      q_4edge_split,
 +      4,
 +};
 +
 +subdpattern *patterns[] = {
 +      &q_1edge,
 +      &q_2edge_op,
 +      &q_4edge,
 +      &q_3edge,
 +      &q_2edge,
 +};
 +
 +#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[MAX_FACE];
 +      BMFace *face;
 +      BMLoop *nl;
 +      BMVert *verts[MAX_FACE];
 +      BMIter fiter, liter;
 +      subdpattern *pat;
 +      float rad;
 +      int i, j, matched, a, b, numcuts, flag, selaction;
 +      subd_facedata *facedata = NULL;
 +      V_DECLARE(facedata);
 +      
 +      BMO_Flag_Buffer(bmesh, op, BMOP_ESUBDIVIDE_EDGES, SUBD_SPLIT);
 +      
 +      numcuts = BMO_GetSlot(op, BMOP_ESUBDIVIDE_NUMCUTS)->data.i;
 +      flag = BMO_GetSlot(op, BMOP_ESUBDIVIDE_FLAG)->data.i;
 +      rad = BMO_GetSlot(op, BMOP_ESUBDIVIDE_RADIUS)->data.f;
 +      selaction = BMO_GetSlot(op, BMOP_ESUBDIVIDE_SELACTION)->data.i;
 +
 +      einput = BMO_GetSlot(op, BMOP_ESUBDIVIDE_EDGES);
 +      
 +      /*first go through and split edges*/
 +      for (i=0; i<einput->len; i++) {
 +              edge = ((BMEdge**)einput->data.p)[i];
 +              BMO_SetFlag(bmesh, edge, SUBD_SPLIT);
 +      }
 +      
 +      for (face=BMIter_New(&fiter, bmesh, BM_FACES, NULL);
 +           face; face=BMIter_Step(&fiter)) {
 +              /*figure out which pattern to use*/
 +              if (face->len > MAX_FACE) continue;
 +
 +              i = 0;
 +              for (nl=BMIter_New(&liter, bmesh, BM_LOOPS_OF_FACE, face);
 +                   nl; nl=BMIter_Step(&liter)) {
 +                      edges[i] = nl->e;
 +                      verts[i] = nl->v;
 +                      i++;
 +              }
 +
 +              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;
 +                              }
 +                      }
 +              }
 +      }
 +
 +      /*go through and split edges*/
 +      for (i=0; i<einput->len; i++) {
 +              edge = ((BMEdge**)einput->data.p)[i];
- void BM_esubdivideflag(Object *obedit, BMesh *bm, int flag, float rad, 
-                      int beauty, int numcuts, int seltype) {
++              bm_subdivide_multicut(bmesh, edge, rad, flag, numcuts,
++                                    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, NULL);
 +           face; face=BMIter_Step(&fiter)) {
 +              /*figure out which pattern to use*/
 +              if (face->len > MAX_FACE) continue;
 +              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++;
 +              }
 +
 +              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, numcuts, flag, rad);
 +              i++;
 +      }
 +
 +      if (facedata) V_FREE(facedata);
 +}
 +
 +/*editmesh-emulating function*/
-       BMO_Set_Int(&op, BMOP_ESUBDIVIDE_FLAG, beauty);
++void BM_esubdivideflag(Object *obedit, BMesh *bm, int selflag, float rad, 
++                     int flag, int numcuts, int seltype) {
 +      BMOperator op;
 +
 +      BMO_Init_Op(&op, BMOP_ESUBDIVIDE);
++      
 +      BMO_Set_Int(&op, BMOP_ESUBDIVIDE_NUMCUTS, numcuts);
-       BMO_HeaderFlag_To_Slot(bm, &op, BMOP_ESUBDIVIDE_EDGES, flag, BM_EDGE);
++      BMO_Set_Int(&op, BMOP_ESUBDIVIDE_FLAG, flag);
 +      BMO_Set_Float(&op, BMOP_ESUBDIVIDE_RADIUS, rad);
 +      BMO_Set_Int(&op, BMOP_ESUBDIVIDE_SELACTION, seltype);
++      BMO_HeaderFlag_To_Slot(bm, &op, BMOP_ESUBDIVIDE_EDGES, selflag, BM_EDGE);
 +      
 +      BMO_Exec_Op(bm, &op);
 +      BMO_Finish_Op(bm, &op);
 +}
++
++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);
++}
index 65c2930b7585867c79d0dd6cab5d13b44a55acab,7860a1a7b10f02c56a876dd8208888c133da3b4f..49f785cfe52b71cbb677ab1abdee42c5738369ca
@@@ -3290,90 -3444,11 +3445,95 @@@ void MESH_OT_de_select_all(wmOperatorTy
        /* api callbacks */
        ot->exec= toggle_select_all_exec;
        ot->poll= ED_operator_editmesh;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
  }
  
-       BIF_undo_push("BMesh Test");
 +static int bmesh_test_exec(bContext *C, wmOperator *op)
 +{
 +      Object *obedit= CTX_data_edit_object(C);
 +      EditMesh *em= ((Mesh *)obedit->data)->edit_mesh;
 +      EditMesh *em2;
 +      BMesh *bm;
 +
 +      bm = editmesh_to_bmesh(em);
 +
 +#if 1 /*edge subdivide test*/
++      //BM_esubdivideflag(obedit, bm, SELECT, 0.292f*5.0, B_SMOOTH, G.rt==0?1:G.rt, 0);
 +      BM_esubdivideflag(obedit, bm, SELECT, 0, 0, G.rt==0?1:G.rt, 0);
++
 +#endif
 +
 +#if 0
 +      /*dissolve vert test*/
 +      {
 +                      BMOperator op;
 +                      BMOpSlot *eoutput, *foutput;
 +                      int i;
 +                      
 +                      BMO_Init_Op(&op, BMOP_DISSOLVE_VERTS);
 +                      BMO_HeaderFlag_To_Slot(bm, &op, BMOP_DISVERTS_VERTIN, BM_SELECT, BM_VERT);
 +                      BMO_Exec_Op(bm, &op);
 +                      
 +                      BMO_Finish_Op(bm, &op);                 
 +      }
 +#endif
 +
 +#if 0
 +      /*triangulator test code*/
 +      {
 +                      BMOperator op;
 +                      BMOpSlot *eoutput, *foutput;
 +                      int i;
 +                      
 +                      BMO_Init_Op(&op, BMOP_TRIANGULATE);
 +                      BMO_HeaderFlag_To_Slot(bm, &op, BMOP_TRIANG_FACEIN, BM_SELECT, BM_FACE);
 +                      BMO_Exec_Op(bm, &op);
 +                      
 +                      eoutput = BMO_GetSlot(&op, BMOP_TRIANG_NEW_EDGES);
 +                      foutput = BMO_GetSlot(&op, BMOP_TRIANG_NEW_FACES);
 +                      
 +                      /*select new faces/edges*/
 +                      for (i=0; i<eoutput->len; i++) {
 +                              BM_Select(bm, ((void**)eoutput->data.buf)[i], 1);
 +                      }
 +                      
 +                      for (i=0; i<foutput->len; i++) {
 +                              BM_Select(bm, ((void**)foutput->data.buf)[i], 1);
 +                      }
 +                      
 +                      BMO_Finish_Op(bm, &op);
 +                      
 +      }
 +#endif
 +      em2 = bmesh_to_editmesh(bm);
 +      
 +      /*free em's data, then copy the contents of the em2 struct
 +        to em, then free the em2 struct.*/
 +      free_editMesh(em);
 +      *em = *em2;
 +      MEM_freeN(em2); 
 +      
 +      BM_Free_Mesh(bm);
 +
 +      WM_event_add_notifier(C, NC_OBJECT|ND_DRAW|ND_TRANSFORM|ND_GEOM_SELECT, obedit);
 +      return OPERATOR_FINISHED;
 +}
 +
 +void MESH_OT_bmesh_test(wmOperatorType *ot)
 +{
 +      /* identifiers */
 +      ot->name= "bmesh test op";
 +      ot->idname= "MESH_OT_bmesh_test";
 +      
 +      /* api callbacks */
 +      ot->exec= bmesh_test_exec;
 +      ot->poll= ED_operator_editmesh;
++
++      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 +}
 +
  /* ******************** **************** */
  
  void EM_select_more(EditMesh *em)
index 37d18be18200172b6979996b1aeef02a129b6478,a8a417f1622f6d68baf6bbbdd820e634aa327b42..58401d79bf12c3bbc0cab64708f4ab62e6b766c9
@@@ -173,21 -172,29 +178,30 @@@ extern struct EditFace *EM_face_from_fa
  
  
  /* ******************* editmesh_mods.c */
+ void MESH_OT_loop_select(struct wmOperatorType *ot);
  void MESH_OT_de_select_all(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_selectswap_mesh(struct wmOperatorType *ot);
+ void MESH_OT_select_invert(struct wmOperatorType *ot);
  void MESH_OT_select_non_manifold(struct wmOperatorType *ot);
- void MESH_OT_selectconnected_mesh_all(struct wmOperatorType *ot);
- void MESH_OT_selectconnected_mesh(struct wmOperatorType *ot);
- void MESH_OT_hide_mesh(struct wmOperatorType *ot);
- void MESH_OT_reveal_mesh(struct wmOperatorType *ot);
- void MESH_OT_righthandfaces(struct wmOperatorType *ot);
+ void MESH_OT_select_linked(struct wmOperatorType *ot);
+ void MESH_OT_select_linked_pick(struct wmOperatorType *ot);
+ void MESH_OT_hide(struct wmOperatorType *ot);
+ void MESH_OT_reveal(struct wmOperatorType *ot);
+ void MESH_OT_consistant_normals(struct wmOperatorType *ot);
  void MESH_OT_select_linked_flat_faces(struct wmOperatorType *ot);
  void MESH_OT_select_sharp_edges(struct wmOperatorType *ot);
 -extern EditEdge *findnearestedge(ViewContext *vc, int *dist);
+ void MESH_OT_shortest_path_select(struct wmOperatorType *ot);
+ void MESH_OT_similar_vertex_select(struct wmOperatorType *ot);
+ void MESH_OT_similar_edge_select(struct wmOperatorType *ot);
+ void MESH_OT_similar_face_select(struct wmOperatorType *ot);
+ void MESH_OT_select_random(struct wmOperatorType *ot);
+ void MESH_OT_vertices_to_sphere(struct wmOperatorType *ot);
+ void MESH_OT_selection_type(struct wmOperatorType *ot);
+ void MESH_OT_select_multi_loop(struct wmOperatorType *ot);
 +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 */