code cleanup: make bmesh operator names more consistant since python has access to...
[blender.git] / source / blender / bmesh / operators / bmo_subdivide.c
index 50b66abd703d61681caf67179bdaed2183fbe11a..5032545af89c9aa830d89a1d655f1b728591b90e 100644 (file)
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/** \file blender/bmesh/operators/bmo_subdivide.c
+ *  \ingroup bmesh
+ */
+
 #include "MEM_guardedalloc.h"
 
 #include "BLI_math.h"
 
 #include "DNA_object_types.h"
 
-#include "ED_mesh.h"
-
 #include "bmesh.h"
-#include "bmesh_private.h"
+#include "intern/bmesh_private.h"
 
-#include "bmesh_operators_private.h" /* own include */
+#include "intern/bmesh_operators_private.h" /* own include */
 
 #include "bmo_subdivide.h" /* own include */
 
@@ -51,6 +53,9 @@
 #define ELE_INNER      8
 #define ELE_SPLIT      16
 
+/* see bug [#32665], 0.00005 means a we get face splits at a little under 1.0 degrees */
+#define FLT_FACE_SPLIT_EPSILON 0.00005f
+
 /*
  * NOTE: beauty has been renamed to flag!
  */
@@ -75,7 +80,7 @@ static BMEdge *connect_smallest_face(BMesh *bm, BMVert *v1, BMVert *v2, BMFace *
 
        /* 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. */
+        * face is "best" and who knows what for non-manifold conditions. */
        for (face = BM_iter_new(&iter, bm, BM_FACES_OF_VERT, v1); face; face = BM_iter_step(&iter)) {
                for (v = BM_iter_new(&iter2, bm, BM_VERTS_OF_FACE, face); v; v = BM_iter_step(&iter2)) {
                        if (v == v2) {
@@ -85,7 +90,7 @@ static BMEdge *connect_smallest_face(BMesh *bm, BMVert *v1, BMVert *v2, BMFace *
        }
 
        if (curf) {
-               face = BM_face_split(bm, curf, v1, v2, &nl, NULL);
+               face = BM_face_split(bm, curf, v1, v2, &nl, NULL, FALSE);
                
                if (r_nf) *r_nf = face;
                return nl ? nl->e : NULL;
@@ -94,19 +99,24 @@ static BMEdge *connect_smallest_face(BMesh *bm, BMVert *v1, BMVert *v2, BMFace *
        return NULL;
 }
 /* calculates offset for co, based on fractal, sphere or smooth settings  */
-static void alter_co(BMesh *bm, BMVert *v, BMEdge *UNUSED(origed), const subdparams *params, float perc,
+static void alter_co(BMesh *bm, BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params, float perc,
                      BMVert *vsta, BMVert *vend)
 {
        float tvec[3], prev_co[3], fac;
        float *co = NULL;
        int i, totlayer = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY);
        
-       BM_vert_normal_update_all(bm, v);
+       BM_vert_normal_update_all(v);
 
        co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, params->origkey);
+       copy_v3_v3(co, v->co);
        copy_v3_v3(prev_co, co);
 
-       if (params->beauty & B_SMOOTH) {
+       if (UNLIKELY(params->use_sphere)) { /* subdivide sphere */
+               normalize_v3(co);
+               mul_v3_fl(co, params->smooth);
+       }
+       else if (params->use_smooth) {
                /* we calculate an offset vector vec1[], to be added to *co */
                float len, nor[3], nor1[3], nor2[3], smooth = params->smooth;
 
@@ -117,7 +127,7 @@ static void alter_co(BMesh *bm, BMVert *v, BMEdge *UNUSED(origed), const subdpar
                copy_v3_v3(nor2, vend->no);
 
                /* cosine angle */
-               fac dot_v3v3(nor, nor1);
+               fac = dot_v3v3(nor, nor1);
                mul_v3_v3fl(tvec, nor1, fac);
 
                /* cosine angle */
@@ -125,40 +135,37 @@ static void alter_co(BMesh *bm, BMVert *v, BMEdge *UNUSED(origed), const subdpar
                madd_v3_v3fl(tvec, nor2, fac);
 
                /* falloff for multi subdivide */
-               smooth *= sqrtf(fabsf(1.0f - 2.0f * fabsf(0.5f-perc)));
+               smooth *= sqrtf(fabsf(1.0f - 2.0f * fabsf(0.5f - perc)));
 
                mul_v3_fl(tvec, smooth * len);
 
                add_v3_v3(co, tvec);
        }
-       else if (params->beauty & B_SPHERE) { /* subdivide sphere */
-               normalize_v3(co);
-               mul_v3_fl(co, params->smooth);
-       }
 
-       if (params->beauty & B_FRACTAL) {
+       if (params->use_fractal) {
                float len = len_v3v3(vsta->co, vend->co);
-               float vec2[3] = {0.0f, 0.0f, 0.0f}, co2[3];
+               float normal[3] = {0.0f, 0.0f, 0.0f}, co2[3], base1[3], base2[3];
 
                fac = params->fractal * len;
 
-               add_v3_v3(vec2, vsta->no);
-               add_v3_v3(vec2, vend->no);
-               mul_v3_fl(vec2, 0.5f);
+               mid_v3_v3v3(normal, vsta->no, vend->no);
+               ortho_basis_v3v3_v3(base1, base2, normal);
 
                add_v3_v3v3(co2, v->co, params->off);
-               tvec[0] = fac * (BLI_gTurbulence(1.0, co2[0], co2[1], co2[2], 15, 0, 1) - 0.5f);
-               tvec[1] = fac * (BLI_gTurbulence(1.0, co2[0], co2[1], co2[2], 15, 0, 1) - 0.5f);
-               tvec[2] = fac * (BLI_gTurbulence(1.0, co2[0], co2[1], co2[2], 15, 0, 1) - 0.5f);
+               mul_v3_fl(co2, 10.0f);
 
-               mul_v3_v3(vec2, tvec);
+               tvec[0] = fac * (BLI_gTurbulence(1.0, co2[0], co2[1], co2[2], 15, 0, 2) - 0.5f);
+               tvec[1] = fac * (BLI_gTurbulence(1.0, co2[1], co2[0], co2[2], 15, 0, 2) - 0.5f);
+               tvec[2] = fac * (BLI_gTurbulence(1.0, co2[1], co2[2], co2[0], 15, 0, 2) - 0.5f);
 
-               /* add displacemen */
-               add_v3_v3v3(co, co, vec2);
+               /* add displacement */
+               madd_v3_v3fl(co, normal, tvec[0]);
+               madd_v3_v3fl(co, base1, tvec[1] * (1.0f - params->along_normal));
+               madd_v3_v3fl(co, base2, tvec[2] * (1.0f - params->along_normal));
        }
 
        /* apply the new difference to the rest of the shape keys,
-        * note that this doent take rotations into account, we _could_ support
+        * note that this dosn't take rotations into account, we _could_ support
         * this by getting the normals and coords for each shape key and
         * re-calculate the smooth value for each but this is quite involved.
         * for now its ok to simply apply the difference IMHO - campbell */
@@ -177,7 +184,7 @@ static void alter_co(BMesh *bm, BMVert *v, BMEdge *UNUSED(origed), const subdpar
 /* 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,
-                                         const subdparams *params, float percent,
+                                         const SubDParams *params, float percent,
                                          float percent2,
                                          BMEdge **out, BMVert *vsta, BMVert *vend)
 {
@@ -205,20 +212,23 @@ static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge, BMEdge *oedge,
        }
 #endif
        
+       interp_v3_v3v3(ev->no, vsta->no, vend->no, percent2);
+       normalize_v3(ev->no);
+
        return ev;
 }
 
 static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge, BMEdge *oedge,
-                                int curpoint, int totpoint, const subdparams *params,
+                                int curpoint, int totpoint, const SubDParams *params,
                                 BMEdge **newe, BMVert *vsta, BMVert *vend)
 {
        BMVert *ev;
        float percent, percent2 = 0.0f;
 
        if (BMO_elem_flag_test(bm, edge, EDGE_PERCENT) && totpoint == 1)
-               percent = BMO_slot_map_float_get(bm, params->op, "edgepercents", edge);
+               percent = BMO_slot_map_float_get(params->op->slots_in, "edgepercents", edge);
        else {
-               percent = 1.0f / (float)(totpoint + 1-curpoint);
+               percent = 1.0f / (float)(totpoint + 1 - curpoint);
                percent2 = (float)(curpoint + 1) / (float)(totpoint + 1);
 
        }
@@ -228,7 +238,7 @@ static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge, BMEdge *oedge,
        return ev;
 }
 
-static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, const subdparams *params,
+static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, const SubDParams *params,
                                   BMVert *vsta, BMVert *vend)
 {
        BMEdge *eed = edge, *newe, temp = *edge;
@@ -249,34 +259,36 @@ static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, const subdparams *par
                BMO_elem_flag_enable(bm, eed, ELE_SPLIT);
                BMO_elem_flag_enable(bm, newe, SUBD_SPLIT);
 
-               BM_CHECK_ELEMENT(bm, v);
-               if (v->e) BM_CHECK_ELEMENT(bm, v->e);
-               if (v->e && v->e->l) BM_CHECK_ELEMENT(bm, v->e->l->f);
+               BM_CHECK_ELEMENT(v);
+               if (v->e) BM_CHECK_ELEMENT(v->e);
+               if (v->e && v->e->l) BM_CHECK_ELEMENT(v->e->l->f);
        }
        
        alter_co(bm, v1, &temp, params, 0, &ov1, &ov2);
        alter_co(bm, v2, &temp, params, 1.0, &ov1, &ov2);
 }
 
-/* note: the patterns are rotated as necassary to
+/* note: the patterns are rotated as necessary to
  * match the input geometry.  they're based on the
  * pre-split state of the  face */
 
-/*
+/**
+ * <pre>
  *  v3---------v2
  *  |          |
  *  |          |
  *  |          |
  *  |          |
  *  v4---v0---v1
+ * </pre>
  */
 static void quad_1edge_split(BMesh *bm, BMFace *UNUSED(face),
-                             BMVert **verts, const subdparams *params)
+                             BMVert **verts, const SubDParams *params)
 {
        BMFace *nf;
        int i, add, numcuts = params->numcuts;
 
-       /* if it's odd, the middle face is a quad, otherwise it's a triangl */
+       /* 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++) {
@@ -290,7 +302,7 @@ static void quad_1edge_split(BMesh *bm, BMFace *UNUSED(face),
                add = 2;
                for (i = 0; i < numcuts; i++) {
                        connect_smallest_face(bm, verts[i], verts[numcuts + add], &nf);
-                       if (i == numcuts/2) {
+                       if (i == numcuts / 2) {
                                add -= 1;
                                connect_smallest_face(bm, verts[i], verts[numcuts + add], &nf);
                        }
@@ -299,23 +311,25 @@ static void quad_1edge_split(BMesh *bm, BMFace *UNUSED(face),
        }
 }
 
-static SubDPattern quad_1edge = {
+static const SubDPattern quad_1edge = {
        {1, 0, 0, 0},
        quad_1edge_split,
        4,
 };
 
 
-/*
+/**
+ * <pre>
  *  v6--------v5
  *  |          |
  *  |          |v4s
  *  |          |v3s
  *  |   s  s   |
  *  v7-v0--v1-v2
+ * </pre>
  */
 static void quad_2edge_split_path(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
-                                  const subdparams *params)
+                                  const SubDParams *params)
 {
        BMFace *nf;
        int i, numcuts = params->numcuts;
@@ -326,22 +340,24 @@ static void quad_2edge_split_path(BMesh *bm, BMFace *UNUSED(face), BMVert **vert
        connect_smallest_face(bm, verts[numcuts * 2 + 3], verts[numcuts * 2 + 1], &nf);
 }
 
-static SubDPattern quad_2edge_path = {
+static const SubDPattern quad_2edge_path = {
        {1, 1, 0, 0},
        quad_2edge_split_path,
        4,
 };
 
-/*
+/**
+ * <pre>
  *  v6--------v5
  *  |          |
  *  |          |v4s
  *  |          |v3s
  *  |   s  s   |
  *  v7-v0--v1-v2
+ * </pre>
  */
 static void quad_2edge_split_innervert(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
-                                       const subdparams *params)
+                                       const SubDParams *params)
 {
        BMFace *nf;
        BMVert *v, *lastv;
@@ -366,23 +382,24 @@ static void quad_2edge_split_innervert(BMesh *bm, BMFace *UNUSED(face), BMVert *
        connect_smallest_face(bm, lastv, verts[numcuts * 2 + 2], &nf);
 }
 
-static SubDPattern quad_2edge_innervert = {
+static const SubDPattern quad_2edge_innervert = {
        {1, 1, 0, 0},
        quad_2edge_split_innervert,
        4,
 };
 
-/*
+/**
+ * <pre>
  *  v6--------v5
  *  |          |
  *  |          |v4s
  *  |          |v3s
  *  |   s  s   |
  *  v7-v0--v1-v2
- *
+ * </pre>
  */
 static void quad_2edge_split_fan(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
-                                 const subdparams *params)
+                                 const SubDParams *params)
 {
        BMFace *nf;
        /* BMVert *v; */               /* UNUSED */
@@ -396,13 +413,14 @@ static void quad_2edge_split_fan(BMesh *bm, BMFace *UNUSED(face), BMVert **verts
        }
 }
 
-static SubDPattern quad_2edge_fan = {
+static const SubDPattern quad_2edge_fan = {
        {1, 1, 0, 0},
        quad_2edge_split_fan,
        4,
 };
 
-/*
+/**
+ * <pre>
  *      s   s
  *  v8--v7--v6-v5
  *  |          |
@@ -411,9 +429,10 @@ static SubDPattern quad_2edge_fan = {
  *  |          v3 s
  *  |   s  s   |
  *  v9-v0--v1-v2
+ * </pre>
  */
 static void quad_3edge_split(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
-                             const subdparams *params)
+                             const SubDParams *params)
 {
        BMFace *nf;
        int i, add = 0, numcuts = params->numcuts;
@@ -433,13 +452,14 @@ static void quad_3edge_split(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
        }
 }
 
-static SubDPattern quad_3edge = {
+static const SubDPattern quad_3edge = {
        {1, 1, 1, 0},
        quad_3edge_split,
        4,
 };
 
-/*
+/**
+ * <pre>
  *            v8--v7-v6--v5
  *            |     s    |
  *            |v9 s     s|v4
@@ -448,9 +468,10 @@ static SubDPattern quad_3edge = {
  *            v11-v0--v1-v2
  *
  *            it goes from bottom up
+ * </pre>
  */
 static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
-                                 const subdparams *params)
+                                 const SubDParams *params)
 {
        BMFace *nf;
        BMVert *v, *v1, *v2;
@@ -459,7 +480,7 @@ static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts
        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");
+       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 */
@@ -487,15 +508,15 @@ static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts
                BMO_elem_flag_enable(bm, nf, ELE_INNER);
 
                
-               v1 = lines[(i + 1)*s] = verts[a];
-               v2 = lines[(i + 1)*s + s - 1] = verts[b];
+               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);
-                       if (!v)
-                               bmesh_error();
+
+                       BMESH_ASSERT(v != NULL);
 
                        BMO_elem_flag_enable(bm, ne, ELE_INNER);
                        lines[(i + 1) * s + a + 1] = v;
@@ -518,7 +539,8 @@ static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts
        MEM_freeN(lines);
 }
 
-/*
+/**
+ * <pre>
  *        v3
  *       / \
  *      /   \
@@ -527,9 +549,10 @@ static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts
  *   /         \
  *  v4--v0--v1--v2
  *      s    s
+ * </pre>
  */
 static void tri_1edge_split(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
-                            const subdparams *params)
+                            const SubDParams *params)
 {
        BMFace *nf;
        int i, numcuts = params->numcuts;
@@ -539,13 +562,15 @@ static void tri_1edge_split(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
        }
 }
 
-static SubDPattern tri_1edge = {
+static const SubDPattern tri_1edge = {
        {1, 0, 0},
        tri_1edge_split,
        3,
 };
 
-/*         v5
+/**
+ * <pre>
+ *         v5
  *        / \
  *   s v6/---\ v4 s
  *      / \ / \
@@ -553,9 +578,10 @@ static SubDPattern tri_1edge = {
  *    /  \/  \/ \
  *   v8--v0--v1--v2
  *      s    s
+ * </pre>
  */
 static void tri_3edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
-                                const subdparams *params)
+                                const SubDParams *params)
 {
        BMFace *nf;
        BMEdge *e, *ne, temp;
@@ -564,7 +590,7 @@ static void tri_3edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
        int i, j, a, b, numcuts = params->numcuts;
        
        /* number of verts in each lin */
-       lines = MEM_callocN(sizeof(void *)*(numcuts + 2), "triangle vert table");
+       lines = MEM_callocN(sizeof(void *) * (numcuts + 2), "triangle vert table");
        
        lines[0] = (BMVert **) stackarr;
        lines[0][0] = verts[numcuts * 2 + 1];
@@ -577,7 +603,7 @@ static void tri_3edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
        lines[numcuts + 1][numcuts + 1] = verts[numcuts];
 
        for (i = 0; i < numcuts; i++) {
-               lines[i + 1] = MEM_callocN(sizeof(void *)*(2 + i), "triangle vert table row");
+               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);
@@ -603,7 +629,8 @@ static void tri_3edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
                }
        }
        
-       /*
+       /**
+        * <pre>
         *         v5
         *        / \
         *   s v6/---\ v4 s
@@ -612,6 +639,7 @@ static void tri_3edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
         *    /  \/  \/ \
         *   v8--v0--v1--v2
         *      s    s
+        * </pre>
         */
        for (i = 1; i < numcuts + 1; i++) {
                for (j = 0; j < i; j++) {
@@ -635,71 +663,77 @@ cleanup:
        MEM_freeN(lines);
 }
 
-static SubDPattern tri_3edge = {
+static const SubDPattern tri_3edge = {
        {1, 1, 1},
        tri_3edge_subdivide,
        3,
 };
 
 
-static SubDPattern quad_4edge = {
+static const SubDPattern quad_4edge = {
        {1, 1, 1, 1},
        quad_4edge_subdivide,
        4,
 };
 
-static SubDPattern *patterns[] = {
-       NULL, //quad single edge pattern is inserted here
-       NULL, //quad corner vert pattern is inserted here
-       NULL, //tri single edge pattern is inserted here
+static const SubDPattern *patterns[] = {
+       NULL,  /* quad single edge pattern is inserted here */
+       NULL,  /* quad corner vert pattern is inserted here */
+       NULL,  /* tri single edge pattern is inserted here */
        NULL,
        &quad_3edge,
        NULL,
 };
 
-#define PLEN   (sizeof(patterns) / sizeof(void *))
+#define PATTERNS_TOT  (sizeof(patterns) / sizeof(void *))
 
-typedef struct subd_facedata {
-       BMVert *start; SubDPattern *pat;
-       int totedgesel; //only used if pat was NULL, e.g. no pattern was found
+typedef struct SubDFaceData {
+       BMVert *start;
+       const SubDPattern *pat;
+       int totedgesel;  /* only used if pat was NULL, e.g. no pattern was found */
        BMFace *face;
-} subd_facedata;
+} SubDFaceData;
 
-void esubdivide_exec(BMesh *bmesh, BMOperator *op)
+void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
 {
        BMOpSlot *einput;
-       SubDPattern *pat;
-       subdparams params;
-       subd_facedata *facedata = NULL;
+       const SubDPattern *pat;
+       SubDParams params;
+       SubDFaceData *facedata = NULL;
+       BLI_array_declare(facedata);
        BMIter viter, fiter, liter;
        BMVert *v, **verts = NULL;
-       BMEdge *edge, **edges = NULL;
-       BMLoop *nl, *l, **splits = NULL, **loops = NULL;
-       BMFace *face;
-       BLI_array_declare(splits);
-       BLI_array_declare(loops);
-       BLI_array_declare(facedata);
+       BMEdge *edge;
+       BMEdge **edges = NULL;
        BLI_array_declare(edges);
+       BMLoop *(*loops_split)[2] = NULL;
+       BLI_array_declare(loops_split);
+       BMLoop **loops = NULL;
+       BLI_array_declare(loops);
+       BMLoop *nl, *l;
+       BMFace *face;
        BLI_array_declare(verts);
-       float smooth, fractal;
-       int beauty, cornertype, singleedge, gridfill;
+       float smooth, fractal, along_normal;
+       int use_sphere, cornertype, use_singleedge, use_gridfill;
        int skey, seed, i, j, matched, a, b, numcuts, totesel;
        
-       BMO_slot_buffer_flag_enable(bmesh, op, "edges", SUBD_SPLIT, BM_EDGE);
+       BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, SUBD_SPLIT);
        
-       numcuts = BMO_slot_int_get(op, "numcuts");
-       seed = BMO_slot_int_get(op, "seed");
-       smooth = BMO_slot_float_get(op, "smooth");
-       fractal = BMO_slot_float_get(op, "fractal");
-       beauty = BMO_slot_int_get(op, "beauty");
-       cornertype = BMO_slot_int_get(op, "quadcornertype");
-       singleedge = BMO_slot_bool_get(op, "singleedge");
-       gridfill = BMO_slot_bool_get(op, "gridfill");
+       numcuts = BMO_slot_int_get(op->slots_in, "cuts");
+       seed = BMO_slot_int_get(op->slots_in, "seed");
+       smooth = BMO_slot_float_get(op->slots_in, "smooth");
+       fractal = BMO_slot_float_get(op->slots_in, "fractal");
+       along_normal = BMO_slot_float_get(op->slots_in, "along_normal");
+       cornertype = BMO_slot_int_get(op->slots_in, "quad_corner_type");
+
+       use_singleedge = BMO_slot_bool_get(op->slots_in, "use_singleedge");
+       use_gridfill   = BMO_slot_bool_get(op->slots_in, "use_gridfill");
+       use_sphere     = BMO_slot_bool_get(op->slots_in, "use_sphere");
        
        BLI_srandom(seed);
        
        patterns[1] = NULL;
-       //straight cut is patterns[1] == NULL
+       /* straight cut is patterns[1] == NULL */
        switch (cornertype) {
                case SUBD_PATH:
                        patterns[1] = &quad_2edge_path;
@@ -712,7 +746,7 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
                        break;
        }
        
-       if (singleedge) {
+       if (use_singleedge) {
                patterns[0] = &quad_1edge;
                patterns[2] = &tri_1edge;
        }
@@ -721,7 +755,7 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
                patterns[2] = NULL;
        }
 
-       if (gridfill) {
+       if (use_gridfill) {
                patterns[3] = &quad_4edge;
                patterns[5] = &tri_3edge;
        }
@@ -730,121 +764,117 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
                patterns[5] = NULL;
        }
        
-       /* add a temporary shapekey layer to store displacements on current geometr */
-       BM_data_layer_add(bmesh, &bmesh->vdata, CD_SHAPEKEY);
-       skey = CustomData_number_of_layers(&bmesh->vdata, CD_SHAPEKEY) - 1;
+       /* add a temporary shapekey layer to store displacements on current geometry */
+       BM_data_layer_add(bm, &bm->vdata, CD_SHAPEKEY);
+       skey = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY) - 1;
        
-       BM_ITER(v, &viter, bmesh, BM_VERTS_OF_MESH, NULL) {
-               float *co = CustomData_bmesh_get_n(&bmesh->vdata, v->head.data, CD_SHAPEKEY, skey);
+       BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+               float *co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, skey);
                copy_v3_v3(co, v->co);
        }
 
-       /* first go through and tag edge */
-       BMO_slot_from_flag(bmesh, op, "edges",
-                          SUBD_SPLIT, BM_EDGE);
+       /* first go through and tag edges */
+       BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_in, "edges", BM_EDGE, SUBD_SPLIT);
 
        params.numcuts = numcuts;
        params.op = op;
        params.smooth = smooth;
        params.seed = seed;
        params.fractal = fractal;
-       params.beauty = beauty;
+       params.along_normal = along_normal;
+       params.use_smooth  = (smooth  != 0.0f);
+       params.use_fractal = (fractal != 0.0f);
+       params.use_sphere  = use_sphere;
        params.origkey = skey;
        params.off[0] = (float)BLI_drand() * 200.0f;
        params.off[1] = (float)BLI_drand() * 200.0f;
        params.off[2] = (float)BLI_drand() * 200.0f;
        
-       BMO_slot_map_to_flag(bmesh, op, "custompatterns",
-                            FACE_CUSTOMFILL);
+       BMO_slot_map_to_flag(bm, op->slots_in, "custompatterns",
+                            BM_FACE, FACE_CUSTOMFILL);
 
-       BMO_slot_map_to_flag(bmesh, op, "edgepercents",
-                            EDGE_PERCENT);
+       BMO_slot_map_to_flag(bm, op->slots_in, "edgepercents",
+                            BM_EDGE, EDGE_PERCENT);
 
-       for (face = BM_iter_new(&fiter, bmesh, BM_FACES_OF_MESH, NULL);
-            face;
-            face = BM_iter_step(&fiter))
-       {
+
+       BM_ITER_MESH (face, &fiter, bm, BM_FACES_OF_MESH) {
                BMEdge *e1 = NULL, *e2 = NULL;
                float vec1[3], vec2[3];
 
-               /* figure out which pattern to us */
+               /* figure out which pattern to use */
 
                BLI_array_empty(edges);
                BLI_array_empty(verts);
+
+               BLI_array_grow_items(edges, face->len);
+               BLI_array_grow_items(verts, face->len);
+
                matched = 0;
 
-               i = 0;
                totesel = 0;
-               for (nl = BM_iter_new(&liter, bmesh, BM_LOOPS_OF_FACE, face); nl; nl = BM_iter_step(&liter)) {
-                       BLI_array_growone(edges);
-                       BLI_array_growone(verts);
+               BM_ITER_ELEM_INDEX (nl, &liter, face, BM_LOOPS_OF_FACE, i) {
                        edges[i] = nl->e;
                        verts[i] = nl->v;
 
-                       if (BMO_elem_flag_test(bmesh, edges[i], SUBD_SPLIT)) {
+                       if (BMO_elem_flag_test(bm, edges[i], SUBD_SPLIT)) {
                                if (!e1) e1 = edges[i];
-                               else e2 = edges[i];
+                               else     e2 = edges[i];
 
                                totesel++;
                        }
-
-                       i++;
                }
 
-               /* make sure the two edges have a valid angle to each othe */
-               if (totesel == 2 && BM_edge_share_vert(e1, e2)) {
-                       float angle;
-
+               /* make sure the two edges have a valid angle to each other */
+               if (totesel == 2 && BM_edge_share_vert_check(e1, e2)) {
                        sub_v3_v3v3(vec1, e1->v2->co, e1->v1->co);
                        sub_v3_v3v3(vec2, e2->v2->co, e2->v1->co);
                        normalize_v3(vec1);
                        normalize_v3(vec2);
 
-                       angle = dot_v3v3(vec1, vec2);
-                       angle = fabsf(angle);
-                       if (fabsf(angle - 1.0f) < 0.01f) {
+                       if (fabsf(dot_v3v3(vec1, vec2)) > 1.0f - FLT_FACE_SPLIT_EPSILON) {
                                totesel = 0;
                        }
                }
 
-               if (BMO_elem_flag_test(bmesh, face, FACE_CUSTOMFILL)) {
-                       pat = BMO_slot_map_data_get(bmesh, op,
-                                                   "custompatterns", face);
+               if (BMO_elem_flag_test(bm, face, FACE_CUSTOMFILL)) {
+                       pat = BMO_slot_map_data_get(op->slots_in, "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_elem_flag_test(bmesh, edges[a], SUBD_SPLIT)) != (!!pat->seledges[j])) {
+                                       if ((!!BMO_elem_flag_test(bm, edges[a], SUBD_SPLIT)) != (!!pat->seledges[j])) {
                                                matched = 0;
                                                break;
                                        }
                                }
                                if (matched) {
-                                       BLI_array_growone(facedata);
+                                       BLI_array_grow_one(facedata);
                                        b = BLI_array_count(facedata) - 1;
                                        facedata[b].pat = pat;
                                        facedata[b].start = verts[i];
                                        facedata[b].face = face;
                                        facedata[b].totedgesel = totesel;
-                                       BMO_elem_flag_enable(bmesh, face, SUBD_SPLIT);
+                                       BMO_elem_flag_enable(bm, face, SUBD_SPLIT);
                                        break;
                                }
                        }
 
-                       /* obvously don't test for other patterns matchin */
+                       /* obvously don't test for other patterns matching */
                        continue;
                }
 
-               for (i = 0; i < PLEN; i++) {
+               for (i = 0; i < PATTERNS_TOT; i++) {
                        pat = patterns[i];
-                       if (!pat) continue;
+                       if (!pat) {
+                               continue;
+                       }
 
                        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_elem_flag_test(bmesh, edges[j], SUBD_SPLIT)) != (!!pat->seledges[b])) {
+                                               if ((!!BMO_elem_flag_test(bm, edges[j], SUBD_SPLIT)) != (!!pat->seledges[b])) {
                                                        matched = 0;
                                                        break;
                                                }
@@ -854,10 +884,10 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
                                        }
                                }
                                if (matched) {
-                                       BLI_array_growone(facedata);
+                                       BLI_array_grow_one(facedata);
                                        j = BLI_array_count(facedata) - 1;
 
-                                       BMO_elem_flag_enable(bmesh, face, SUBD_SPLIT);
+                                       BMO_elem_flag_enable(bm, face, SUBD_SPLIT);
 
                                        facedata[j].pat = pat;
                                        facedata[j].start = verts[a];
@@ -870,28 +900,34 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
                }
                
                if (!matched && totesel) {
-                       BLI_array_growone(facedata);
+                       BLI_array_grow_one(facedata);
                        j = BLI_array_count(facedata) - 1;
                        
-                       BMO_elem_flag_enable(bmesh, face, SUBD_SPLIT);
+                       BMO_elem_flag_enable(bm, face, SUBD_SPLIT);
                        facedata[j].totedgesel = totesel;
                        facedata[j].face = face;
                }
        }
 
-       einput = BMO_slot_get(op, "edges");
+       einput = BMO_slot_get(op->slots_in, "edges");
 
-       /* go through and split edge */
+       /* 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);
+               edge = einput->data.buf[i];
+               bm_subdivide_multicut(bm, edge, &params, edge->v1, edge->v2);
+       }
+
+       /* copy original-geometry displacements to current coordinates */
+       BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+               float *co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, skey);
+               copy_v3_v3(v->co, co);
        }
 
        i = 0;
        for (i = 0; i < BLI_array_count(facedata); i++) {
                face = facedata[i].face;
 
-               /* figure out which pattern to us */
+               /* figure out which pattern to use */
                BLI_array_empty(verts);
 
                pat = facedata[i].pat;
@@ -901,34 +937,34 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
                        
                        /* ok, no pattern.  we still may be able to do something */
                        BLI_array_empty(loops);
-                       BLI_array_empty(splits);
+                       BLI_array_empty(loops_split);
 
-                       /* for case of two edges, connecting them shouldn't be too har */
-                       BM_ITER(l, &liter, bmesh, BM_LOOPS_OF_FACE, face) {
-                               BLI_array_growone(loops);
-                               loops[BLI_array_count(loops) - 1] = l;
+                       /* for case of two edges, connecting them shouldn't be too hard */
+                       BLI_array_grow_items(loops, face->len);
+                       BM_ITER_ELEM_INDEX (l, &liter, face, BM_LOOPS_OF_FACE, a) {
+                               loops[a] = l;
                        }
                        
                        vlen = BLI_array_count(loops);
 
-                       /* find the boundary of one of the split edge */
+                       /* find the boundary of one of the split edges */
                        for (a = 1; a < vlen; a++) {
-                               if (!BMO_elem_flag_test(bmesh, loops[a - 1]->v, ELE_INNER) &&
-                                   BMO_elem_flag_test(bmesh, loops[a]->v, ELE_INNER))
+                               if (!BMO_elem_flag_test(bm, loops[a - 1]->v, ELE_INNER) &&
+                                   BMO_elem_flag_test(bm, loops[a]->v, ELE_INNER))
                                {
                                        break;
                                }
                        }
                        
-                       if (BMO_elem_flag_test(bmesh, loops[(a + numcuts + 1) % vlen]->v, ELE_INNER)) {
+                       if (BMO_elem_flag_test(bm, loops[(a + numcuts + 1) % vlen]->v, ELE_INNER)) {
                                b = (a + numcuts + 1) % vlen;
                        }
                        else {
                                /* find the boundary of the other edge. */
                                for (j = 0; j < vlen; j++) {
                                        b = (j + a + numcuts + 1) % vlen;
-                                       if (!BMO_elem_flag_test(bmesh, loops[b == 0 ? vlen - 1 : b - 1]->v, ELE_INNER) &&
-                                           BMO_elem_flag_test(bmesh, loops[b]->v, ELE_INNER))
+                                       if (!BMO_elem_flag_test(bm, loops[b == 0 ? vlen - 1 : b - 1]->v, ELE_INNER) &&
+                                           BMO_elem_flag_test(bm, loops[b]->v, ELE_INNER))
                                        {
                                                break;
                                        }
@@ -937,23 +973,65 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
                        
                        b += numcuts - 1;
 
+                       BLI_array_grow_items(loops_split, numcuts);
                        for (j = 0; j < numcuts; j++) {
-                               BLI_array_growone(splits);
-                               splits[BLI_array_count(splits) - 1] = loops[a];
-                               
-                               BLI_array_growone(splits);
-                               splits[BLI_array_count(splits) - 1] = loops[b];
+                               int ok = TRUE;
+
+                               /* Check for special case: [#32500]
+                                * This edge pair could be used by more then one face,
+                                * in this case it used to (2.63), split both faces along the same verts
+                                * while it could be calculated which face should do the split,
+                                * it's ambiguous, so in this case we're better off to skip them as exceptional cases
+                                * and not try to be clever guessing which face to cut up.
+                                *
+                                * To avoid this case we need to check:
+                                * Do the verts of each share a face besides the one we are subdividing,
+                                *  (but not connect to make an edge of that face).
+                                */
+                               {
+                                       BMLoop *other_loop;
+                                       BMIter other_fiter;
+                                       BM_ITER_ELEM (other_loop, &other_fiter, loops[a]->v, BM_LOOPS_OF_VERT) {
+                                               if (other_loop->f != face) {
+                                                       if (BM_vert_in_face(other_loop->f, loops[b]->v)) {
+                                                               /* we assume that these verts are not making an edge in the face */
+                                                               BLI_assert(other_loop->prev->v != loops[a]->v);
+                                                               BLI_assert(other_loop->next->v != loops[a]->v);
+
+                                                               ok = FALSE;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                               }
+
+
+                               if (ok == TRUE) {
+                                       loops_split[j][0] = loops[a];
+                                       loops_split[j][1] = loops[b];
+                               }
+                               else {
+                                       loops_split[j][0] = NULL;
+                                       loops_split[j][1] = NULL;
+                               }
 
                                b = (b - 1) % vlen;
                                a = (a + 1) % vlen;
                        }
                        
-                       //BM_face_legal_splits(bmesh, face, splits, BLI_array_count(splits)/2);
+                       /* Since these are newly created vertices, we don't need to worry about them being legal,
+                        * ... though there are some cases we _should_ check for
+                        * - concave corner of an ngon.
+                        * - 2 edges being used in 2+ ngons.
+                        */
+//                     BM_face_legal_splits(bm, face, loops_split, BLI_array_count(loops_split));
+
+                       for (j = 0; j < BLI_array_count(loops_split); j++) {
+                               if (loops_split[j][0]) {
+                                       BLI_assert(BM_edge_exists(loops_split[j][0]->v, loops_split[j][1]->v) == FALSE);
 
-                       for (j = 0; j < BLI_array_count(splits) / 2; j++) {
-                               if (splits[j * 2]) {
                                        /* BMFace *nf = */ /* UNUSED */
-                                       BM_face_split(bmesh, face, splits[j * 2]->v, splits[j * 2 + 1]->v, &nl, NULL);
+                                       BM_face_split(bm, face, loops_split[j][0]->v, loops_split[j][1]->v, &nl, NULL, FALSE);
                                }
                        }
 
@@ -963,112 +1041,106 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
                        continue;
                }
 
-               j = a = 0;
-               for (nl = BM_iter_new(&liter, bmesh, BM_LOOPS_OF_FACE, face);
-                    nl;
-                    nl = BM_iter_step(&liter))
-               {
+               a = 0;
+               BM_ITER_ELEM_INDEX (nl, &liter, face, BM_LOOPS_OF_FACE, j) {
                        if (nl->v == facedata[i].start) {
                                a = j + 1;
                                break;
                        }
-                       j++;
                }
 
-               for (j = 0; j < face->len; j++) {
-                       BLI_array_growone(verts);
-               }
-               
-               j = 0;
-               for (nl = BM_iter_new(&liter, bmesh, BM_LOOPS_OF_FACE, face); nl; nl = BM_iter_step(&liter)) {
+               BLI_array_grow_items(verts, face->len);
+
+               BM_ITER_ELEM_INDEX (nl, &liter, face, BM_LOOPS_OF_FACE, j) {
                        b = (j - a + face->len) % face->len;
                        verts[b] = nl->v;
-                       j += 1;
                }
 
-               BM_CHECK_ELEMENT(bmesh, face);
-               pat->connectexec(bmesh, face, verts, &params);
+               BM_CHECK_ELEMENT(face);
+               pat->connectexec(bm, face, verts, &params);
        }
 
-       /* copy original-geometry displacements to current coordinate */
-       BM_ITER(v, &viter, bmesh, BM_VERTS_OF_MESH, NULL) {
-               float *co = CustomData_bmesh_get_n(&bmesh->vdata, v->head.data, CD_SHAPEKEY, skey);
+       /* copy original-geometry displacements to current coordinates */
+       BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+               float *co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, skey);
                copy_v3_v3(v->co, co);
        }
 
-       BM_data_layer_free_n(bmesh, &bmesh->vdata, CD_SHAPEKEY, skey);
+       BM_data_layer_free_n(bm, &bm->vdata, CD_SHAPEKEY, skey);
        
        if (facedata) BLI_array_free(facedata);
        if (edges) BLI_array_free(edges);
        if (verts) BLI_array_free(verts);
-       BLI_array_free(splits);
+       BLI_array_free(loops_split);
        BLI_array_free(loops);
 
-       BMO_slot_from_flag(bmesh, op, "outinner",
-                          ELE_INNER, BM_ALL);
-       BMO_slot_from_flag(bmesh, op, "outsplit",
-                          ELE_SPLIT, BM_ALL);
+       BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_inner.out", BM_ALL, ELE_INNER);
+       BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_split.out", BM_ALL, ELE_SPLIT);
        
-       BMO_slot_from_flag(bmesh, op, "geomout",
-                          ELE_INNER|ELE_SPLIT|SUBD_SPLIT, BM_ALL);
+       BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL, ELE_INNER | ELE_SPLIT | SUBD_SPLIT);
 }
 
-/* editmesh-emulating functio */
-void BM_mesh_esubdivideflag(Object *UNUSED(obedit), BMesh *bm, int flag, float smooth,
-                       float fractal, int beauty, int numcuts,
-                       int seltype, int cornertype, int singleedge,
-                       int gridfill, int seed)
+/* editmesh-emulating function */
+void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag,
+                        float smooth, float fractal, float along_normal,
+                        int numcuts,
+                        int seltype, int cornertype,
+                        const short use_singleedge, const short use_gridfill,
+                        int seed)
 {
        BMOperator op;
        
-       BMO_op_initf(bm, &op, "esubd edges=%he smooth=%f fractal=%f "
-                    "beauty=%i numcuts=%i quadcornertype=%i singleedge=%b "
-                    "gridfill=%b seed=%i",
-                    flag, smooth, fractal, beauty, numcuts,
-                    cornertype, singleedge, gridfill, seed);
+       /* use_sphere isnt exposed here since its only used for new primitives */
+       BMO_op_initf(bm, &op, BMO_FLAG_DEFAULTS,
+                    "subdivide_edges edges=%he "
+                    "smooth=%f fractal=%f along_normal=%f "
+                    "cuts=%i "
+                    "quad_corner_type=%i "
+                    "use_singleedge=%b use_gridfill=%b "
+                    "seed=%i",
+                    edge_hflag,
+                    smooth, fractal, along_normal,
+                    numcuts,
+                    cornertype,
+                    use_singleedge, use_gridfill,
+                    seed);
        
        BMO_op_exec(bm, &op);
        
        if (seltype == SUBDIV_SELECT_INNER) {
                BMOIter iter;
-               BMHeader *ele;
-               // int i;
-               
-               ele = BMO_iter_new(&iter, bm, &op, "outinner", BM_EDGE|BM_VERT);
-               for ( ; ele; ele = BMO_iter_step(&iter)) {
+               BMElem *ele;
+
+               for (ele = BMO_iter_new(&iter, op.slots_out, "geom_inner.out", BM_EDGE | BM_VERT); ele; ele = BMO_iter_step(&iter)) {
                        BM_elem_select_set(bm, ele, TRUE);
                }
        }
        else if (seltype == SUBDIV_SELECT_LOOPCUT) {
                BMOIter iter;
-               BMHeader *ele;
-               // int i;
+               BMElem *ele;
                
                /* deselect input */
-               BM_mesh_elem_flag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT);
+               BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, FALSE);
 
-               ele = BMO_iter_new(&iter, bm, &op, "outinner", BM_EDGE|BM_VERT);
-               for ( ; ele; ele = BMO_iter_step(&iter)) {
+               for (ele = BMO_iter_new(&iter, op.slots_out, "geom_inner.out", BM_EDGE | BM_VERT); ele; ele = BMO_iter_step(&iter)) {
                        BM_elem_select_set(bm, ele, TRUE);
 
-                       if (ele->htype == BM_VERT) {
+                       if (ele->head.htype == BM_VERT) {
                                BMEdge *e;
                                BMIter eiter;
 
-                               BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, ele) {
+                               BM_ITER_ELEM (e, &eiter, ele, BM_EDGES_OF_VERT) {
                                        if (!BM_elem_flag_test(e, BM_ELEM_SELECT) &&
                                             BM_elem_flag_test(e->v1, BM_ELEM_SELECT) &&
                                             BM_elem_flag_test(e->v2, BM_ELEM_SELECT))
                                        {
-                                               BM_elem_select_set(bm, e, TRUE);
-                                               bm->totedgesel += 1;
+                                               BM_edge_select_set(bm, e, TRUE);
                                        }
                                        else if (BM_elem_flag_test(e, BM_ELEM_SELECT) &&
                                                 (!BM_elem_flag_test(e->v1, BM_ELEM_SELECT) ||
                                                  !BM_elem_flag_test(e->v2, BM_ELEM_SELECT)))
                                        {
-                                               BM_elem_select_set(bm, e, FALSE);
-                                               bm->totedgesel -= 1;
+                                               BM_edge_select_set(bm, e, FALSE);
                                        }
                                }
                        }
@@ -1078,14 +1150,14 @@ void BM_mesh_esubdivideflag(Object *UNUSED(obedit), BMesh *bm, int flag, float s
        BMO_op_finish(bm, &op);
 }
 
-void esplit_exec(BMesh *bm, BMOperator *op)
+void bmo_bisect_edges_exec(BMesh *bm, BMOperator *op)
 {
        BMOIter siter;
        BMEdge *e;
-       subdparams params;
+       SubDParams params = {0};
        int skey;
        
-       params.numcuts = BMO_slot_get(op, "numcuts")->data.i;
+       params.numcuts = BMO_slot_int_get(op->slots_in, "cuts");
        params.op = op;
        
        BM_data_layer_add(bm, &bm->vdata, CD_SHAPEKEY);
@@ -1093,12 +1165,12 @@ void esplit_exec(BMesh *bm, BMOperator *op)
        
        params.origkey = skey;
 
-       /* go through and split edge */
-       BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
+       /* go through and split edges */
+       BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
                bm_subdivide_multicut(bm, e, &params, e->v1, e->v2);
        }
 
-       BMO_slot_from_flag(bm, op, "outsplit", ELE_SPLIT, BM_ALL);
+       BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_split.out", BM_ALL, ELE_SPLIT);
 
        BM_data_layer_free_n(bm, &bm->vdata, CD_SHAPEKEY, skey);
 }