diff options
author | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2012-12-01 06:47:59 +0400 |
---|---|---|
committer | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2012-12-01 06:47:59 +0400 |
commit | ed0e2fbd9f4edd55e11df694b34e233cb38cb953 (patch) | |
tree | 70a0d0fc080339b87cbeb73ebab6d4eda91ca5ba /source/blender/bmesh/intern | |
parent | 129a29873e552d769339c2b7d3b99a0afbbf2ae0 (diff) | |
parent | 75cce01a614e686530e26dbd186a88d75dc4e7b5 (diff) |
Merged changes in the trunk up to revision 52690.
Conflicts resolved:
release/datafiles/startup.blend
source/blender/blenlib/intern/bpath.c
Diffstat (limited to 'source/blender/bmesh/intern')
-rw-r--r-- | source/blender/bmesh/intern/bmesh_construct.c | 28 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_construct.h | 4 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_core.c | 106 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_core.h | 15 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_mesh_conv.c | 31 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_mods.c | 7 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_opdefines.c | 1145 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_operator_api.h | 100 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_operator_api_inline.h | 63 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_operators.c | 219 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_operators.h | 15 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_operators_private.h | 2 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_queries.c | 23 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_queries.h | 1 |
14 files changed, 1019 insertions, 740 deletions
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index eabbf6f87cd..c805a91ff22 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -105,17 +105,17 @@ BMFace *BM_face_create_quad_tri_v(BMesh *bm, BMVert **verts, int len, const BMFa /* make new face */ if ((f == NULL) && (!is_overlap)) { BMEdge *edar[4] = {NULL}; - edar[0] = BM_edge_create(bm, verts[0], verts[1], NULL, TRUE); - edar[1] = BM_edge_create(bm, verts[1], verts[2], NULL, TRUE); + edar[0] = BM_edge_create(bm, verts[0], verts[1], NULL, BM_CREATE_NO_DOUBLE); + edar[1] = BM_edge_create(bm, verts[1], verts[2], NULL, BM_CREATE_NO_DOUBLE); if (len == 4) { - edar[2] = BM_edge_create(bm, verts[2], verts[3], NULL, TRUE); - edar[3] = BM_edge_create(bm, verts[3], verts[0], NULL, TRUE); + edar[2] = BM_edge_create(bm, verts[2], verts[3], NULL, BM_CREATE_NO_DOUBLE); + edar[3] = BM_edge_create(bm, verts[3], verts[0], NULL, BM_CREATE_NO_DOUBLE); } else { - edar[2] = BM_edge_create(bm, verts[2], verts[0], NULL, TRUE); + edar[2] = BM_edge_create(bm, verts[2], verts[0], NULL, BM_CREATE_NO_DOUBLE); } - f = BM_face_create(bm, verts, edar, len, FALSE); + f = BM_face_create(bm, verts, edar, len, 0); if (example && f) { BM_elem_attrs_copy(bm, bm, example, f); @@ -171,7 +171,7 @@ void BM_face_copy_shared(BMesh *bm, BMFace *f) * #BM_face_create should be considered over this function as it * avoids some unnecessary work. */ -BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, int nodouble) +BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, const int create_flag) { BMEdge **edges2 = NULL; BLI_array_staticdeclare(edges2, BM_DEFAULT_NGON_STACK_SIZE); @@ -282,7 +282,7 @@ BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, i BM_ELEM_API_FLAG_DISABLE(verts[i], _FLAG_MV); } - f = BM_face_create(bm, verts, edges2, len, nodouble); + f = BM_face_create(bm, verts, edges2, len, create_flag); /* clean up flags */ for (i = 0; i < len; i++) { @@ -338,7 +338,7 @@ static int angle_index_pair_cmp(const void *e1, const void *e2) * * \note Since this is a vcloud there is no direction. */ -BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, int nodouble) +BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, const int create_flag) { BMFace *f; @@ -464,7 +464,7 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, int n i_prev = totv - 1; for (i = 0; i < totv; i++) { - edge_arr[i] = BM_edge_create(bm, vert_arr_map[i_prev], vert_arr_map[i], NULL, TRUE); + edge_arr[i] = BM_edge_create(bm, vert_arr_map[i_prev], vert_arr_map[i], NULL, BM_CREATE_NO_DOUBLE); /* the edge may exist already and be attached to a face * in this case we can find the best winding to use for the new face */ @@ -493,7 +493,7 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, int n /* --- */ /* create the face */ - f = BM_face_create_ngon(bm, vert_arr_map[winding[0]], vert_arr_map[winding[1]], edge_arr, totv, nodouble); + f = BM_face_create_ngon(bm, vert_arr_map[winding[0]], vert_arr_map[winding[1]], edge_arr, totv, create_flag); MEM_freeN(edge_arr); MEM_freeN(vert_arr_map); @@ -856,7 +856,7 @@ BMesh *BM_mesh_copy(BMesh *bm_old) v = BM_iter_new(&iter, bm_old, BM_VERTS_OF_MESH, NULL); for (i = 0; v; v = BM_iter_step(&iter), i++) { - v2 = BM_vert_create(bm_new, v->co, NULL); /* copy between meshes so cant use 'example' argument */ + v2 = BM_vert_create(bm_new, v->co, NULL, BM_CREATE_SKIP_CD); /* copy between meshes so cant use 'example' argument */ BM_elem_attrs_copy(bm_old, bm_new, v, v2); vtable[i] = v2; BM_elem_index_set(v, i); /* set_inline */ @@ -873,7 +873,7 @@ BMesh *BM_mesh_copy(BMesh *bm_old) e2 = BM_edge_create(bm_new, vtable[BM_elem_index_get(e->v1)], vtable[BM_elem_index_get(e->v2)], - e, FALSE); + e, BM_CREATE_SKIP_CD); BM_elem_attrs_copy(bm_old, bm_new, e, e2); etable[i] = e2; @@ -909,7 +909,7 @@ BMesh *BM_mesh_copy(BMesh *bm_old) v2 = vtable[BM_elem_index_get(loops[0]->v)]; } - f2 = BM_face_create_ngon(bm_new, v, v2, edges, f->len, FALSE); + f2 = BM_face_create_ngon(bm_new, v, v2, edges, f->len, BM_CREATE_SKIP_CD); if (UNLIKELY(f2 == NULL)) { continue; } diff --git a/source/blender/bmesh/intern/bmesh_construct.h b/source/blender/bmesh/intern/bmesh_construct.h index 29b84046884..60c465e5f5a 100644 --- a/source/blender/bmesh/intern/bmesh_construct.h +++ b/source/blender/bmesh/intern/bmesh_construct.h @@ -36,9 +36,9 @@ BMFace *BM_face_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, B void BM_face_copy_shared(BMesh *bm, BMFace *f); -BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, int nodouble); +BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, const int create_flag); -BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, int nodouble); +BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, const int create_flag); void BMO_remove_tagged_faces(BMesh *bm, const short oflag); void BMO_remove_tagged_edges(BMesh *bm, const short oflag); diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 03094873e25..14fab7abdc9 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -54,7 +54,7 @@ /** * \brief Main function for creating a new vertex. */ -BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example) +BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example, const eBMCreateFlag create_flag) { BMVert *v = BLI_mempool_calloc(bm->vpool); @@ -64,6 +64,9 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example) BM_elem_index_set(v, -1); /* set_ok_invalid */ #endif + /* disallow this flag for verts - its meaningless */ + BLI_assert((create_flag & BM_CREATE_NO_DOUBLE) == 0); + bm->elem_index_dirty |= BM_VERT; /* may add to middle of the pool */ bm->totvert++; @@ -80,17 +83,20 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example) v->oflags = BLI_mempool_calloc(bm->toolflagpool); } - CustomData_bmesh_set_default(&bm->vdata, &v->head.data); - - if (example) { - int *keyi; + if (!(create_flag & BM_CREATE_SKIP_CD)) { + if (example) { + int *keyi; - BM_elem_attrs_copy(bm, bm, example, v); + BM_elem_attrs_copy(bm, bm, example, v); - /* exception: don't copy the original shapekey index */ - keyi = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_SHAPE_KEYINDEX); - if (keyi) { - *keyi = ORIGINDEX_NONE; + /* exception: don't copy the original shapekey index */ + keyi = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_SHAPE_KEYINDEX); + if (keyi) { + *keyi = ORIGINDEX_NONE; + } + } + else { + CustomData_bmesh_set_default(&bm->vdata, &v->head.data); } } @@ -105,11 +111,11 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example) * \note Duplicate edges are supported by the API however users should _never_ see them. * so unless you need a unique edge or know the edge won't exist, you should call with \a nodouble = TRUE */ -BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, int nodouble) +BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, const eBMCreateFlag create_flag) { BMEdge *e; - if (nodouble && (e = BM_edge_exists(v1, v2))) + if ((create_flag & BM_CREATE_NO_DOUBLE) && (e = BM_edge_exists(v1, v2))) return e; e = BLI_mempool_calloc(bm->epool); @@ -136,20 +142,26 @@ BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, BM_elem_flag_enable(e, BM_ELEM_SMOOTH | BM_ELEM_DRAW); - CustomData_bmesh_set_default(&bm->edata, &e->head.data); - bmesh_disk_edge_append(e, e->v1); bmesh_disk_edge_append(e, e->v2); - if (example) - BM_elem_attrs_copy(bm, bm, example, e); + if (!(create_flag & BM_CREATE_SKIP_CD)) { + if (example) { + BM_elem_attrs_copy(bm, bm, example, e); + } + else { + CustomData_bmesh_set_default(&bm->edata, &e->head.data); + } + } + BM_CHECK_ELEMENT(e); return e; } -static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f, const BMLoop *example) +static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f, + const BMLoop *example, const eBMCreateFlag create_flag) { BMLoop *l = NULL; @@ -164,22 +176,24 @@ static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f, const bm->totloop++; - if (example) { - CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, example->head.data, &l->head.data); - } - else { - CustomData_bmesh_set_default(&bm->ldata, &l->head.data); + if (!(create_flag & BM_CREATE_SKIP_CD)) { + if (example) { + CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, example->head.data, &l->head.data); + } + else { + CustomData_bmesh_set_default(&bm->ldata, &l->head.data); + } } return l; } -static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte) +static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte, const int create_flag) { #ifdef USE_BMESH_HOLES BMLoopList *lst = BLI_mempool_calloc(bm->looplistpool); #endif - BMLoop *l = bm_loop_create(bm, startv, starte, f, NULL); + BMLoop *l = bm_loop_create(bm, startv, starte, f, starte->l, create_flag); bmesh_radial_append(starte, l); @@ -211,7 +225,7 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short co i = 0; do { if (copyverts) { - verts[i] = BM_vert_create(bm, l_iter->v->co, l_iter->v); + verts[i] = BM_vert_create(bm, l_iter->v->co, l_iter->v, 0); } else { verts[i] = l_iter->v; @@ -234,7 +248,7 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short co v1 = verts[(i + 1) % f->len]; } - edges[i] = BM_edge_create(bm, v1, v2, l_iter->e, FALSE); + edges[i] = BM_edge_create(bm, v1, v2, l_iter->e, 0); } else { edges[i] = l_iter->e; @@ -242,7 +256,7 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short co i++; } while ((l_iter = l_iter->next) != l_first); - f_copy = BM_face_create(bm, verts, edges, f->len, FALSE); + f_copy = BM_face_create(bm, verts, edges, f->len, BM_CREATE_SKIP_CD); BM_elem_attrs_copy(bm, bm, f, f_copy); @@ -263,7 +277,7 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short co * only create the face, since this calloc's the length is initialized to 0, * leave adding loops to the caller. */ -BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm) +BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm, const eBMCreateFlag create_flag) { BMFace *f; @@ -286,7 +300,9 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm) f->oflags = BLI_mempool_calloc(bm->toolflagpool); } - CustomData_bmesh_set_default(&bm->pdata, &f->head.data); + if (!(create_flag & BM_CREATE_SKIP_CD)) { + CustomData_bmesh_set_default(&bm->pdata, &f->head.data); + } #ifdef USE_BMESH_HOLES f->totbounds = 0; @@ -298,7 +314,7 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm) /** * \brief Main face creation function */ -BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, int nodouble) +BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, const eBMCreateFlag create_flag) { BMFace *f = NULL; BMLoop *l, *startl, *lastl; @@ -309,7 +325,7 @@ BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, return NULL; } - if (nodouble) { + if (create_flag & BM_CREATE_NO_DOUBLE) { /* Check if face already exists */ overlap = BM_face_exists(verts, len, &f); if (overlap) { @@ -320,14 +336,14 @@ BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, } } - f = bm_face_create__internal(bm); + f = bm_face_create__internal(bm, create_flag); - startl = lastl = bm_face_boundary_add(bm, f, verts[0], edges[0]); + startl = lastl = bm_face_boundary_add(bm, f, verts[0], edges[0], create_flag); startl->v = verts[0]; startl->e = edges[0]; for (i = 1; i < len; i++) { - l = bm_loop_create(bm, verts[i], edges[i], f, edges[i]->l); + l = bm_loop_create(bm, verts[i], edges[i], f, edges[i]->l, create_flag); l->f = f; bmesh_radial_append(edges[i], l); @@ -1033,7 +1049,7 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const short do_del } /* create region face */ - newf = BM_face_create_ngon(bm, v1, v2, edges, tote, FALSE); + newf = tote ? BM_face_create_ngon(bm, v1, v2, edges, tote, 0) : NULL; if (UNLIKELY(!newf || BMO_error_occurred(bm))) { if (!BMO_error_occurred(bm)) err = N_("Invalid boundary region to join faces"); @@ -1139,7 +1155,7 @@ static BMFace *bm_face_create__sfme(BMesh *bm, BMFace *UNUSED(example)) BMLoopList *lst; #endif - f = bm_face_create__internal(bm); + f = bm_face_create__internal(bm, 0); #ifdef USE_BMESH_HOLES lst = BLI_mempool_calloc(bm->looplistpool); @@ -1223,11 +1239,11 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, } /* allocate new edge between v1 and v2 */ - e = BM_edge_create(bm, v1, v2, example, nodouble); + e = BM_edge_create(bm, v1, v2, example, nodouble ? BM_CREATE_NO_DOUBLE : 0); f2 = bm_face_create__sfme(bm, f); - f1loop = bm_loop_create(bm, v2, e, f, v2loop); - f2loop = bm_loop_create(bm, v1, e, f2, v1loop); + f1loop = bm_loop_create(bm, v2, e, f, v2loop, 0); + f2loop = bm_loop_create(bm, v1, e, f2, v1loop, 0); f1loop->prev = v2loop->prev; f2loop->prev = v1loop->prev; @@ -1334,10 +1350,10 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, * will be attached to that end and is returned in \a r_e. * * \par Examples: + * * <pre> * E * Before: OV-------------TV - * * E RE * After: OV------NV-----TV * </pre> @@ -1359,8 +1375,8 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) valence2 = bmesh_disk_count(tv); - nv = BM_vert_create(bm, tv->co, tv); - ne = BM_edge_create(bm, nv, tv, e, FALSE); + nv = BM_vert_create(bm, tv->co, tv, 0); + ne = BM_edge_create(bm, nv, tv, e, 0); bmesh_disk_edge_remove(ne, tv); bmesh_disk_edge_remove(ne, nv); @@ -1403,7 +1419,7 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) nextl = nextl != nextl->radial_next ? nextl->radial_next : NULL; bmesh_radial_loop_remove(l, NULL); - nl = bm_loop_create(bm, NULL, NULL, l->f, l); + nl = bm_loop_create(bm, NULL, NULL, l->f, l, 0); nl->prev = l; nl->next = (l->next); nl->prev->next = nl; @@ -1919,7 +1935,7 @@ int bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len) verts = MEM_callocN(sizeof(BMVert *) * maxindex, __func__); verts[0] = v; for (i = 1; i < maxindex; i++) { - verts[i] = BM_vert_create(bm, v->co, v); + verts[i] = BM_vert_create(bm, v->co, v, 0); } /* Replace v with the new verts in each group */ @@ -2085,7 +2101,7 @@ int bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep) e->l = l_sep->radial_next; } - ne = BM_edge_create(bm, e->v1, e->v2, e, FALSE); + ne = BM_edge_create(bm, e->v1, e->v2, e, 0); bmesh_radial_loop_remove(l_sep, e); bmesh_radial_append(ne, l_sep); l_sep->e = ne; diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h index 0667ed9ea1c..5fd4a6ec7df 100644 --- a/source/blender/bmesh/intern/bmesh_core.h +++ b/source/blender/bmesh/intern/bmesh_core.h @@ -29,9 +29,18 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short copyedges); -BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example); -BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, int nodouble); -BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, int nodouble); +typedef enum eBMCreateFlag { + /* faces and edges only */ + BM_CREATE_NO_DOUBLE = (1 << 1), + /* Skip CustomData - for all element types data, + * use if we immediately write customdata into the element so this skips copying from 'example' + * args or setting defaults, speeds up conversion when data is converted all at once. */ + BM_CREATE_SKIP_CD = (1 << 2), +} eBMCreateFlag; + +BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example, const eBMCreateFlag create_flag); +BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, const eBMCreateFlag create_flag); +BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, const eBMCreateFlag create_flag); void BM_face_edges_kill(BMesh *bm, BMFace *f); void BM_face_verts_kill(BMesh *bm, BMFace *f); diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index 62abf43829b..388d148377a 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -206,7 +206,7 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE); for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) { - v = BM_vert_create(bm, keyco && set_key ? keyco[i] : mvert->co, NULL); + v = BM_vert_create(bm, keyco && set_key ? keyco[i] : mvert->co, NULL, BM_CREATE_SKIP_CD); BM_elem_index_set(v, i); /* set_ok */ vt[i] = v; @@ -220,11 +220,11 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) normal_short_to_float_v3(v->no, mvert->no); - BM_elem_float_data_set(&bm->vdata, v, CD_BWEIGHT, (float)mvert->bweight / 255.0f); - - /* Copy Custom Dat */ + /* Copy Custom Data */ CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data); + BM_elem_float_data_set(&bm->vdata, v, CD_BWEIGHT, (float)mvert->bweight / 255.0f); + /* set shapekey data */ if (me->key) { /* set shape key original index */ @@ -254,7 +254,7 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) medge = me->medge; for (i = 0; i < me->totedge; i++, medge++) { - e = BM_edge_create(bm, vt[medge->v1], vt[medge->v2], NULL, FALSE); + e = BM_edge_create(bm, vt[medge->v1], vt[medge->v2], NULL, BM_CREATE_SKIP_CD); BM_elem_index_set(e, i); /* set_ok */ et[i] = e; @@ -312,7 +312,7 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) } #endif - f = BM_face_create(bm, verts, fedges, mpoly->totloop, FALSE); + f = BM_face_create(bm, verts, fedges, mpoly->totloop, BM_CREATE_SKIP_CD); if (UNLIKELY(f == NULL)) { printf("%s: Warning! Bad face in mesh" @@ -338,7 +338,7 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) j = 0; BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, j) { /* Save index of correspsonding MLoop */ - BM_elem_index_set(l, mpoly->loopstart + j); /* set_loop */ + CustomData_to_bmesh_block(&me->ldata, &bm->ldata, mpoly->loopstart + j, &l->head.data); } /* Copy Custom Data */ @@ -347,23 +347,6 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) bm->elem_index_dirty &= ~BM_FACE; /* added in order, clear dirty flag */ - { - BMIter fiter; - BMIter liter; - - /* Copy over loop CustomData. Doing this in a separate loop isn't necessary - * but is an optimization, to avoid copying a bunch of interpolated customdata - * for each BMLoop (from previous BMLoops using the same edge), always followed - * by freeing the interpolated data and overwriting it with data from the Mesh. */ - BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - int li = BM_elem_index_get(l); - CustomData_to_bmesh_block(&me->ldata, &bm->ldata, li, &l->head.data); - BM_elem_index_set(l, 0); /* set_loop */ - } - } - } - if (me->mselect && me->totselect != 0) { BMVert **vert_array = MEM_callocN(sizeof(BMVert *) * bm->totvert, diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index dc8b52423ab..89516061f91 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -142,9 +142,10 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v) return FALSE; } #else - BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, TRUE); - - if (!BM_vert_collapse_faces(bm, v->e, v, 1.0, FALSE, TRUE)) { + if (UNLIKELY(!BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, TRUE))) { + return FALSE; + } + else if (UNLIKELY(!BM_vert_collapse_faces(bm, v->e, v, 1.0, FALSE, TRUE))) { return FALSE; } #endif diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index ec07eb5d9f7..58c6e051e48 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -59,8 +59,10 @@ #include "bmesh.h" #include "intern/bmesh_private.h" -/* ok, I'm going to write a little docgen script. so all - * bmop comments must conform to the following template/rules: +/* The formatting of these bmesh operators is parsed by + * 'doc/python_api/rst_from_bmesh_opdefines.py' + * for use in python docs, so reStructuredText may be used + * rather then doxygen syntax. * * template (py quotes used because nested comments don't work * on all C compilers): @@ -79,148 +81,149 @@ * so the first line is the "title" of the bmop. * subsequent line blocks separated by blank lines * are paragraphs. individual descriptions of slots - * would be extracted from comments - * next to them, e.g. + * are extracted from comments next to them. * - * {BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, //output slot, boundary region + * eg: + * {BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, """ output slot, boundary region """ * - * the doc generator would automatically detect the presence of "output slot" - * and flag the slot as an output. the same happens for "input slot". also - * note that "edges", "faces", "verts", "loops", and "geometry" are valid - * substitutions for "slot". + * ... or: * - * note that slots default to being input slots. + * """ output slot, boundary region """ + * {BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, + * + * Both are acceptable. + * note that '//' comments are ignored. */ /* - * Vertex Smooth + * Vertex Smooth. * * Smooths vertices by using a basic vertex averaging scheme. */ static BMOpDefine bmo_smooth_vert_def = { "smooth_vert", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_BOOL, "mirror_clip_x"}, /* set vertices close to the x axis before the operation to 0 */ - {BMO_OP_SLOT_BOOL, "mirror_clip_y"}, /* set vertices close to the y axis before the operation to 0 */ - {BMO_OP_SLOT_BOOL, "mirror_clip_z"}, /* set vertices close to the z axis before the operation to 0 */ - {BMO_OP_SLOT_FLT, "clip_dist"}, /* clipping threshod for the above three slots */ - {BMO_OP_SLOT_BOOL, "use_axis_x"}, /* smooth vertices along X axis */ - {BMO_OP_SLOT_BOOL, "use_axis_y"}, /* smooth vertices along Y axis */ - {BMO_OP_SLOT_BOOL, "use_axis_z"}, /* smooth vertices along Z axis */ - {0}, - }, - {{0}}, /* no output */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"mirror_clip_x", BMO_OP_SLOT_BOOL}, /* set vertices close to the x axis before the operation to 0 */ + {"mirror_clip_y", BMO_OP_SLOT_BOOL}, /* set vertices close to the y axis before the operation to 0 */ + {"mirror_clip_z", BMO_OP_SLOT_BOOL}, /* set vertices close to the z axis before the operation to 0 */ + {"clip_dist", BMO_OP_SLOT_FLT}, /* clipping threshold for the above three slots */ + {"use_axis_x", BMO_OP_SLOT_BOOL}, /* smooth vertices along X axis */ + {"use_axis_y", BMO_OP_SLOT_BOOL}, /* smooth vertices along Y axis */ + {"use_axis_z", BMO_OP_SLOT_BOOL}, /* smooth vertices along Z axis */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_smooth_vert_exec, 0 }; /* - * Vertext Smooth Laplacian + * Vertext Smooth Laplacian. + * * Smooths vertices by using Laplacian smoothing propose by. - * Desbrun, et al. Implicit Fairing of Irregular Meshes using Diffusion and Curvature Flow + * Desbrun, et al. Implicit Fairing of Irregular Meshes using Diffusion and Curvature Flow. */ static BMOpDefine bmo_smooth_laplacian_vert_def = { "smooth_laplacian_vert", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_FLT, "lambda"}, /* lambda param */ - {BMO_OP_SLOT_FLT, "lambda_border"}, /* lambda param in border */ - {BMO_OP_SLOT_BOOL, "use_x"}, /* Smooth object along X axis */ - {BMO_OP_SLOT_BOOL, "use_y"}, /* Smooth object along Y axis */ - {BMO_OP_SLOT_BOOL, "use_z"}, /* Smooth object along Z axis */ - {BMO_OP_SLOT_BOOL, "preserve_volume"}, /* Apply volume preservation after smooth */ - {0}, + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"lambda", BMO_OP_SLOT_FLT}, /* lambda param */ + {"lambda_border", BMO_OP_SLOT_FLT}, /* lambda param in border */ + {"use_x", BMO_OP_SLOT_BOOL}, /* Smooth object along X axis */ + {"use_y", BMO_OP_SLOT_BOOL}, /* Smooth object along Y axis */ + {"use_z", BMO_OP_SLOT_BOOL}, /* Smooth object along Z axis */ + {"preserve_volume", BMO_OP_SLOT_BOOL}, /* Apply volume preservation after smooth */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_smooth_laplacian_vert_exec, 0 }; /* - * Right-Hand Faces + * Right-Hand Faces. * * Computes an "outside" normal for the specified input faces. */ - static BMOpDefine bmo_recalc_face_normals_def = { "recalc_face_normals", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, - {BMO_OP_SLOT_BOOL, "use_flip"}, /* internal flag, used by bmesh_rationalize_normals */ - {0}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {"use_flip", BMO_OP_SLOT_BOOL}, /* Reverse the result */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_recalc_face_normals_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Region Extend + * Region Extend. * * used to implement the select more/less tools. * this puts some geometry surrounding regions of * geometry in geom into geom.out. * - * if usefaces is 0 then geom.out spits out verts and edges, + * if use_faces is 0 then geom.out spits out verts and edges, * otherwise it spits out faces. */ static BMOpDefine bmo_region_extend_def = { "region_extend", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry */ - {BMO_OP_SLOT_BOOL, "use_constrict"}, /* find boundary inside the regions, not outside. */ - {BMO_OP_SLOT_BOOL, "use_faces"}, /* extend from faces instead of edges */ - {0}, + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */ + {"use_constrict", BMO_OP_SLOT_BOOL}, /* find boundary inside the regions, not outside. */ + {"use_faces", BMO_OP_SLOT_BOOL}, /* extend from faces instead of edges */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* output slot, computed boundary geometry. */ - {0}, + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output slot, computed boundary geometry. */ + {{'\0'}}, }, bmo_region_extend_exec, 0 }; /* - * Edge Rotate + * Edge Rotate. * * Rotates edges topologically. Also known as "spin edge" to some people. - * Simple example: [/] becomes [|] then [\]. + * Simple example: ``[/] becomes [|] then [\]``. */ static BMOpDefine bmo_rotate_edges_def = { "rotate_edges", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_BOOL, "use_ccw"}, /* rotate edge counter-clockwise if true, othewise clockwise */ - {0}, + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {"use_ccw", BMO_OP_SLOT_BOOL}, /* rotate edge counter-clockwise if true, otherwise clockwise */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* newly spun edges */ - {0}, + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* newly spun edges */ + {{'\0'}}, }, bmo_rotate_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; /* - * Reverse Faces + * Reverse Faces. * - * Reverses the winding (vertex order) of faces. This has the effect of - * flipping the normal. + * Reverses the winding (vertex order) of faces. + * This has the effect of flipping the normal. */ static BMOpDefine bmo_reverse_faces_def = { "reverse_faces", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {0}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_reverse_faces_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Edge Bisect + * Edge Bisect. * * Splits input edges (but doesn't do anything else). * This creates a 2-valence vert. @@ -228,50 +231,49 @@ static BMOpDefine bmo_reverse_faces_def = { static BMOpDefine bmo_bisect_edges_def = { "bisect_edges", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_INT, "cuts"}, /* number of cuts */ - {0}, + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {"cuts", BMO_OP_SLOT_INT}, /* number of cuts */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom_split.out"}, /* newly created vertices and edges */ - {0}, + {{"geom_split.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* newly created vertices and edges */ + {{'\0'}}, }, bmo_bisect_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; /* - * Mirror + * Mirror. * * Mirrors geometry along an axis. The resulting geometry is welded on using * merge_dist. Pairs of original/mirrored vertices are welded using the merge_dist * parameter (which defines the minimum distance for welding to happen). */ - static BMOpDefine bmo_mirror_def = { "mirror", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix defining the mirror transformation */ - {BMO_OP_SLOT_FLT, "merge_dist"}, /* maximum distance for merging. does no merging if 0. */ - {BMO_OP_SLOT_INT, "axis"}, /* the axis to use, 0, 1, or 2 for x, y, z */ - {BMO_OP_SLOT_BOOL, "mirror_u"}, /* mirror UVs across the u axis */ - {BMO_OP_SLOT_BOOL, "mirror_v"}, /* mirror UVs across the v axis */ - {0}, + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix defining the mirror transformation */ + {"merge_dist", BMO_OP_SLOT_FLT}, /* maximum distance for merging. does no merging if 0. */ + {"axis", BMO_OP_SLOT_INT}, /* the axis to use, 0, 1, or 2 for x, y, z */ + {"mirror_u", BMO_OP_SLOT_BOOL}, /* mirror UVs across the u axis */ + {"mirror_v", BMO_OP_SLOT_BOOL}, /* mirror UVs across the v axis */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* output geometry, mirrored */ - {0}, + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output geometry, mirrored */ + {{'\0'}}, }, bmo_mirror_exec, 0, }; /* - * Find Doubles + * Find Doubles. * - * Takes input verts and find vertices they should weld to. Outputs a - * mapping slot suitable for use with the weld verts bmop. + * Takes input verts and find vertices they should weld to. + * Outputs a mapping slot suitable for use with the weld verts bmop. * * If keep_verts is used, vertices outside that set can only be merged * with vertices in that set. @@ -279,21 +281,21 @@ static BMOpDefine bmo_mirror_def = { static BMOpDefine bmo_find_doubles_def = { "find_doubles", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_ELEMENT_BUF, "keep_verts"}, /* list of verts to keep */ - {BMO_OP_SLOT_FLT, "dist"}, /* minimum distance */ - {0}, + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"keep_verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* list of verts to keep */ + {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_MAPPING, "targetmap.out"}, - {0}, + {{"targetmap.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {{'\0'}}, }, bmo_find_doubles_exec, 0, }; /* - * Remove Doubles + * Remove Doubles. * * Finds groups of vertices closer then dist and merges them together, * using the weld verts bmop. @@ -301,70 +303,69 @@ static BMOpDefine bmo_find_doubles_def = { static BMOpDefine bmo_remove_doubles_def = { "remove_doubles", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input verts */ - {BMO_OP_SLOT_FLT, "dist"}, /* minimum distance */ - {0}, + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input verts */ + {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_remove_doubles_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Auto Merge + * Auto Merge. * - * Finds groups of vertices closer then dist and merges them together, + * Finds groups of vertices closer then **dist** and merges them together, * using the weld verts bmop. The merges must go from a vert not in - * verts to one in verts. + * **verts** to one in **verts**. */ static BMOpDefine bmo_automerge_def = { "automerge", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input verts */ - {BMO_OP_SLOT_FLT, "dist"}, /* minimum distance */ - {0}, + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input verts */ + {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_automerge_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Collapse Connected + * Collapse Connected. * * Collapses connected vertices */ static BMOpDefine bmo_collapse_def = { "collapse", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */ - {0}, + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edge */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_collapse_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; - /* - * Facedata point Merge + * Face-Data Point Merge. * * Merge uv/vcols at a specific vertex. */ static BMOpDefine bmo_pointmerge_facedata_def = { "pointmerge_facedata", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_ELEMENT_BUF, "snapv"}, /* snap vertex */ - {0}, + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"vert_snap", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE}}, /* snap vertex */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_pointmerge_facedata_exec, 0, }; /* - * Average Vertices Facevert Data + * Average Vertices Facevert Data. * * Merge uv/vcols associated with the input vertices at * the bounding box center. (I know, it's not averaging but @@ -373,67 +374,68 @@ static BMOpDefine bmo_pointmerge_facedata_def = { static BMOpDefine bmo_average_vert_facedata_def = { "average_vert_facedata", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertice */ - {0}, + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertice */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_average_vert_facedata_exec, 0, }; /* - * Point Merge + * Point Merge. * * Merge verts together at a point. */ static BMOpDefine bmo_pointmerge_def = { "pointmerge", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertice */ - {BMO_OP_SLOT_VEC, "merge_co"}, - {0}, + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertice */ + {"merge_co", BMO_OP_SLOT_VEC}, + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_pointmerge_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Collapse Connected UVs + * Collapse Connected UV's. * * Collapses connected UV vertices. */ static BMOpDefine bmo_collapse_uvs_def = { "collapse_uvs", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */ - {0}, + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edge */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_collapse_uvs_exec, 0, }; /* - * Weld Verts + * Weld Verts. * - * Welds verts together (kindof like remove doubles, merge, etc, all of which + * Welds verts together (kind-of like remove doubles, merge, etc, all of which * use or will use this bmop). You pass in mappings from vertices to the vertices * they weld with. */ static BMOpDefine bmo_weld_verts_def = { "weld_verts", /* slots_in */ - {{BMO_OP_SLOT_MAPPING, "targetmap"}, /* maps welded vertices to verts they should weld to */ - {0}, + /* maps welded vertices to verts they should weld to */ + {{"targetmap", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_weld_verts_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Make Vertex + * Make Vertex. * * Creates a single vertex; this bmop was necessary * for click-create-vertex. @@ -441,19 +443,19 @@ static BMOpDefine bmo_weld_verts_def = { static BMOpDefine bmo_create_vert_def = { "create_vert", /* slots_in */ - {{BMO_OP_SLOT_VEC, "co"}, /* the coordinate of the new vert */ - {0}, + {{"co", BMO_OP_SLOT_VEC}, /* the coordinate of the new vert */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "vert.out"}, /* the new vert */ - {0}, + {{"vert.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* the new vert */ + {{'\0'}}, }, bmo_create_vert_exec, 0, }; /* - * Join Triangles + * Join Triangles. * * Tries to intelligently join triangles according * to various settings and stuff. @@ -461,29 +463,28 @@ static BMOpDefine bmo_create_vert_def = { static BMOpDefine bmo_join_triangles_def = { "join_triangles", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input geometry. */ - {BMO_OP_SLOT_BOOL, "cmp_sharp"}, - {BMO_OP_SLOT_BOOL, "cmp_uvs"}, - {BMO_OP_SLOT_BOOL, "cmp_vcols"}, - {BMO_OP_SLOT_BOOL, "cmp_materials"}, - {BMO_OP_SLOT_FLT, "limit"}, - {0}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input geometry. */ + {"cmp_sharp", BMO_OP_SLOT_BOOL}, + {"cmp_uvs", BMO_OP_SLOT_BOOL}, + {"cmp_vcols", BMO_OP_SLOT_BOOL}, + {"cmp_materials", BMO_OP_SLOT_BOOL}, + {"limit", BMO_OP_SLOT_FLT}, + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* joined faces */ - {0}, + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* joined faces */ + {{'\0'}}, }, bmo_join_triangles_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Contextual Create + * Contextual Create. * - * This is basically fkey, it creates + * This is basically F-key, it creates * new faces from vertices, makes stuff from edge nets, - * makes wire edges, etc. It also dissolves - * faces. + * makes wire edges, etc. It also dissolves faces. * * Three verts become a triangle, four become a quad. Two * become a wire edge. @@ -491,63 +492,70 @@ static BMOpDefine bmo_join_triangles_def = { static BMOpDefine bmo_contextual_create_def = { "contextual_create", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry. */ - {BMO_OP_SLOT_INT, "mat_nr"}, /* material to use */ - {BMO_OP_SLOT_BOOL, "use_smooth"}, /* smooth to use */ - {0}, + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry. */ + {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */ + {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth to use */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* newly-made face(s) */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* newly-made face(s) */ /* note, this is for stand-alone edges only, not edges which are apart of newly created faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* newly-made edge(s) */ - {0}, + {"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* newly-made edge(s) */ + {{'\0'}}, }, bmo_contextual_create_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Bridge edge loops with faces + * Bridge edge loops with faces. */ static BMOpDefine bmo_bridge_loops_def = { "bridge_loops", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */ - {BMO_OP_SLOT_BOOL, "use_merge"}, - {BMO_OP_SLOT_FLT, "merge_factor"}, - {0}, + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edge */ + {"use_merge", BMO_OP_SLOT_BOOL}, + {"merge_factor", BMO_OP_SLOT_FLT}, + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* new faces */ - {0}, + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */ + {{'\0'}}, }, bmo_bridge_loops_exec, 0, }; +/* + * Edge Net Fill. + * + * Create faces defined by enclosed edges. + */ static BMOpDefine bmo_edgenet_fill_def = { "edgenet_fill", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */ - {BMO_OP_SLOT_MAPPING, "restrict"}, /* restricts edges to groups. maps edges to integer */ - {BMO_OP_SLOT_BOOL, "use_restrict"}, - {BMO_OP_SLOT_BOOL, "use_fill_check"}, - {BMO_OP_SLOT_ELEMENT_BUF, "exclude_faces"}, /* list of faces to ignore for manifold check */ - {BMO_OP_SLOT_INT, "mat_nr"}, /* material to use */ - {BMO_OP_SLOT_BOOL, "use_smooth"}, /* material to use */ - {0}, + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edge */ + /* restricts edges to groups. maps edges to integer */ + {"restrict", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_BOOL}}, + {"use_restrict", BMO_OP_SLOT_BOOL}, + {"use_fill_check", BMO_OP_SLOT_BOOL}, + {"exclude_faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* list of faces to ignore for manifold check */ + {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */ + {"use_smooth", BMO_OP_SLOT_BOOL}, /* material to use */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_MAPPING, "face_groupmap.out"}, /* maps new faces to the group numbers they came from */ - {BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* new face */ - {0}, + /* maps new faces to the group numbers they came from */ + {{"face_groupmap.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new face */ + {{'\0'}}, }, bmo_edgenet_fill_exec, 0, }; /* - * Edgenet Prepare + * Edgenet Prepare. * * Identifies several useful edge loop cases and modifies them so * they'll become a face when edgenet_fill is called. The cases covered are: @@ -559,74 +567,72 @@ static BMOpDefine bmo_edgenet_fill_def = { static BMOpDefine bmo_edgenet_prepare_def = { "edgenet_prepare", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {0}, + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* new edges */ - {0}, + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* new edges */ + {{'\0'}}, }, - bmo_edgenet_prepare, + bmo_edgenet_prepare_exec, 0, }; /* - * Rotate + * Rotate. * - * Rotate vertices around a center, using a 3x3 rotation - * matrix. Equivalent of the old rotateflag function. + * Rotate vertices around a center, using a 3x3 rotation matrix. */ static BMOpDefine bmo_rotate_def = { "rotate", /* slots_in */ - {{BMO_OP_SLOT_VEC, "cent"}, /* center of rotation */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix defining rotation */ - {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0}, + {{"cent", BMO_OP_SLOT_VEC}, /* center of rotation */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix defining rotation */ + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_rotate_exec, 0, }; /* - * Translate + * Translate. * - * Translate vertices by an offset. Equivalent of the - * old translateflag function. + * Translate vertices by an offset. */ static BMOpDefine bmo_translate_def = { "translate", /* slots_in */ - {{BMO_OP_SLOT_VEC, "vec"}, /* translation offset */ - {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0}, + {{"vec", BMO_OP_SLOT_VEC}, /* translation offset */ + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_translate_exec, 0, }; /* - * Scale + * Scale. * * Scales vertices by an offset. */ static BMOpDefine bmo_scale_def = { "scale", /* slots_in */ - {{BMO_OP_SLOT_VEC, "vec"}, /* scale factor */ - {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0}, + {{"vec", BMO_OP_SLOT_VEC}, /* scale factor */ + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_scale_exec, 0, }; /* - * Transform + * Transform. * * Transforms a set of vertices by a matrix. Multiplies * the vertex coordinates with the matrix. @@ -634,17 +640,17 @@ static BMOpDefine bmo_scale_def = { static BMOpDefine bmo_transform_def = { "transform", /* slots_in */ - {{BMO_OP_SLOT_MAT, "mat"}, /* transform matrix */ - {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0}, + {{"matrix", BMO_OP_SLOT_MAT}, /* transform matrix */ + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_transform_exec, 0, }; /* - * Object Load BMesh + * Object Load BMesh. * * Loads a bmesh into an object/mesh. This is a "private" * bmop. @@ -652,36 +658,39 @@ static BMOpDefine bmo_transform_def = { static BMOpDefine bmo_object_load_bmesh_def = { "object_load_bmesh", /* slots_in */ - {{BMO_OP_SLOT_PTR, "scene"}, - {BMO_OP_SLOT_PTR, "object"}, - {0}, + {{"scene", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_SCENE}}, + {"object", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}}, + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_object_load_bmesh_exec, 0, }; /* - * BMesh to Mesh + * BMesh to Mesh. * * Converts a bmesh to a Mesh. This is reserved for exiting editmode. */ static BMOpDefine bmo_bmesh_to_mesh_def = { "bmesh_to_mesh", /* slots_in */ - {{BMO_OP_SLOT_PTR, "mesh"}, /* pointer to a mesh structure to fill in */ - {BMO_OP_SLOT_PTR, "object"}, /* pointer to an object structure */ - {BMO_OP_SLOT_BOOL, "skip_tessface"}, /* don't calculate mfaces */ - {0}, + { + /* pointer to a mesh structure to fill in */ + {"mesh", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_MESH}}, + /* pointer to an object structure */ + {"object", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}}, + {"skip_tessface", BMO_OP_SLOT_BOOL}, /* don't calculate mfaces */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_bmesh_to_mesh_exec, 0, }; /* - * Mesh to BMesh + * Mesh to BMesh. * * Load the contents of a mesh into the bmesh. this bmop is private, it's * reserved exclusively for entering editmode. @@ -689,38 +698,40 @@ static BMOpDefine bmo_bmesh_to_mesh_def = { static BMOpDefine bmo_mesh_to_bmesh_def = { "mesh_to_bmesh", /* slots_in */ - {{BMO_OP_SLOT_PTR, "mesh"}, /* pointer to a Mesh structure */ - {BMO_OP_SLOT_PTR, "object"}, /* pointer to an Object structure */ - {BMO_OP_SLOT_BOOL, "use_shapekey"}, /* load active shapekey coordinates into verts */ - {0}, + { + /* pointer to a Mesh structure */ + {"mesh", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_MESH}}, + /* pointer to an Object structure */ + {"object", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}}, + {"use_shapekey", BMO_OP_SLOT_BOOL}, /* load active shapekey coordinates into verts */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_mesh_to_bmesh_exec, 0 }; /* - * Individual Face Extrude + * Individual Face Extrude. * * Extrudes faces individually. */ static BMOpDefine bmo_extrude_discrete_faces_def = { "extrude_discrete_faces", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {0}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* output faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "geom_skirt.out"}, /* output skirt geometry, faces and edges */ - {0}, + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ + {{'\0'}}, }, bmo_extrude_discrete_faces_exec, 0 }; /* - * Extrude Only Edges + * Extrude Only Edges. * * Extrudes Edges into faces, note that this is very simple, there's no fancy * winged extrusion. @@ -728,247 +739,308 @@ static BMOpDefine bmo_extrude_discrete_faces_def = { static BMOpDefine bmo_extrude_edge_only_def = { "extrude_edge_only", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input vertices */ - {0}, + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input vertices */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* output geometry */ - {0}, + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output geometry */ + {{'\0'}}, }, bmo_extrude_edge_only_exec, 0 }; /* - * Individual Vertex Extrude + * Individual Vertex Extrude. * * Extrudes wire edges from vertices. */ static BMOpDefine bmo_extrude_vert_indiv_def = { "extrude_vert_indiv", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0}, + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* output wire edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output vertices */ - {0}, + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output wire edges */ + {"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output vertices */ + {{'\0'}}, }, bmo_extrude_vert_indiv_exec, 0 }; +/* + * Connect Verts. + * + * Split faces by adding edges that connect **verts**. + */ static BMOpDefine bmo_connect_verts_def = { "connect_verts", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, - {0}, + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, - {0}, + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {{'\0'}}, }, bmo_connect_verts_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Extrude Faces. + * + * Extrude operator (does not transform) + */ static BMOpDefine bmo_extrude_face_region_def = { "extrude_face_region", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* edges and faces */ - {BMO_OP_SLOT_MAPPING, "edges_exclude"}, - {BMO_OP_SLOT_BOOL, "use_keep_orig"}, /* keep original geometry */ - {0}, + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* edges and faces */ + {"edges_exclude", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_EMPTY}}, + {"use_keep_orig", BMO_OP_SLOT_BOOL}, /* keep original geometry */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, - {0}, + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {{'\0'}}, }, bmo_extrude_face_region_exec, 0 }; +/* + * Dissolve Verts. + */ static BMOpDefine bmo_dissolve_verts_def = { "dissolve_verts", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, - {0}, + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_dissolve_verts_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Dissolve Edges. + */ static BMOpDefine bmo_dissolve_edges_def = { "dissolve_edges", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, - {BMO_OP_SLOT_BOOL, "use_verts"}, /* dissolve verts left between only 2 edges. */ - {0}, + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {"use_verts", BMO_OP_SLOT_BOOL}, /* dissolve verts left between only 2 edges. */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "region.out"}, - {0}, + {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {{'\0'}}, }, bmo_dissolve_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Dissolve Edge Loop. + */ static BMOpDefine bmo_dissolve_edge_loop_def = { "dissolve_edge_loop", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, - {0}, + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "region.out"}, - {0}, + {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {{'\0'}}, }, bmo_dissolve_edgeloop_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Dissolve Faces. + */ static BMOpDefine bmo_dissolve_faces_def = { "dissolve_faces", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, - {BMO_OP_SLOT_BOOL, "use_verts"}, /* dissolve verts left between only 2 edges. */ - {0}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {"use_verts", BMO_OP_SLOT_BOOL}, /* dissolve verts left between only 2 edges. */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "region.out"}, - {0}, + {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {{'\0'}}, }, bmo_dissolve_faces_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Limited Dissolve. + * + * Dissolve planar faces and co-linear edges. + */ static BMOpDefine bmo_dissolve_limit_def = { "dissolve_limit", /* slots_in */ - {{BMO_OP_SLOT_FLT, "angle_limit"}, /* total rotation angle (degrees) */ - {BMO_OP_SLOT_BOOL, "use_dissolve_boundaries"}, - {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, - {BMO_OP_SLOT_ELEMENT_BUF, "edges"}, - {0}, + {{"angle_limit", BMO_OP_SLOT_FLT}, /* total rotation angle (radians) */ + {"use_dissolve_boundaries", BMO_OP_SLOT_BOOL}, + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, + {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_dissolve_limit_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Triangulate. + */ static BMOpDefine bmo_triangulate_def = { "triangulate", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, - {BMO_OP_SLOT_BOOL, "use_beauty"}, - {0}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {"use_beauty", BMO_OP_SLOT_BOOL}, + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, - {BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, - {BMO_OP_SLOT_MAPPING, "facemap.out"}, - {0}, + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {"face_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {{'\0'}}, }, bmo_triangulate_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Un-Subdivide. + * + * Reduce detail in geometry containing grids. + */ static BMOpDefine bmo_unsubdivide_def = { "unsubdivide", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_INT, "iterations"}, - {0}, + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"iterations", BMO_OP_SLOT_INT}, + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_unsubdivide_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Subdivide Edges. + * + * Advanced operator for subdividing edges + * with options for face patterns, smoothing and randomization. + */ static BMOpDefine bmo_subdivide_edges_def = { "subdivide_edges", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, - {BMO_OP_SLOT_FLT, "smooth"}, - {BMO_OP_SLOT_FLT, "fractal"}, - {BMO_OP_SLOT_FLT, "along_normal"}, - {BMO_OP_SLOT_INT, "cuts"}, - {BMO_OP_SLOT_INT, "seed"}, - {BMO_OP_SLOT_MAPPING, "custompatterns"}, - {BMO_OP_SLOT_MAPPING, "edgepercents"}, - - {BMO_OP_SLOT_INT, "quad_corner_type"}, /* quad corner type, see bmesh_operators.h */ - {BMO_OP_SLOT_BOOL, "use_gridfill"}, /* fill in fully-selected faces with a grid */ - {BMO_OP_SLOT_BOOL, "use_singleedge"}, /* tessellate the case of one edge selected in a quad or triangle */ - {BMO_OP_SLOT_BOOL, "use_sphere"}, /* for making new primitives only */ - {0}, + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {"smooth", BMO_OP_SLOT_FLT}, + {"fractal", BMO_OP_SLOT_FLT}, + {"along_normal", BMO_OP_SLOT_FLT}, + {"cuts", BMO_OP_SLOT_INT}, + {"seed", BMO_OP_SLOT_INT}, + {"custom_patterns", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL}}, /* uses custom pointers */ + {"edge_percents", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_FLT}}, + + {"quad_corner_type", BMO_OP_SLOT_INT}, /* quad corner type, see bmesh_operators.h */ + {"use_grid_fill", BMO_OP_SLOT_BOOL}, /* fill in fully-selected faces with a grid */ + {"use_single_edge", BMO_OP_SLOT_BOOL}, /* tessellate the case of one edge selected in a quad or triangle */ + {"use_only_quads", BMO_OP_SLOT_BOOL}, /* only subdivide quads (for loopcut) */ + {"use_sphere", BMO_OP_SLOT_BOOL}, /* for making new primitives only */ + {{'\0'}}, }, /* slots_out */ {/* these next three can have multiple types of elements in them */ - {BMO_OP_SLOT_ELEMENT_BUF, "geom_inner.out"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geom_split.out"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* contains all output geometr */ - {0}, + {"geom_inner.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"geom_split.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* contains all output geometr */ + {{'\0'}}, }, bmo_subdivide_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Delete Geometry. + * + * Utility operator to delete geometry. + */ static BMOpDefine bmo_delete_def = { "delete", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_INT, "context"}, - {0}, + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"context", BMO_OP_SLOT_INT}, /* enum DEL_VERTS ... */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_delete_exec, 0 }; +/* + * Duplicate Geometry. + * + * Utility operator to duplicate geometry, + * optionally into a destination mesh. + */ static BMOpDefine bmo_duplicate_def = { "duplicate", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_PTR, "dest"}, /* destination bmesh, if NULL will use current on */ - {0}, + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + /* destination bmesh, if NULL will use current on */ + {"dest", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_BMESH}}, + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom_orig.out"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, + {{"geom_orig.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* facemap maps from source faces to dupe * faces, and from dupe faces to source faces */ - {BMO_OP_SLOT_MAPPING, "facemap.out"}, - {BMO_OP_SLOT_MAPPING, "boundarymap.out"}, - {BMO_OP_SLOT_MAPPING, "isovertmap.out"}, - {0}, + {"face_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {"boundary_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {"isovert_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {{'\0'}}, }, bmo_duplicate_exec, 0 }; +/* + * Split Off Geometry. + * + * Disconnect geometry from adjacent edges and faces, + * optionally into a destination mesh. + */ static BMOpDefine bmo_split_def = { "split", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_PTR, "dest"}, /* destination bmesh, if NULL will use current one */ - {BMO_OP_SLOT_BOOL, "use_only_faces"}, /* when enabled. don't duplicate loose verts/edges */ - {0}, + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + /* destination bmesh, if NULL will use current one */ + {"dest", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_BMESH}}, + {"use_only_faces", BMO_OP_SLOT_BOOL}, /* when enabled. don't duplicate loose verts/edges */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, - {BMO_OP_SLOT_MAPPING, "boundarymap.out"}, - {BMO_OP_SLOT_MAPPING, "isovertmap.out"}, - {0}, + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"boundary_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {"isovert_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {{'\0'}}, }, bmo_split_exec, 0 }; /* - * Spin + * Spin. * * Extrude or duplicate geometry a number of times, * rotating and possibly translating after each step @@ -976,18 +1048,18 @@ static BMOpDefine bmo_split_def = { static BMOpDefine bmo_spin_def = { "spin", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_VEC, "cent"}, /* rotation center */ - {BMO_OP_SLOT_VEC, "axis"}, /* rotation axis */ - {BMO_OP_SLOT_VEC, "dvec"}, /* translation delta per step */ - {BMO_OP_SLOT_FLT, "angle"}, /* total rotation angle (degrees) */ - {BMO_OP_SLOT_INT, "steps"}, /* number of steps */ - {BMO_OP_SLOT_BOOL, "use_duplicate"}, /* duplicate or extrude? */ - {0}, + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"cent", BMO_OP_SLOT_VEC}, /* rotation center */ + {"axis", BMO_OP_SLOT_VEC}, /* rotation axis */ + {"dvec", BMO_OP_SLOT_VEC}, /* translation delta per step */ + {"angle", BMO_OP_SLOT_FLT}, /* total rotation angle (radians) */ + {"steps", BMO_OP_SLOT_INT}, /* number of steps */ + {"use_duplicate", BMO_OP_SLOT_BOOL}, /* duplicate or extrude? */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom_last.out"}, /* result of last step */ - {0}, + {{"geom_last.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* result of last step */ + {{'\0'}}, }, bmo_spin_exec, 0 @@ -995,486 +1067,490 @@ static BMOpDefine bmo_spin_def = { /* - * Similar faces search + * Similar Faces Search. * * Find similar faces (area/material/perimeter, ...). */ static BMOpDefine bmo_similar_faces_def = { "similar_faces", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_INT, "type"}, /* type of selection */ - {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ - {BMO_OP_SLOT_INT, "compare"}, /* comparison method */ - {0}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"type", BMO_OP_SLOT_INT}, /* type of selection */ + {"thresh", BMO_OP_SLOT_FLT}, /* threshold of selection */ + {"compare", BMO_OP_SLOT_INT}, /* comparison method */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* output faces */ - {0}, + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ + {{'\0'}}, }, bmo_similar_faces_exec, 0 }; /* - * Similar edges search + * Similar Edges Search. * * Find similar edges (length, direction, edge, seam, ...). */ static BMOpDefine bmo_similar_edges_def = { "similar_edges", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_INT, "type"}, /* type of selection */ - {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ - {BMO_OP_SLOT_INT, "compare"}, /* comparison method */ - {0}, + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {"type", BMO_OP_SLOT_INT}, /* type of selection */ + {"thresh", BMO_OP_SLOT_FLT}, /* threshold of selection */ + {"compare", BMO_OP_SLOT_INT}, /* comparison method */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* output edges */ - {0}, + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output edges */ + {{'\0'}}, }, bmo_similar_edges_exec, 0 }; /* - * Similar vertices search + * Similar Verts Search. * * Find similar vertices (normal, face, vertex group, ...). */ static BMOpDefine bmo_similar_verts_def = { "similar_verts", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_INT, "type"}, /* type of selection */ - {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ - {BMO_OP_SLOT_INT, "compare"}, /* comparison method */ - {0}, + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"type", BMO_OP_SLOT_INT}, /* type of selection */ + {"thresh", BMO_OP_SLOT_FLT}, /* threshold of selection */ + {"compare", BMO_OP_SLOT_INT}, /* comparison method */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output vertices */ - {0}, + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output vertices */ + {{'\0'}}, }, bmo_similar_verts_exec, 0 }; /* - * uv rotation - * cycle the uvs + * UV Rotation. + * + * Cycle the loop UV's */ static BMOpDefine bmo_rotate_uvs_def = { "rotate_uvs", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_BOOL, "use_ccw"}, /* rotate counter-clockwise if true, othewise clockwise */ - {0}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"use_ccw", BMO_OP_SLOT_BOOL}, /* rotate counter-clockwise if true, otherwise clockwise */ + {{'\0'}}, }, /* slots_out */ - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_rotate_uvs_exec, 0 }; /* - * uv reverse - * reverse the uvs + * UV Reverse. + * + * Reverse the UV's */ static BMOpDefine bmo_reverse_uvs_def = { "reverse_uvs", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {0}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_reverse_uvs_exec, 0 }; /* - * color rotation - * cycle the colors + * Color Rotation. + * + * Cycle the loop colors */ static BMOpDefine bmo_rotate_colors_def = { "rotate_colors", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_BOOL, "use_ccw"}, /* rotate counter-clockwise if true, othewise clockwise */ - {0}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"use_ccw", BMO_OP_SLOT_BOOL}, /* rotate counter-clockwise if true, otherwise clockwise */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_rotate_colors_exec, 0 }; /* - * color reverse - * reverse the colors + * Color Reverse + * + * Reverse the loop colors. */ static BMOpDefine bmo_reverse_colors_def = { "reverse_colors", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {0}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {{'\0'}}, }, - {{0}}, /* no output */ + {{{'\0'}}}, /* no output */ bmo_reverse_colors_exec, 0 }; /* - * Similar vertices search + * Shortest Path. * - * Find similar vertices (normal, face, vertex group, ...). + * Select the shortest path between 2 verts. */ static BMOpDefine bmo_shortest_path_def = { "shortest_path", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "startv"}, /* start vertex */ - {BMO_OP_SLOT_ELEMENT_BUF, "endv"}, /* end vertex */ - {BMO_OP_SLOT_INT, "type"}, /* type of selection */ - {0}, + {{"vert_start", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE}}, /* start vertex */ + {"vert_end", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE}}, /* end vertex */ + {"type", BMO_OP_SLOT_INT}, /* type of selection */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output vertices */ - {0}, + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output vertices */ + {{'\0'}}, }, bmo_shortest_path_exec, 0 }; /* - * Edge Split + * Edge Split. * * Disconnects faces along input edges. */ static BMOpDefine bmo_split_edges_def = { "split_edges", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ /* needed for vertex rip so we can rip only half an edge at a boundary wich would otherwise split off */ - {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* optional tag verts, use to have greater control of splits */ - {BMO_OP_SLOT_BOOL, "use_verts"}, /* use 'verts' for splitting, else just find verts to split from edges */ - {0}, + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* optional tag verts, use to have greater control of splits */ + {"use_verts", BMO_OP_SLOT_BOOL}, /* use 'verts' for splitting, else just find verts to split from edges */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* old output disconnected edges */ - {0}, + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* old output disconnected edges */ + {{'\0'}}, }, bmo_split_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; /* - * Create Grid + * Create Grid. * * Creates a grid with a variable number of subdivisions */ static BMOpDefine bmo_create_grid_def = { "create_grid", /* slots_in */ - {{BMO_OP_SLOT_INT, "x_segments"}, /* number of x segments */ - {BMO_OP_SLOT_INT, "y_segments"}, /* number of y segments */ - {BMO_OP_SLOT_FLT, "size"}, /* size of the grid */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ - {0}, + {{"x_segments", BMO_OP_SLOT_INT}, /* number of x segments */ + {"y_segments", BMO_OP_SLOT_INT}, /* number of y segments */ + {"size", BMO_OP_SLOT_FLT}, /* size of the grid */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ - {0}, + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, }, bmo_create_grid_exec, 0, }; /* - * Create UV Sphere + * Create UV Sphere. * * Creates a grid with a variable number of subdivisions */ static BMOpDefine bmo_create_uvsphere_def = { "create_uvsphere", /* slots_in */ - {{BMO_OP_SLOT_INT, "u_segments"}, /* number of u segments */ - {BMO_OP_SLOT_INT, "v_segments"}, /* number of v segment */ - {BMO_OP_SLOT_FLT, "diameter"}, /* diameter */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ - {0}, + {{"u_segments", BMO_OP_SLOT_INT}, /* number of u segments */ + {"v_segments", BMO_OP_SLOT_INT}, /* number of v segment */ + {"diameter", BMO_OP_SLOT_FLT}, /* diameter */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ - {0}, + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, }, bmo_create_uvsphere_exec, 0, }; /* - * Create Ico Sphere + * Create Ico-Sphere. * * Creates a grid with a variable number of subdivisions */ static BMOpDefine bmo_create_icosphere_def = { "create_icosphere", /* slots_in */ - {{BMO_OP_SLOT_INT, "subdivisions"}, /* how many times to recursively subdivide the sphere */ - {BMO_OP_SLOT_FLT, "diameter"}, /* diameter */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ - {0}, + {{"subdivisions", BMO_OP_SLOT_INT}, /* how many times to recursively subdivide the sphere */ + {"diameter", BMO_OP_SLOT_FLT}, /* diameter */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ - {0}, + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, }, bmo_create_icosphere_exec, 0, }; /* - * Create Suzanne + * Create Suzanne. * - * Creates a monkey. Be wary. + * Creates a monkey (standard blender primitive). */ static BMOpDefine bmo_create_monkey_def = { "create_monkey", /* slots_in */ - {{BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ - {0}, + {{"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ - {0}, + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, }, bmo_create_monkey_exec, 0, }; /* - * Create Cone + * Create Cone. * * Creates a cone with variable depth at both ends */ static BMOpDefine bmo_create_cone_def = { "create_cone", /* slots_in */ - {{BMO_OP_SLOT_BOOL, "cap_ends"}, /* wheter or not to fill in the ends with faces */ - {BMO_OP_SLOT_BOOL, "cap_tris"}, /* fill ends with triangles instead of ngons */ - {BMO_OP_SLOT_INT, "segments"}, - {BMO_OP_SLOT_FLT, "diameter1"}, /* diameter of one end */ - {BMO_OP_SLOT_FLT, "diameter2"}, /* diameter of the opposite */ - {BMO_OP_SLOT_FLT, "depth"}, /* distance between ends */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ - {0}, + {{"cap_ends", BMO_OP_SLOT_BOOL}, /* whether or not to fill in the ends with faces */ + {"cap_tris", BMO_OP_SLOT_BOOL}, /* fill ends with triangles instead of ngons */ + {"segments", BMO_OP_SLOT_INT}, + {"diameter1", BMO_OP_SLOT_FLT}, /* diameter of one end */ + {"diameter2", BMO_OP_SLOT_FLT}, /* diameter of the opposite */ + {"depth", BMO_OP_SLOT_FLT}, /* distance between ends */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ - {0}, + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, }, bmo_create_cone_exec, 0, }; /* - * Creates a circle + * Creates a Circle. */ static BMOpDefine bmo_create_circle_def = { "create_circle", /* slots_in */ - {{BMO_OP_SLOT_BOOL, "cap_ends"}, /* wheter or not to fill in the ends with faces */ - {BMO_OP_SLOT_BOOL, "cap_tris"}, /* fill ends with triangles instead of ngons */ - {BMO_OP_SLOT_INT, "segments"}, - {BMO_OP_SLOT_FLT, "diameter"}, /* diameter of one end */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ - {0}, + {{"cap_ends", BMO_OP_SLOT_BOOL}, /* whether or not to fill in the ends with faces */ + {"cap_tris", BMO_OP_SLOT_BOOL}, /* fill ends with triangles instead of ngons */ + {"segments", BMO_OP_SLOT_INT}, + {"diameter", BMO_OP_SLOT_FLT}, /* diameter of one end */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ - {0}, + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, }, bmo_create_circle_exec, 0, }; /* - * Create Cone + * Create Cube * - * Creates a cone with variable depth at both ends + * Creates a cube. */ static BMOpDefine bmo_create_cube_def = { "create_cube", /* slots_in */ - {{BMO_OP_SLOT_FLT, "size"}, /* size of the cube */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ - {0}, + {{"size", BMO_OP_SLOT_FLT}, /* size of the cube */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ - {0}, + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, }, bmo_create_cube_exec, 0, }; /* - * Bevel + * Bevel. * * Bevels edges and vertices */ static BMOpDefine bmo_bevel_def = { "bevel", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input edges and vertices */ - {BMO_OP_SLOT_FLT, "offset"}, /* amount to offset beveled edge */ - {BMO_OP_SLOT_INT, "segments"}, /* number of segments in bevel */ - {0}, + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input edges and vertices */ + {"offset", BMO_OP_SLOT_FLT}, /* amount to offset beveled edge */ + {"segments", BMO_OP_SLOT_INT}, /* number of segments in bevel */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* output faces */ - {0}, - }, -#if 0 /* old bevel*/ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input edges and vertices */ - {BMO_OP_SLOT_ELEMENT_BUF, "face_spans"}, /* new geometry */ - {BMO_OP_SLOT_ELEMENT_BUF, "face_holes"}, /* new geometry */ - {BMO_OP_SLOT_BOOL, "use_lengths"}, /* grab edge lengths from a PROP_FLT customdata layer */ - {BMO_OP_SLOT_BOOL, "use_even"}, /* corner vert placement: use shell/angle calculations */ - {BMO_OP_SLOT_BOOL, "use_dist"}, /* corner vert placement: evaluate percent as a distance, - * modifier uses this. We could do this as another float setting */ - {BMO_OP_SLOT_INT, "lengthlayer"}, /* which PROP_FLT layer to us */ - {BMO_OP_SLOT_FLT, "percent"}, /* percentage to expand beveled edge */ - {0}, - }, -#endif + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ + {{'\0'}}, + }, +/* old bevel*/ +// {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input edges and vertices */ +// {"face_spans", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new geometry */ +// {"face_holes", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new geometry */ +// {"use_lengths", BMO_OP_SLOT_BOOL}, /* grab edge lengths from a PROP_FLT customdata layer */ +// {"use_even", BMO_OP_SLOT_BOOL}, /* corner vert placement: use shell/angle calculations */ +// {"use_dist", BMO_OP_SLOT_BOOL}, /* corner vert placement: evaluate percent as a distance, +// * modifier uses this. We could do this as another float setting */ +// {"lengthlayer", BMO_OP_SLOT_INT}, /* which PROP_FLT layer to us */ +// {"percent", BMO_OP_SLOT_FLT}, /* percentage to expand beveled edge */ +// {{'\0'}}, +// }, + bmo_bevel_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; /* - * Beautify Fill + * Beautify Fill. * - * Makes triangle a bit nicer + * Rotate edges to create more evenly spaced triangles. */ static BMOpDefine bmo_beautify_fill_def = { "beautify_fill", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "constrain_edges"}, /* edges that can't be flipped */ - {0}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"constrain_edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* edges that can't be flipped */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* new flipped faces and edges */ - {0}, + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* new flipped faces and edges */ + {{'\0'}}, }, bmo_beautify_fill_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; /* - * Triangle Fill + * Triangle Fill. * * Fill edges with triangles */ static BMOpDefine bmo_triangle_fill_def = { "triangle_fill", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {0}, + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* new faces and edges */ - {0}, + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* new faces and edges */ + {{'\0'}}, }, bmo_triangle_fill_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; /* - * Solidify + * Solidify. * * Turns a mesh into a shell with thickness */ static BMOpDefine bmo_solidify_def = { "solidify", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_FLT, "thickness"}, - {0}, + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"thickness", BMO_OP_SLOT_FLT}, + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, - {0}, + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {{'\0'}}, }, bmo_solidify_face_region_exec, 0 }; /* - * Face Inset + * Face Inset. * - * Extrudes faces individually. + * Inset or outset faces. */ static BMOpDefine bmo_inset_def = { "inset", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_BOOL, "use_boundary"}, - {BMO_OP_SLOT_BOOL, "use_even_offset"}, - {BMO_OP_SLOT_BOOL, "use_relative_offset"}, - {BMO_OP_SLOT_FLT, "thickness"}, - {BMO_OP_SLOT_FLT, "depth"}, - {BMO_OP_SLOT_BOOL, "use_outset"}, - {0}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"use_boundary", BMO_OP_SLOT_BOOL}, + {"use_even_offset", BMO_OP_SLOT_BOOL}, + {"use_relative_offset", BMO_OP_SLOT_BOOL}, + {"thickness", BMO_OP_SLOT_FLT}, + {"depth", BMO_OP_SLOT_FLT}, + {"use_outset", BMO_OP_SLOT_BOOL}, + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* output faces */ - {0}, + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ + {{'\0'}}, }, bmo_inset_exec, 0 }; /* - * Wire Frame + * Wire Frame. * - * Makes a wire copy of faces. + * Makes a wire-frame copy of faces. */ static BMOpDefine bmo_wireframe_def = { "wireframe", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_BOOL, "use_boundary"}, - {BMO_OP_SLOT_BOOL, "use_even_offset"}, - {BMO_OP_SLOT_BOOL, "use_crease"}, - {BMO_OP_SLOT_FLT, "thickness"}, - {BMO_OP_SLOT_BOOL, "use_relative_offset"}, - {BMO_OP_SLOT_FLT, "depth"}, - {0}, + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"use_boundary", BMO_OP_SLOT_BOOL}, + {"use_even_offset", BMO_OP_SLOT_BOOL}, + {"use_crease", BMO_OP_SLOT_BOOL}, + {"thickness", BMO_OP_SLOT_FLT}, + {"use_relative_offset", BMO_OP_SLOT_BOOL}, + {"depth", BMO_OP_SLOT_FLT}, + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* output faces */ - {0}, + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ + {{'\0'}}, }, bmo_wireframe_exec, 0 }; /* - * Vertex Slide + * Vertex Slide. * - * Translates vertes along an edge + * Translates verts along an edge */ static BMOpDefine bmo_slide_vert_def = { "slide_vert", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "vert"}, - {BMO_OP_SLOT_ELEMENT_BUF, "edge"}, - {BMO_OP_SLOT_FLT, "distance_t"}, - {0}, + {{"vert", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE}}, + {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {"factor", BMO_OP_SLOT_FLT}, + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, - {0}, + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, + {{'\0'}}, }, bmo_slide_vert_exec, BMO_OP_FLAG_UNTAN_MULTIRES @@ -1499,16 +1575,16 @@ static BMOpDefine bmo_slide_vert_def = { static BMOpDefine bmo_convex_hull_def = { "convex_hull", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "input"}, - {BMO_OP_SLOT_BOOL, "use_existing_faces"}, - {0}, + {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"use_existing_faces", BMO_OP_SLOT_BOOL}, + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geom_interior.out"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geom_unused.out"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geom_holes.out"}, - {0}, + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"geom_interior.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"geom_unused.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"geom_holes.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {{'\0'}}, }, bmo_convex_hull_exec, 0 @@ -1516,9 +1592,9 @@ static BMOpDefine bmo_convex_hull_def = { #endif /* - * Symmetrize + * Symmetrize. * - * Mekes the mesh elements in the "input" slot symmetrical. Unlike + * Makes the mesh elements in the "input" slot symmetrical. Unlike * normal mirroring, it only copies in one direction, as specified by * the "direction" slot. The edges and faces that cross the plane of * symmetry are split as needed to enforce symmetry. @@ -1528,19 +1604,19 @@ static BMOpDefine bmo_convex_hull_def = { static BMOpDefine bmo_symmetrize_def = { "symmetrize", /* slots_in */ - {{BMO_OP_SLOT_ELEMENT_BUF, "input"}, - {BMO_OP_SLOT_INT, "direction"}, - {0}, + {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"direction", BMO_OP_SLOT_INT}, + {{'\0'}}, }, /* slots_out */ - {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, - {0}, + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {{'\0'}}, }, bmo_symmetrize_exec, 0 }; -BMOpDefine *opdefines[] = { +const BMOpDefine *bmo_opdefines[] = { &bmo_automerge_def, &bmo_average_vert_facedata_def, &bmo_beautify_fill_def, @@ -1615,7 +1691,6 @@ BMOpDefine *opdefines[] = { &bmo_unsubdivide_def, &bmo_weld_verts_def, &bmo_wireframe_def, - }; -int bmesh_total_ops = (sizeof(opdefines) / sizeof(void *)); +const int bmo_opdefines_total = (sizeof(bmo_opdefines) / sizeof(void *)); diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index b87e023e63a..7df9c94a2f1 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -91,15 +91,15 @@ BLI_INLINE void _bmo_elem_flag_toggle( BMesh *bm, BMFlagLayer *oflags, const /* slot type arrays are terminated by the last member * having a slot type of 0 */ -enum { - BMO_OP_SLOT_SENTINEL = 0, +typedef enum eBMOpSlotType { + /* BMO_OP_SLOT_SENTINEL = 0, */ BMO_OP_SLOT_BOOL = 1, BMO_OP_SLOT_INT = 2, BMO_OP_SLOT_FLT = 3, /* normally store pointers to object, scene, * _never_ store arrays corresponding to mesh elements with this */ - BMO_OP_SLOT_PTR = 4, + BMO_OP_SLOT_PTR = 4, /* requres subtype BMO_OP_SLOT_SUBTYPE_PTR_xxx */ BMO_OP_SLOT_MAT = 5, BMO_OP_SLOT_VEC = 8, @@ -108,16 +108,47 @@ enum { * * it's very important this remain a power of two */ BMO_OP_SLOT_ELEMENT_BUF = 9, /* list of verts/edges/faces */ - BMO_OP_SLOT_MAPPING = 10 /* simple hash map */ -}; + BMO_OP_SLOT_MAPPING = 10 /* simple hash map, requres subtype BMO_OP_SLOT_SUBTYPE_MAP_xxx */ +} eBMOpSlotType; #define BMO_OP_SLOT_TOTAL_TYPES 11 +/* don't overlap values to avoid confusion */ +typedef enum eBMOpSlotSubType_Elem { + /* use as flags */ + BMO_OP_SLOT_SUBTYPE_ELEM_VERT = BM_VERT, + BMO_OP_SLOT_SUBTYPE_ELEM_EDGE = BM_EDGE, + BMO_OP_SLOT_SUBTYPE_ELEM_FACE = BM_FACE, + BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE = (BM_FACE << 1), +} eBMOpSlotSubType_Elem; +typedef enum eBMOpSlotSubType_Map { + BMO_OP_SLOT_SUBTYPE_MAP_EMPTY = 64, /* use as a set(), unused value */ + BMO_OP_SLOT_SUBTYPE_MAP_ELEM = 65, + BMO_OP_SLOT_SUBTYPE_MAP_FLT = 66, + BMO_OP_SLOT_SUBTYPE_MAP_INT = 67, + BMO_OP_SLOT_SUBTYPE_MAP_BOOL = 68, + BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL = 69, /* python can't convert these */ +} eBMOpSlotSubType_Map; +typedef enum eBMOpSlotSubType_Ptr { + BMO_OP_SLOT_SUBTYPE_PTR_BMESH = 100, + BMO_OP_SLOT_SUBTYPE_PTR_SCENE = 101, + BMO_OP_SLOT_SUBTYPE_PTR_OBJECT = 102, + BMO_OP_SLOT_SUBTYPE_PTR_MESH = 103, +} eBMOpSlotSubType_Ptr; + +typedef union eBMOpSlotSubType_Union { + eBMOpSlotSubType_Elem elem; + eBMOpSlotSubType_Ptr ptr; + eBMOpSlotSubType_Map map; +} eBMOpSlotSubType_Union; + /* please ignore all these structures, don't touch them in tool code, except * for when your defining an operator with BMOpDefine.*/ typedef struct BMOpSlot { const char *slot_name; /* pointer to BMOpDefine.slot_args */ - int slot_type; + eBMOpSlotType slot_type; + eBMOpSlotSubType_Union slot_subtype; + int len; // int flag; /* UNUSED */ // int index; /* index within slot array */ /* UNUSED */ @@ -166,8 +197,9 @@ enum { #define MAX_SLOTNAME 32 typedef struct BMOSlotType { - int type; char name[MAX_SLOTNAME]; + eBMOpSlotType type; + eBMOpSlotSubType_Union subtype; } BMOSlotType; typedef struct BMOpDefine { @@ -208,43 +240,6 @@ int BMO_mesh_enabled_flag_count(BMesh *bm, const char htype, const short oflag); int BMO_mesh_disabled_flag_count(BMesh *bm, const char htype, const short oflag); /*---------formatted operator initialization/execution-----------*/ -/* - * this system is used to execute or initialize an operator, - * using a formatted-string system. - * - * for example, BMO_op_callf(bm, BMO_FLAG_DEFAULTS, "delete geom=%hf context=%i", BM_ELEM_SELECT, DEL_FACES); - * . . .will execute the delete operator, feeding in selected faces, deleting them. - * - * the basic format for the format string is: - * [operatorname] [slot_name]=%[code] [slot_name]=%[code] - * - * as in printf, you pass in one additional argument to the function - * for every code. - * - * the formatting codes are: - * %d - put int in slot - * %f - put float in slot - * %p - put pointer in slot - * %h[f/e/v] - put elements with a header flag in slot. - * the letters after %h define which element types to use, - * so e.g. %hf will do faces, %hfe will do faces and edges, - * %hv will do verts, etc. must pass in at least one - * element type letter. - * %H[f/e/v] - same as %h, but tests if the flag is disabled - * %f[f/e/v] - same as %h, except it deals with tool flags instead of - * header flags. - * %F[f/e/v] - same as %f, but tests if the flag is disabled - * %a[f/e/v] - pass all elements (of types specified by f/e/v) to the - * slot. - * %e - pass in a single element. - * %v - pointer to a float vector of length 3. - * %m[3/4] - matrix, 3/4 refers to the matrix size, 3 or 4. the - * corresponding argument must be a pointer to - * a float matrix. - * %s - copy a slot from another op, instead of mapping to one - * argument, it maps to two, a pointer to an operator and - * a slot name. - */ void BMO_push(BMesh *bm, BMOperator *op); void BMO_pop(BMesh *bm); @@ -385,12 +380,16 @@ void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag); +void BMO_slot_buffer_from_single(BMOperator *op, BMOpSlot *slot, BMHeader *ele); +void *BMO_slot_buffer_get_single(BMOpSlot *slot); + + /* counts number of elements inside a slot array. */ int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, - const void *element, void *data, int len); + const void *element, const void *data, const int len); /* Counts the number of edges with tool flag toolflag around */ @@ -407,15 +406,18 @@ void *BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS] void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype); -/* this part of the API is used to iterate over element buffer or +/** + * This part of the API is used to iterate over element buffer or * mapping slots. * * for example, iterating over the faces in a slot is: * + * \code{.c} + * * BMOIter oiter; * BMFace *f; * - * f = BMO_iter_new(&oiter, bm, some_operator, "slot_name", BM_FACE); + * f = BMO_iter_new(&oiter, some_operator, "slot_name", BM_FACE); * for (; f; f = BMO_iter_step(&oiter)) { * /do something with the face * } @@ -436,6 +438,7 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_ * // *((void**)BMO_iter_map_value(&oiter)); * //or something like that. * } + * \endcode */ /* contents of this structure are private, @@ -478,6 +481,9 @@ typedef struct BMOElemMapping { int len; } BMOElemMapping; +/* pointer after BMOElemMapping */ +#define BMO_OP_SLOT_MAPPING_DATA(var) (void *)(((BMOElemMapping *)var) + 1) + extern const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES]; #ifdef __cplusplus diff --git a/source/blender/bmesh/intern/bmesh_operator_api_inline.h b/source/blender/bmesh/intern/bmesh_operator_api_inline.h index b405ecc1841..ad116011421 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api_inline.h +++ b/source/blender/bmesh/intern/bmesh_operator_api_inline.h @@ -70,14 +70,24 @@ BLI_INLINE void _bmo_elem_flag_toggle(BMesh *bm, BMFlagLayer *oflags, const shor } BLI_INLINE void BMO_slot_map_int_insert(BMOperator *op, BMOpSlot *slot, - void *element, int val) + void *element, const int val) { + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT); + BMO_slot_map_insert(op, slot, element, &val, sizeof(int)); +} + +BLI_INLINE void BMO_slot_map_bool_insert(BMOperator *op, BMOpSlot *slot, + void *element, const int val) +{ + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL); + BLI_assert(val == FALSE || val == TRUE); BMO_slot_map_insert(op, slot, element, &val, sizeof(int)); } BLI_INLINE void BMO_slot_map_float_insert(BMOperator *op, BMOpSlot *slot, - void *element, float val) + void *element, const float val) { + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT); BMO_slot_map_insert(op, slot, element, &val, sizeof(float)); } @@ -90,9 +100,26 @@ BLI_INLINE void BMO_slot_map_float_insert(BMOperator *op, BMOpSlot *slot, BLI_INLINE void BMO_slot_map_ptr_insert(BMOperator *op, BMOpSlot *slot, const void *element, void *val) { + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL); BMO_slot_map_insert(op, slot, element, &val, sizeof(void *)); } +BLI_INLINE void BMO_slot_map_elem_insert(BMOperator *op, BMOpSlot *slot, + const void *element, void *val) +{ + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_ELEM); + BMO_slot_map_insert(op, slot, element, &val, sizeof(void *)); +} + + +/* no values */ +BLI_INLINE void BMO_slot_map_empty_insert(BMOperator *op, BMOpSlot *slot, + const void *element) +{ + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_EMPTY); + BMO_slot_map_insert(op, slot, element, NULL, 0); +} + BLI_INLINE int BMO_slot_map_contains(BMOpSlot *slot, const void *element) { BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); @@ -126,7 +153,10 @@ BLI_INLINE void *BMO_slot_map_data_get(BMOpSlot *slot, const void *element) BLI_INLINE float BMO_slot_map_float_get(BMOpSlot *slot, const void *element) { - float *val = (float *) BMO_slot_map_data_get(slot, element); + float *val; + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT); + + val = (float *) BMO_slot_map_data_get(slot, element); if (val) return *val; return 0.0f; @@ -134,7 +164,22 @@ BLI_INLINE float BMO_slot_map_float_get(BMOpSlot *slot, const void *element) BLI_INLINE int BMO_slot_map_int_get(BMOpSlot *slot, const void *element) { - int *val = (int *) BMO_slot_map_data_get(slot, element); + int *val; + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT); + + val = (int *) BMO_slot_map_data_get(slot, element); + if (val) return *val; + + return 0; +} + +BLI_INLINE int BMO_slot_map_bool_get(BMOpSlot *slot, const void *element) +{ + int *val; + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL); + + val = (int *) BMO_slot_map_data_get(slot, element); + BLI_assert(val == NULL || *val == FALSE || *val == TRUE); if (val) return *val; return 0; @@ -143,6 +188,16 @@ BLI_INLINE int BMO_slot_map_int_get(BMOpSlot *slot, const void *element) BLI_INLINE void *BMO_slot_map_ptr_get(BMOpSlot *slot, const void *element) { void **val = (void **) BMO_slot_map_data_get(slot, element); + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL); + if (val) return *val; + + return NULL; +} + +BLI_INLINE void *BMO_slot_map_elem_get(BMOpSlot *slot, const void *element) +{ + void **val = (void **) BMO_slot_map_data_get(slot, element); + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_ELEM); if (val) return *val; return NULL; diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index 157837a13c0..ba38f230f0b 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -127,12 +127,13 @@ void BMO_pop(BMesh *bm) /* use for both slot_types_in and slot_types_out */ -static void bmo_op_slots_init(BMOSlotType *slot_types, BMOpSlot *slot_args) +static void bmo_op_slots_init(const BMOSlotType *slot_types, BMOpSlot *slot_args) { unsigned int i; for (i = 0; slot_types[i].type; i++) { - slot_args[i].slot_name = slot_types[i].name; - slot_args[i].slot_type = slot_types[i].type; + slot_args[i].slot_name = slot_types[i].name; + slot_args[i].slot_type = slot_types[i].type; + slot_args[i].slot_subtype = slot_types[i].subtype; // slot_args[i].index = i; // UNUSED } } @@ -158,15 +159,15 @@ void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname) memset(op, 0, sizeof(BMOperator)); op->type = opcode; - op->type_flag = opdefines[opcode]->type_flag; + op->type_flag = bmo_opdefines[opcode]->type_flag; op->flag = flag; /* initialize the operator slot types */ - bmo_op_slots_init(opdefines[opcode]->slot_types_in, op->slots_in); - bmo_op_slots_init(opdefines[opcode]->slot_types_out, op->slots_out); + bmo_op_slots_init(bmo_opdefines[opcode]->slot_types_in, op->slots_in); + bmo_op_slots_init(bmo_opdefines[opcode]->slot_types_out, op->slots_out); /* callback */ - op->exec = opdefines[opcode]->exec; + op->exec = bmo_opdefines[opcode]->exec; /* memarena, used for operator's slot buffers */ op->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); @@ -199,7 +200,7 @@ void BMO_op_exec(BMesh *bm, BMOperator *op) BMO_pop(bm); } -static void bmo_op_slots_free(BMOSlotType *slot_types, BMOpSlot *slot_args) +static void bmo_op_slots_free(const BMOSlotType *slot_types, BMOpSlot *slot_args) { BMOpSlot *slot; unsigned int i; @@ -220,13 +221,13 @@ static void bmo_op_slots_free(BMOSlotType *slot_types, BMOpSlot *slot_args) */ void BMO_op_finish(BMesh *bm, BMOperator *op) { - bmo_op_slots_free(opdefines[op->type]->slot_types_in, op->slots_in); - bmo_op_slots_free(opdefines[op->type]->slot_types_out, op->slots_out); + bmo_op_slots_free(bmo_opdefines[op->type]->slot_types_in, op->slots_in); + bmo_op_slots_free(bmo_opdefines[op->type]->slot_types_out, op->slots_out); BLI_memarena_free(op->arena); #ifdef DEBUG - BM_ELEM_INDEX_VALIDATE(bm, "post bmo", opdefines[op->type]->opname); + BM_ELEM_INDEX_VALIDATE(bm, "post bmo", bmo_opdefines[op->type]->opname); #else (void)bm; #endif @@ -287,9 +288,49 @@ void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_n slot_dst->data.buf = NULL; slot_dst->len = slot_src->len; if (slot_dst->len) { - const int slot_alloc_size = BMO_OPSLOT_TYPEINFO[slot_dst->slot_type] * slot_dst->len; - slot_dst->data.buf = BLI_memarena_alloc(arena_dst, slot_alloc_size); - memcpy(slot_dst->data.buf, slot_src->data.buf, slot_alloc_size); + /* check dest has all flags enabled that the source has */ + const eBMOpSlotSubType_Elem src_elem_flag = (slot_src->slot_subtype.elem & BM_ALL_NOLOOP); + const eBMOpSlotSubType_Elem dst_elem_flag = (slot_dst->slot_subtype.elem & BM_ALL_NOLOOP); + + if ((src_elem_flag | dst_elem_flag) == dst_elem_flag) { + /* pass */ + } + else { + /* check types */ + const unsigned int tot = slot_src->len; + unsigned int i; + unsigned int out = 0; + BMElem **ele_src = (BMElem **)slot_src->data.buf; + for (i = 0; i < tot; i++, ele_src++) { + if ((*ele_src)->head.htype & dst_elem_flag) { + out++; + } + } + if (out != tot) { + slot_dst->len = out; + } + } + + if (slot_dst->len) { + const int slot_alloc_size = BMO_OPSLOT_TYPEINFO[slot_dst->slot_type] * slot_dst->len; + slot_dst->data.buf = BLI_memarena_alloc(arena_dst, slot_alloc_size); + if (slot_src->len == slot_dst->len) { + memcpy(slot_dst->data.buf, slot_src->data.buf, slot_alloc_size); + } + else { + /* only copy compatible elements */ + const unsigned int tot = slot_src->len; + unsigned int i; + BMElem **ele_src = (BMElem **)slot_src->data.buf; + BMElem **ele_dst = (BMElem **)slot_dst->data.buf; + for (i = 0; i < tot; i++, ele_src++) { + if ((*ele_src)->head.htype & dst_elem_flag) { + *ele_dst = *ele_src; + ele_dst++; + } + } + } + } } } else if (slot_dst->slot_type == BMO_OP_SLOT_MAPPING) { @@ -313,7 +354,7 @@ void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_n dstmap->element = srcmap->element; dstmap->len = srcmap->len; - memcpy(dstmap + 1, srcmap + 1, srcmap->len); + memcpy(BMO_OP_SLOT_MAPPING_DATA(dstmap), BMO_OP_SLOT_MAPPING_DATA(srcmap), srcmap->len); BLI_ghash_insert(slot_dst->data.ghash, dstmap->element, dstmap); } @@ -595,7 +636,7 @@ int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_na * value, it doesn't store a reference to it. */ void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, - const void *element, void *data, int len) + const void *element, const void *data, const int len) { BMOElemMapping *mapping; BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); @@ -605,11 +646,14 @@ void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, mapping->element = (BMHeader *) element; mapping->len = len; - memcpy(mapping + 1, data, len); + memcpy(BMO_OP_SLOT_MAPPING_DATA(mapping), data, len); if (!slot->data.ghash) { slot->data.ghash = BLI_ghash_ptr_new("bmesh slot map hash"); } + else { + BLI_assert(slot->data.ghash); + } BLI_ghash_insert(slot->data.ghash, (void *)element, mapping); } @@ -631,7 +675,7 @@ void *bmo_slot_buffer_grow(BMesh *bm, BMOperator *op, int slot_code, int totadd) if (slot->len >= slot->size) { slot->size = (slot->size + 1 + totadd) * 2; - allocsize = BMO_OPSLOT_TYPEINFO[opdefines[op->type]->slot_types[slot_code].type] * slot->size; + allocsize = BMO_OPSLOT_TYPEINFO[bmo_opdefines[op->type]->slot_types[slot_code].type] * slot->size; tmp = slot->data.buf; slot->data.buf = MEM_callocN(allocsize, "opslot dynamic array"); @@ -646,7 +690,7 @@ void *bmo_slot_buffer_grow(BMesh *bm, BMOperator *op, int slot_code, int totadd) slot->len += totadd; slot->size = slot->len + 2; - allocsize = BMO_OPSLOT_TYPEINFO[opdefines[op->type]->slot_types[slot_code].type] * slot->len; + allocsize = BMO_OPSLOT_TYPEINFO[bmo_opdefines[op->type]->slot_types[slot_code].type] * slot->len; tmp = slot->data.buf; slot->data.buf = MEM_callocN(allocsize, "opslot dynamic array"); @@ -823,6 +867,29 @@ void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op, bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, FALSE); } +void BMO_slot_buffer_from_single(BMOperator *op, BMOpSlot *slot, BMHeader *ele) +{ + BMO_ASSERT_SLOT_IN_OP(slot, op); + BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE); + BLI_assert(slot->len == 0 || slot->len == 1); + + BLI_assert(slot->slot_subtype.elem & ele->htype); + + slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(void *) * 4); /* XXX, why 'x4' ? */ + slot->len = 1; + *slot->data.buf = ele; +} + +void *BMO_slot_buffer_get_single(BMOpSlot *slot) +{ + BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE); + BLI_assert(slot->len == 0 || slot->len == 1); + + return slot->len ? (BMHeader *)slot->data.buf[0] : NULL; +} + /** * Copies the values from another slot to the end of the output slot. */ @@ -880,6 +947,7 @@ static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, totelement = BMO_mesh_disabled_flag_count(bm, htype, oflag); BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); if (totelement) { BMIter iter; @@ -955,6 +1023,7 @@ void BMO_slot_buffer_hflag_enable(BMesh *bm, const char do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN)); BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); for (i = 0; i < slot->len; i++, data++) { if (!(htype & (*data)->head.htype)) @@ -989,6 +1058,7 @@ void BMO_slot_buffer_hflag_disable(BMesh *bm, const char do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN)); BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); for (i = 0; i < slot->len; i++, data++) { if (!(htype & (*data)->head.htype)) @@ -1039,6 +1109,7 @@ void BMO_slot_buffer_flag_enable(BMesh *bm, int i; BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); for (i = 0; i < slot->len; i++) { if (!(htype & data[i]->htype)) @@ -1062,6 +1133,7 @@ void BMO_slot_buffer_flag_disable(BMesh *bm, int i; BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); for (i = 0; i < slot->len; i++) { if (!(htype & data[i]->htype)) @@ -1252,35 +1324,42 @@ void *BMO_iter_new(BMOIter *iter, void *BMO_iter_step(BMOIter *iter) { - if (iter->slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) { - BMHeader *h; + BMOpSlot *slot = iter->slot; + if (slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) { + BMHeader *ele; - if (iter->cur >= iter->slot->len) { + if (iter->cur >= slot->len) { return NULL; } - h = iter->slot->data.buf[iter->cur++]; - while (!(iter->restrictmask & h->htype)) { - if (iter->cur >= iter->slot->len) { + ele = slot->data.buf[iter->cur++]; + while (!(iter->restrictmask & ele->htype)) { + if (iter->cur >= slot->len) { return NULL; } - h = iter->slot->data.buf[iter->cur++]; + ele = slot->data.buf[iter->cur++]; + BLI_assert((ele == NULL) || (slot->slot_subtype.elem & ele->htype)); } - return h; + BLI_assert((ele == NULL) || (slot->slot_subtype.elem & ele->htype)); + + return ele; } - else if (iter->slot->slot_type == BMO_OP_SLOT_MAPPING) { + else if (slot->slot_type == BMO_OP_SLOT_MAPPING) { BMOElemMapping *map; void *ret = BLI_ghashIterator_getKey(&iter->giter); map = BLI_ghashIterator_getValue(&iter->giter); - iter->val = map + 1; + iter->val = BMO_OP_SLOT_MAPPING_DATA(map); BLI_ghashIterator_step(&iter->giter); return ret; } + else { + BLI_assert(0); + } return NULL; } @@ -1393,8 +1472,8 @@ static int bmo_opname_to_opcode(const char *opname) { int i; - for (i = 0; i < bmesh_total_ops; i++) { - if (!strcmp(opname, opdefines[i]->opname)) { + for (i = 0; i < bmo_opdefines_total; i++) { + if (!strcmp(opname, bmo_opdefines[i]->opname)) { return i; } } @@ -1403,23 +1482,63 @@ static int bmo_opname_to_opcode(const char *opname) return -1; } -/* Example: - * BMO_op_callf(bm, BMO_FLAG_DEFAULTS, "delete %i %hv", DEL_ONLYFACES, BM_ELEM_SELECT); +/** + * \brief Format Strings for #BMOperator Initialization. + * + * This system is used to execute or initialize an operator, + * using a formatted-string system. + * + * The basic format for the format string is: + * `[operatorname] [slot_name]=%[code] [slot_name]=%[code]` + * + * Example: + * + * \code{.c} + * BMO_op_callf(bm, BMO_FLAG_DEFAULTS, + * "delete context=%i geom=%hv", + * DEL_ONLYFACES, BM_ELEM_SELECT); + * \endcode + * + * + * **Primitive Types** + * - `b` - boolean (same as int but 1/0 only). #BMO_OP_SLOT_BOOL + * - `i` - int. #BMO_OP_SLOT_INT + * - `f` - float. #BMO_OP_SLOT_FLT + * - `p` - pointer (normally to a Scene/Mesh/Object/BMesh). #BMO_OP_SLOT_PTR + * - `m3` - 3x3 matrix of floats. #BMO_OP_SLOT_MAT + * - `m4` - 4x4 matrix of floats. #BMO_OP_SLOT_MAT + * - `v` - 3D vector of floats. #BMO_OP_SLOT_VEC + * + * + * **Utility** + * + * Pass an existing slot which is copied to either an input or output slot. + * Taking the operator and slot-name pair of args. + * - `s` - slot_in (lower case) + * - `S` - slot_out (upper case) + * * - * i - int - * b - boolean (same as int but 1/0 only) - * f - float - * s - slot_in - * S - slot_out - * hv - header flagged verts (hflag) - * he - header flagged edges (hflag) - * hf - header flagged faces (hflag) - * fv - flagged verts (oflag) - * fe - flagged edges (oflag) - * ff - flagged faces (oflag) + * **Element Buffer** (#BMO_OP_SLOT_ELEMENT_BUF) + * - `e` - single element vert/edge/face (use with #BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE). + * - `av` - all verts + * - `ae` - all edges + * - `af` - all faces + * - `hv` - header flagged verts (hflag) + * - `he` - header flagged edges (hflag) + * - `hf` - header flagged faces (hflag) + * - `Hv` - header flagged verts (hflag off) + * - `He` - header flagged edges (hflag off) + * - `Hf` - header flagged faces (hflag off) + * - `fv` - flagged verts (oflag) + * - `fe` - flagged edges (oflag) + * - `ff` - flagged faces (oflag) + * - `Fv` - flagged verts (oflag off) + * - `Fe` - flagged edges (oflag off) + * - `Ff` - flagged faces (oflag off) * - * capitals - H, F to use the flag flipped (when the flag is off) - * Hv, He, Hf, Fv, Fe, Ff, + * \note The common v/e/f suffix can be mixed, + * so `avef` is can be used for all verts, edges and faces. + * Order is not important so `Hfev` is also valid (all unflagged verts, edges and faces). */ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, va_list vlist) @@ -1463,7 +1582,7 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v } BMO_op_init(bm, op, flag, opname); -// def = opdefines[i]; +// def = bmo_opdefines[i]; i = 0; state = 1; /* 0: not inside slot_code name, 1: inside slot_code name */ @@ -1522,14 +1641,12 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v state = 1; break; } - case 'e': + case 'e': /* single vert/edge/face */ { BMHeader *ele = va_arg(vlist, void *); BMOpSlot *slot = BMO_slot_get(op->slots_in, slot_name); - slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(void *) * 4); - slot->len = 1; - *slot->data.buf = ele; + BMO_slot_buffer_from_single(op, slot, ele); state = 1; break; diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h index 1c62a038f34..c98c3eae50b 100644 --- a/source/blender/bmesh/intern/bmesh_operators.h +++ b/source/blender/bmesh/intern/bmesh_operators.h @@ -85,29 +85,22 @@ enum { SIMVERT_EDGE }; -enum { - OPUVC_AXIS_X = 1, - OPUVC_AXIS_Y -}; - /* vertex path selection values */ enum { VPATH_SELECT_EDGE_LENGTH = 0, VPATH_SELECT_TOPOLOGICAL }; -extern BMOpDefine *opdefines[]; -extern int bmesh_total_ops; +extern const BMOpDefine *bmo_opdefines[]; +extern const int bmo_opdefines_total; /*------specific operator helper functions-------*/ - -struct Object; - 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, + const short use_single_edge, const short use_grid_fill, + const short use_only_quads, int seed); #include "intern/bmesh_operator_api_inline.h" diff --git a/source/blender/bmesh/intern/bmesh_operators_private.h b/source/blender/bmesh/intern/bmesh_operators_private.h index 65c9cf0c421..9175af1c822 100644 --- a/source/blender/bmesh/intern/bmesh_operators_private.h +++ b/source/blender/bmesh/intern/bmesh_operators_private.h @@ -61,7 +61,7 @@ void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op); void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op); void bmo_duplicate_exec(BMesh *bm, BMOperator *op); void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op); -void bmo_edgenet_prepare(BMesh *bm, BMOperator *op); +void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op); void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op); void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op); void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op); diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index ec2e90591cc..195c60c5a9c 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -824,6 +824,29 @@ int BM_edge_share_face_check(BMEdge *e1, BMEdge *e2) } /** + * Test if e1 shares any quad faces with e2 + */ +int BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2) +{ + BMLoop *l; + BMFace *f; + + if (e1->l && e2->l) { + l = e1->l; + do { + f = l->f; + if (f->len == 4) { + if (bmesh_radial_face_find(e2, f)) { + return TRUE; + } + } + l = l->radial_next; + } while (l != e1->l); + } + return FALSE; +} + +/** * Tests to see if e1 shares a vertex with e2 */ int BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2) diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index d97faebf021..7a18f69371e 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -90,6 +90,7 @@ int BM_face_share_edge_count(BMFace *f1, BMFace *f2); int BM_face_share_face_check(BMFace *f1, BMFace *f2); int BM_face_share_edge_check(BMFace *f1, BMFace *f2); int BM_edge_share_face_check(BMEdge *e1, BMEdge *e2); +int BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2); int BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2); BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2); |