Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Wilkins <Jason.A.Wilkins@gmail.com>2012-11-27 05:18:54 +0400
committerJason Wilkins <Jason.A.Wilkins@gmail.com>2012-11-27 05:18:54 +0400
commitff7c690e4064bbb1d6180668625d7b414000e9ea (patch)
tree4ac96ca8ed5a4e6a7ab1104d0271aba02266ace6 /source/blender/bmesh/intern
parent6b65102c20e9bdafd90f55f60c2a2084d873e809 (diff)
parent9b32776be349f5e738b449ca1298e65ce1b69d33 (diff)
Merge w/ trunk: r52086-r52534 (As with last time, the game engine was not merged)soc-2012-swiss_cheese
Diffstat (limited to 'source/blender/bmesh/intern')
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c10
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c69
-rw-r--r--source/blender/bmesh/intern/bmesh_decimate.h41
-rw-r--r--source/blender/bmesh/intern/bmesh_decimate_collapse.c1044
-rw-r--r--source/blender/bmesh/intern/bmesh_decimate_dissolve.c243
-rw-r--r--source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c344
-rw-r--r--source/blender/bmesh/intern/bmesh_interp.c20
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.c10
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.h7
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c44
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.h6
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c774
-rw-r--r--source/blender/bmesh/intern/bmesh_operator_api.h141
-rw-r--r--source/blender/bmesh/intern/bmesh_operator_api_inline.h48
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c434
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.h5
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c9
-rw-r--r--source/blender/bmesh/intern/bmesh_private.h20
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c57
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.h10
20 files changed, 1086 insertions, 2250 deletions
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c
index eae78c6cc25..770196108f0 100644
--- a/source/blender/bmesh/intern/bmesh_construct.c
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -99,7 +99,7 @@ BMFace *BM_face_create_quad_tri_v(BMesh *bm, BMVert **verts, int len, const BMFa
if (nodouble) {
/* check if face exists or overlaps */
- is_overlap = BM_face_exists(bm, verts, len, &f);
+ is_overlap = BM_face_exists(verts, len, &f);
}
/* make new face */
@@ -174,9 +174,9 @@ 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)
{
BMEdge **edges2 = NULL;
- BLI_array_staticdeclare(edges2, BM_NGON_STACK_SIZE);
+ BLI_array_staticdeclare(edges2, BM_DEFAULT_NGON_STACK_SIZE);
BMVert **verts = NULL;
- BLI_array_staticdeclare(verts, BM_NGON_STACK_SIZE);
+ BLI_array_staticdeclare(verts, BM_DEFAULT_NGON_STACK_SIZE);
BMFace *f = NULL;
BMEdge *e;
BMVert *v, *ev1, *ev2;
@@ -187,8 +187,10 @@ BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, i
* _and_ the old bmesh_mf functions, so its kindof smashed together
* - joeedh */
- if (!len || !v1 || !v2 || !edges || !bm)
+ if (!len || !v1 || !v2 || !edges || !bm) {
+ BLI_assert(0);
return NULL;
+ }
/* put edges in correct order */
for (i = 0; i < len; i++) {
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index 0910dd82701..03094873e25 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -76,7 +76,9 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example)
}
/* allocate flag */
- v->oflags = BLI_mempool_calloc(bm->toolflagpool);
+ if (bm->toolflagpool) {
+ v->oflags = BLI_mempool_calloc(bm->toolflagpool);
+ }
CustomData_bmesh_set_default(&bm->vdata, &v->head.data);
@@ -125,12 +127,14 @@ BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example,
e->head.htype = BM_EDGE;
/* allocate flag */
- e->oflags = BLI_mempool_calloc(bm->toolflagpool);
+ if (bm->toolflagpool) {
+ e->oflags = BLI_mempool_calloc(bm->toolflagpool);
+ }
e->v1 = v1;
e->v2 = v2;
- BM_elem_flag_enable(e, BM_ELEM_SMOOTH);
+ BM_elem_flag_enable(e, BM_ELEM_SMOOTH | BM_ELEM_DRAW);
CustomData_bmesh_set_default(&bm->edata, &e->head.data);
@@ -195,8 +199,8 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short co
{
BMVert **verts = NULL;
BMEdge **edges = NULL;
- BLI_array_fixedstack_declare(verts, BM_NGON_STACK_SIZE, f->len, __func__);
- BLI_array_fixedstack_declare(edges, BM_NGON_STACK_SIZE, f->len, __func__);
+ BLI_array_fixedstack_declare(verts, BM_DEFAULT_NGON_STACK_SIZE, f->len, __func__);
+ BLI_array_fixedstack_declare(edges, BM_DEFAULT_NGON_STACK_SIZE, f->len, __func__);
BMLoop *l_iter;
BMLoop *l_first;
BMLoop *l_copy;
@@ -278,7 +282,9 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm)
f->head.htype = BM_FACE;
/* allocate flag */
- f->oflags = BLI_mempool_calloc(bm->toolflagpool);
+ if (bm->toolflagpool) {
+ f->oflags = BLI_mempool_calloc(bm->toolflagpool);
+ }
CustomData_bmesh_set_default(&bm->pdata, &f->head.data);
@@ -305,7 +311,7 @@ BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len,
if (nodouble) {
/* Check if face already exists */
- overlap = BM_face_exists(bm, verts, len, &f);
+ overlap = BM_face_exists(verts, len, &f);
if (overlap) {
return f;
}
@@ -495,7 +501,9 @@ static void bm_kill_only_vert(BMesh *bm, BMVert *v)
if (v->head.data)
CustomData_bmesh_free_block(&bm->vdata, &v->head.data);
- BLI_mempool_free(bm->toolflagpool, v->oflags);
+ if (bm->toolflagpool) {
+ BLI_mempool_free(bm->toolflagpool, v->oflags);
+ }
BLI_mempool_free(bm->vpool, v);
}
@@ -513,7 +521,9 @@ static void bm_kill_only_edge(BMesh *bm, BMEdge *e)
if (e->head.data)
CustomData_bmesh_free_block(&bm->edata, &e->head.data);
- BLI_mempool_free(bm->toolflagpool, e->oflags);
+ if (bm->toolflagpool) {
+ BLI_mempool_free(bm->toolflagpool, e->oflags);
+ }
BLI_mempool_free(bm->epool, e);
}
@@ -534,7 +544,9 @@ static void bm_kill_only_face(BMesh *bm, BMFace *f)
if (f->head.data)
CustomData_bmesh_free_block(&bm->pdata, &f->head.data);
- BLI_mempool_free(bm->toolflagpool, f->oflags);
+ if (bm->toolflagpool) {
+ BLI_mempool_free(bm->toolflagpool, f->oflags);
+ }
BLI_mempool_free(bm->fpool, f);
}
@@ -558,7 +570,7 @@ static void bm_kill_only_loop(BMesh *bm, BMLoop *l)
void BM_face_edges_kill(BMesh *bm, BMFace *f)
{
BMEdge **edges = NULL;
- BLI_array_staticdeclare(edges, BM_NGON_STACK_SIZE);
+ BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE);
BMLoop *l_iter;
BMLoop *l_first;
int i;
@@ -582,7 +594,7 @@ void BM_face_edges_kill(BMesh *bm, BMFace *f)
void BM_face_verts_kill(BMesh *bm, BMFace *f)
{
BMVert **verts = NULL;
- BLI_array_staticdeclare(verts, BM_NGON_STACK_SIZE);
+ BLI_array_staticdeclare(verts, BM_DEFAULT_NGON_STACK_SIZE);
BMLoop *l_iter;
BMLoop *l_first;
int i;
@@ -734,7 +746,7 @@ static int bm_loop_reverse_loop(BMesh *bm, BMFace *f
const int do_disps = CustomData_has_layer(&bm->ldata, CD_MDISPS);
BMLoop *l_iter, *oldprev, *oldnext;
BMEdge **edar = NULL;
- BLI_array_fixedstack_declare(edar, BM_NGON_STACK_SIZE, len, __func__);
+ BLI_array_fixedstack_declare(edar, BM_DEFAULT_NGON_STACK_SIZE, len, __func__);
int i, j, edok;
for (i = 0, l_iter = l_first; i < len; i++, l_iter = l_iter->next) {
@@ -937,9 +949,9 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const short do_del
BMEdge **edges = NULL;
BMEdge **deledges = NULL;
BMVert **delverts = NULL;
- BLI_array_staticdeclare(edges, BM_NGON_STACK_SIZE);
- BLI_array_staticdeclare(deledges, BM_NGON_STACK_SIZE);
- BLI_array_staticdeclare(delverts, BM_NGON_STACK_SIZE);
+ BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE);
+ BLI_array_staticdeclare(deledges, BM_DEFAULT_NGON_STACK_SIZE);
+ BLI_array_staticdeclare(delverts, BM_DEFAULT_NGON_STACK_SIZE);
BMVert *v1 = NULL, *v2 = NULL;
const char *err = NULL;
int i, tote = 0;
@@ -1587,7 +1599,7 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_dou
if (LIKELY(radlen)) {
BMLoop **loops = NULL;
- BLI_array_fixedstack_declare(loops, BM_NGON_STACK_SIZE, radlen, __func__);
+ BLI_array_fixedstack_declare(loops, BM_DEFAULT_NGON_STACK_SIZE, radlen, __func__);
killoop = ke->l;
@@ -1773,14 +1785,18 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
bmesh_disk_edge_remove(f1loop->e, f1loop->e->v2);
/* deallocate edge and its two loops as well as f2 */
- BLI_mempool_free(bm->toolflagpool, f1loop->e->oflags);
+ if (bm->toolflagpool) {
+ BLI_mempool_free(bm->toolflagpool, f1loop->e->oflags);
+ }
BLI_mempool_free(bm->epool, f1loop->e);
bm->totedge--;
BLI_mempool_free(bm->lpool, f1loop);
bm->totloop--;
BLI_mempool_free(bm->lpool, f2loop);
bm->totloop--;
- BLI_mempool_free(bm->toolflagpool, f2->oflags);
+ if (bm->toolflagpool) {
+ BLI_mempool_free(bm->toolflagpool, f2->oflags);
+ }
BLI_mempool_free(bm->fpool, f2);
bm->totface--;
/* account for both above */
@@ -1808,23 +1824,28 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
*/
int BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target)
{
- BMEdge *e;
-
+ void *loops_stack[BM_DEFAULT_ITER_STACK_SIZE];
BMLoop **loops;
int i, loops_tot;
+ BMEdge *e;
+
/* verts already spliced */
if (v == v_target) {
return FALSE;
}
/* we can't modify the vert while iterating so first allocate an array of loops */
- loops = BM_iter_as_arrayN(bm, BM_LOOPS_OF_VERT, v, &loops_tot);
- if (loops) {
+ loops = BM_iter_as_arrayN(bm, BM_LOOPS_OF_VERT, v, &loops_tot,
+ loops_stack, BM_DEFAULT_ITER_STACK_SIZE);
+
+ if (LIKELY(loops != NULL)) {
for (i = 0; i < loops_tot; i++) {
loops[i]->v = v_target;
}
- MEM_freeN(loops);
+ if (loops != (BMLoop **)loops_stack) {
+ MEM_freeN(loops);
+ }
}
/* move all the edges from v's disk to vtarget's disk */
diff --git a/source/blender/bmesh/intern/bmesh_decimate.h b/source/blender/bmesh/intern/bmesh_decimate.h
deleted file mode 100644
index 04dc0cfd2ea..00000000000
--- a/source/blender/bmesh/intern/bmesh_decimate.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributor(s): Campbell Barton
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifndef __BMESH_DECIMATE_H__
-#define __BMESH_DECIMATE_H__
-
-/** \file blender/bmesh/intern/bmesh_decimate.h
- * \ingroup bmesh
- */
-
-void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, const int do_triangulate);
-
-void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int tag_only);
-void BM_mesh_decimate_unsubdivide(BMesh *bm, const int iterations);
-
-void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries,
- BMVert **vinput_arr, const int vinput_len,
- BMEdge **einput_arr, const int einput_len);
-void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries);
-
-
-#endif /* __BMESH_DECIMATE_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_decimate_collapse.c b/source/blender/bmesh/intern/bmesh_decimate_collapse.c
deleted file mode 100644
index 74792d1d558..00000000000
--- a/source/blender/bmesh/intern/bmesh_decimate_collapse.c
+++ /dev/null
@@ -1,1044 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributor(s): Campbell Barton
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/bmesh/intern/bmesh_decimate_collapse.c
- * \ingroup bmesh
- *
- * BMesh decimator that uses an edge collapse method.
- */
-
-#include <stddef.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_scene_types.h"
-
-#include "BLI_math.h"
-#include "BLI_quadric.h"
-#include "BLI_heap.h"
-
-#include "BKE_customdata.h"
-
-#include "bmesh.h"
-#include "bmesh_structure.h"
-#include "bmesh_decimate.h" /* own include */
-
-/* defines for testing */
-#define USE_CUSTOMDATA
-#define USE_TRIANGULATE
-#define USE_VERT_NORMAL_INTERP /* has the advantage that flipped faces don't mess up vertex normals */
-
-/* these checks are for rare cases that we can't avoid since they are valid meshes still */
-#define USE_SAFETY_CHECKS
-
-#define BOUNDARY_PRESERVE_WEIGHT 100.0f
-#define OPTIMIZE_EPS 0.01f /* FLT_EPSILON is too small, see [#33106] */
-#define COST_INVALID FLT_MAX
-
-typedef enum CD_UseFlag {
- CD_DO_VERT = (1 << 0),
- CD_DO_EDGE = (1 << 1),
- CD_DO_LOOP = (1 << 2)
-} CD_UseFlag;
-
-
-/* BMesh Helper Functions
- * ********************** */
-
-/**
- * \param vquadrics must be calloc'd
- */
-static void bm_decim_build_quadrics(BMesh *bm, Quadric *vquadrics)
-{
- BMIter iter;
- BMFace *f;
- BMEdge *e;
-
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- BMLoop *l_first;
- BMLoop *l_iter;
-
- const float *co = BM_FACE_FIRST_LOOP(f)->v->co;
- const float *no = f->no;
- const float offset = -dot_v3v3(no, co);
- Quadric q;
-
- BLI_quadric_from_v3_dist(&q, no, offset);
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(l_iter->v)], &q);
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- /* boundary edges */
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (UNLIKELY(BM_edge_is_boundary(e))) {
- float edge_vector[3];
- float edge_cross[3];
- sub_v3_v3v3(edge_vector, e->v2->co, e->v1->co);
- f = e->l->f;
- cross_v3_v3v3(edge_cross, edge_vector, f->no);
-
- if (normalize_v3(edge_cross) > FLT_EPSILON) {
- Quadric q;
- BLI_quadric_from_v3_dist(&q, edge_cross, -dot_v3v3(edge_cross, e->v1->co));
- BLI_quadric_mul(&q, BOUNDARY_PRESERVE_WEIGHT);
-
- BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(e->v1)], &q);
- BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(e->v2)], &q);
- }
- }
- }
-}
-
-
-static void bm_decim_calc_target_co(BMEdge *e, float optimize_co[3],
- const Quadric *vquadrics)
-{
- /* compute an edge contration target for edge 'e'
- * this is computed by summing it's vertices quadrics and
- * optimizing the result. */
- Quadric q;
-
- BLI_quadric_add_qu_ququ(&q,
- &vquadrics[BM_elem_index_get(e->v1)],
- &vquadrics[BM_elem_index_get(e->v2)]);
-
-
- if (BLI_quadric_optimize(&q, optimize_co, OPTIMIZE_EPS)) {
- return; /* all is good */
- }
- else {
- mid_v3_v3v3(optimize_co, e->v1->co, e->v2->co);
- }
-}
-
-static int bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_co[3])
-{
- BMIter liter;
- BMLoop *l;
- unsigned int i;
-
- for (i = 0; i < 2; i++) {
- /* loop over both verts */
- BMVert *v = *((&e->v1) + i);
-
- BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
- if (l->e != e && l->prev->e != e) {
- float *co_prev = l->prev->v->co;
- float *co_next = l->next->v->co;
- float cross_exist[3];
- float cross_optim[3];
-
-#if 1
- float vec_other[3]; /* line between the two outer verts, re-use for both cross products */
- float vec_exist[3]; /* before collapse */
- float vec_optim[3]; /* after collapse */
-
- sub_v3_v3v3(vec_other, co_prev, co_next);
- sub_v3_v3v3(vec_exist, co_prev, v->co);
- sub_v3_v3v3(vec_optim, co_prev, optimize_co);
-
- cross_v3_v3v3(cross_exist, vec_other, vec_exist);
- cross_v3_v3v3(cross_optim, vec_other, vec_optim);
-
- /* normalize isn't really needed, but ensures the value at a unit we can compare against */
- normalize_v3(cross_exist);
- normalize_v3(cross_optim);
-#else
- normal_tri_v3(cross_exist, v->co, co_prev, co_next);
- normal_tri_v3(cross_optim, optimize_co, co_prev, co_next);
-#endif
-
- /* use a small value rather then zero so we don't flip a face in multiple steps
- * (first making it zero area, then flipping again)*/
- if (dot_v3v3(cross_exist, cross_optim) <= FLT_EPSILON) {
- //printf("no flip\n");
- return TRUE;
- }
- }
- }
- }
-
- return FALSE;
-}
-
-static void bm_decim_build_edge_cost_single(BMEdge *e,
- const Quadric *vquadrics, const float *vweights,
- Heap *eheap, HeapNode **eheap_table)
-{
- const Quadric *q1, *q2;
- float optimize_co[3];
- float cost;
-
- if (eheap_table[BM_elem_index_get(e)]) {
- BLI_heap_remove(eheap, eheap_table[BM_elem_index_get(e)]);
- }
-
- /* check we can collapse, some edges we better not touch */
- if (BM_edge_is_boundary(e)) {
- if (e->l->f->len == 3) {
- /* pass */
- }
- else {
- /* only collapse tri's */
- eheap_table[BM_elem_index_get(e)] = NULL;
- return;
- }
- }
- else if (BM_edge_is_manifold(e)) {
- if ((e->l->f->len == 3) && (e->l->radial_next->f->len == 3)) {
- /* pass */
- }
- else {
- /* only collapse tri's */
- eheap_table[BM_elem_index_get(e)] = NULL;
- return;
- }
- }
- else {
- eheap_table[BM_elem_index_get(e)] = NULL;
- return;
- }
-
- if (vweights) {
- if ((vweights[BM_elem_index_get(e->v1)] < FLT_EPSILON) &&
- (vweights[BM_elem_index_get(e->v2)] < FLT_EPSILON))
- {
- /* skip collapsing this edge */
- eheap_table[BM_elem_index_get(e)] = NULL;
- return;
- }
- }
- /* end sanity check */
-
-
- bm_decim_calc_target_co(e, optimize_co, vquadrics);
-
- q1 = &vquadrics[BM_elem_index_get(e->v1)];
- q2 = &vquadrics[BM_elem_index_get(e->v2)];
-
- if (vweights == NULL) {
- cost = (BLI_quadric_evaluate(q1, optimize_co) +
- BLI_quadric_evaluate(q2, optimize_co));
- }
- else {
- cost = ((BLI_quadric_evaluate(q1, optimize_co) * vweights[BM_elem_index_get(e->v1)]) +
- (BLI_quadric_evaluate(q2, optimize_co) * vweights[BM_elem_index_get(e->v2)]));
- }
- // print("COST %.12f\n");
-
- eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, cost, e);
-}
-
-
-/* use this for degenerate cases - add back to the heap with an invalid cost,
- * this way it may be calculated again if surrounding geometry changes */
-static void bm_decim_invalid_edge_cost_single(BMEdge *e,
- Heap *eheap, HeapNode **eheap_table)
-{
- BLI_assert(eheap_table[BM_elem_index_get(e)] == NULL);
- eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, COST_INVALID, e);
-}
-
-static void bm_decim_build_edge_cost(BMesh *bm,
- const Quadric *vquadrics, const float *vweights,
- Heap *eheap, HeapNode **eheap_table)
-{
- BMIter iter;
- BMEdge *e;
- unsigned int i;
-
- BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
- eheap_table[i] = NULL; /* keep sanity check happy */
- bm_decim_build_edge_cost_single(e, vquadrics, vweights, eheap, eheap_table);
- }
-}
-
-#ifdef USE_TRIANGULATE
-/* Temp Triangulation
- * ****************** */
-
-/**
- * To keep things simple we can only collapse edges on triangulated data
- * (limitation with edge collapse and error calculation functions).
- *
- * But to avoid annoying users by only giving triangle results, we can
- * triangulate, keeping a reference between the faces, then join after
- * if the edges don't collapse, this will also allow more choices when
- * collapsing edges so even has some advantage over decimating quads
- * directly.
- *
- * \return TRUE if any faces were triangulated.
- */
-
-static int bm_decim_triangulate_begin(BMesh *bm)
-{
- BMIter iter;
- BMFace *f;
- // int has_quad; // could optimize this a little
- int has_cut = FALSE;
-
- BLI_assert((bm->elem_index_dirty & BM_VERT) == 0);
-
- /* first clear loop index values */
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- BMLoop *l_iter;
- BMLoop *l_first;
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BM_elem_index_set(l_iter, -1);
- } while ((l_iter = l_iter->next) != l_first);
-
- // has_quad |= (f->len == 4)
- }
-
- /* adding new faces as we loop over faces
- * is normally best avoided, however in this case its not so bad because any face touched twice
- * will already be triangulated*/
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (f->len == 4) {
- BMLoop *f_l[4];
- BMLoop *l_a, *l_b;
-
- {
- BMLoop *l_iter = BM_FACE_FIRST_LOOP(f);
-
- f_l[0] = l_iter; l_iter = l_iter->next;
- f_l[1] = l_iter; l_iter = l_iter->next;
- f_l[2] = l_iter; l_iter = l_iter->next;
- f_l[3] = l_iter;
- }
-
- if (len_squared_v3v3(f_l[0]->v->co, f_l[2]->v->co) <
- len_squared_v3v3(f_l[1]->v->co, f_l[3]->v->co))
- {
- l_a = f_l[0];
- l_b = f_l[2];
- }
- else {
- l_a = f_l[1];
- l_b = f_l[3];
- }
-
-#ifdef USE_SAFETY_CHECKS
- if (BM_edge_exists(l_a->v, l_b->v) == FALSE)
-#endif
- {
- BMFace *f_new;
- BMLoop *l_new;
-
- /* warning, NO_DOUBLE option here isn't handled as nice as it could be
- * - if there is a quad that has a free standing edge joining it along
- * where we want to split the face, there isnt a good way we can handle this.
- * currently that edge will get removed when joining the tris back into a quad. */
- f_new = BM_face_split(bm, f, l_a->v, l_b->v, &l_new, NULL, FALSE);
-
- if (f_new) {
- /* the value of this doesn't matter, only that the 2 loops match and have unique values */
- const int f_index = BM_elem_index_get(f);
-
- /* since we just split theres only ever 2 loops */
- BLI_assert(BM_edge_is_manifold(l_new->e));
-
- BM_elem_index_set(l_new, f_index);
- BM_elem_index_set(l_new->radial_next, f_index);
-
- BM_face_normal_update(f);
- BM_face_normal_update(f_new);
-
- has_cut = TRUE;
- }
- }
- }
- }
-
- BLI_assert((bm->elem_index_dirty & BM_VERT) == 0);
-
- if (has_cut) {
- /* now triangulation is done we need to correct index values */
- BM_mesh_elem_index_ensure(bm, BM_EDGE | BM_FACE);
- }
-
- return has_cut;
-}
-
-static void bm_decim_triangulate_end(BMesh *bm)
-{
- /* decimation finished, now re-join */
- BMIter iter;
- BMEdge *e;
-
- /* boundary edges */
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- BMLoop *l_a, *l_b;
- if (BM_edge_loop_pair(e, &l_a, &l_b)) {
- const int l_a_index = BM_elem_index_get(l_a);
- if (l_a_index != -1) {
- const int l_b_index = BM_elem_index_get(l_b);
- if (l_a_index == l_b_index) {
- if (LIKELY(l_a->f->len == 3 && l_b->f->len == 3)) {
- if (l_a->v != l_b->v) { /* if this is the case, faces have become flipped */
- /* check we are not making a degenerate quad */
- BMVert *vquad[4] = {
- e->v1,
- BM_vert_in_edge(e, l_a->next->v) ? l_a->prev->v : l_a->next->v,
- e->v2,
- BM_vert_in_edge(e, l_b->next->v) ? l_b->prev->v : l_b->next->v,
- };
-
- BLI_assert(ELEM3(vquad[0], vquad[1], vquad[2], vquad[3]) == FALSE);
- BLI_assert(ELEM3(vquad[1], vquad[0], vquad[2], vquad[3]) == FALSE);
- BLI_assert(ELEM3(vquad[2], vquad[1], vquad[0], vquad[3]) == FALSE);
- BLI_assert(ELEM3(vquad[3], vquad[1], vquad[2], vquad[0]) == FALSE);
-
- if (is_quad_convex_v3(vquad[0]->co, vquad[1]->co, vquad[2]->co, vquad[3]->co)) {
- /* highly unlikely to fail, but prevents possible double-ups */
- BMFace *f[2] = {l_a->f, l_b->f};
- BM_faces_join(bm, f, 2, TRUE);
- }
- }
- }
- }
- }
- }
- }
-}
-
-#endif /* USE_TRIANGULATE */
-
-/* Edge Collapse Functions
- * *********************** */
-
-#ifdef USE_CUSTOMDATA
-
-/**
- * \param v is the target to merge into.
- */
-static void bm_edge_collapse_loop_customdata(BMesh *bm, BMLoop *l, BMVert *v_clear, BMVert *v_other,
- const float customdata_fac)
-{
- /* these don't need to be updated, since they will get removed when the edge collapses */
- BMLoop *l_clear, *l_other;
- const int is_manifold = BM_edge_is_manifold(l->e);
- int side;
-
- /* l defines the vert to collapse into */
-
- /* first find the loop of 'v_other' thats attached to the face of 'l' */
- if (l->v == v_clear) {
- l_clear = l;
- l_other = l->next;
- }
- else {
- l_clear = l->next;
- l_other = l;
- }
-
- BLI_assert(l_clear->v == v_clear);
- BLI_assert(l_other->v == v_other);
- (void)v_other; /* quiet warnings for release */
-
- /* now we have both corners of the face 'l->f' */
- for (side = 0; side < 2; side++) {
- int is_seam = FALSE;
- void *src[2];
- BMFace *f_exit = is_manifold ? l->radial_next->f : NULL;
- BMEdge *e_prev = l->e;
- BMLoop *l_first;
- BMLoop *l_iter;
- float w[2];
-
- if (side == 0) {
- l_iter = l_first = l_clear;
- src[0] = l_clear->head.data;
- src[1] = l_other->head.data;
-
- w[0] = customdata_fac;
- w[1] = 1.0f - customdata_fac;
- }
- else {
- l_iter = l_first = l_other;
- src[0] = l_other->head.data;
- src[1] = l_clear->head.data;
-
- w[0] = 1.0f - customdata_fac;
- w[1] = customdata_fac;
- }
-
- // print_v2("weights", w);
-
- /* WATCH IT! - should NOT reference (_clear or _other) vars for this while loop */
-
- /* walk around the fan using 'e_prev' */
- while (((l_iter = BM_vert_step_fan_loop(l_iter, &e_prev)) != l_first) && (l_iter != NULL)) {
- int i;
- /* quit once we hit the opposite face, if we have one */
- if (f_exit && UNLIKELY(f_exit == l_iter->f)) {
- break;
- }
-
- /* break out unless we find a match */
- is_seam = TRUE;
-
- /* ok. we have a loop. now be smart with it! */
- for (i = 0; i < bm->ldata.totlayer; i++) {
- if (CustomData_layer_has_math(&bm->ldata, i)) {
- const int offset = bm->ldata.layers[i].offset;
- const int type = bm->ldata.layers[i].type;
- void *cd_src, *cd_iter;
-
- /* todo, make nicer macros for this */
- cd_src = (char *)src[0] + offset;
- // cd_dst = (char *)src[1] + offset; // UNUSED
- cd_iter = (char *)l_iter->head.data + offset;
-
- /* detect seams */
- if (CustomData_data_equals(type, cd_src, cd_iter)) {
- CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, l_iter->head.data);
- is_seam = FALSE;
- }
- }
- }
-
- if (is_seam) {
- break;
- }
- }
- }
-}
-#endif /* USE_CUSTOMDATA */
-
-/**
- * Check if the collapse will result in a degenerate mesh,
- * that is - duplicate edges or faces.
- *
- * This situation could be checked for when calculating collapse cost
- * however its quite slow and a degenerate collapse could eventuate
- * after the cost is calculated, so instead, check just before collapsing.
- */
-
-static void bm_edge_tag_enable(BMEdge *e)
-{
- BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
- BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
- if (e->l) {
- BM_elem_flag_enable(e->l->f, BM_ELEM_TAG);
- if (e->l != e->l->radial_next) {
- BM_elem_flag_enable(e->l->radial_next->f, BM_ELEM_TAG);
- }
- }
-}
-
-static void bm_edge_tag_disable(BMEdge *e)
-{
- BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
- BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
- if (e->l) {
- BM_elem_flag_disable(e->l->f, BM_ELEM_TAG);
- if (e->l != e->l->radial_next) {
- BM_elem_flag_disable(e->l->radial_next->f, BM_ELEM_TAG);
- }
- }
-}
-
-static int bm_edge_tag_test(BMEdge *e)
-{
- /* is the edge or one of its faces tagged? */
- return (BM_elem_flag_test(e->v1, BM_ELEM_TAG) ||
- BM_elem_flag_test(e->v2, BM_ELEM_TAG) ||
- (e->l && (BM_elem_flag_test(e->l->f, BM_ELEM_TAG) ||
- (e->l != e->l->radial_next &&
- BM_elem_flag_test(e->l->radial_next->f, BM_ELEM_TAG))))
- );
-}
-
-/* takes the edges loop */
-BLI_INLINE int bm_edge_is_manifold_or_boundary(BMLoop *l)
-{
-#if 0
- /* less optimized version of check below */
- return (BM_edge_is_manifold(l->e) || BM_edge_is_boundary(l->e);
-#else
- /* if the edge is a boundary it points to its self, else this must be a manifold */
- return LIKELY(l) && LIKELY(l->radial_next->radial_next == l);
-#endif
-}
-
-static int bm_edge_collapse_is_degenerate_topology(BMEdge *e_first)
-{
- /* simply check that there is no overlap between faces and edges of each vert,
- * (excluding the 2 faces attached to 'e' and 'e' its self) */
-
- BMEdge *e_iter;
-
- /* clear flags on both disks */
- e_iter = e_first;
- do {
- if (!bm_edge_is_manifold_or_boundary(e_iter->l)) {
- return TRUE;
- }
- bm_edge_tag_disable(e_iter);
- } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v1)) != e_first);
-
- e_iter = e_first;
- do {
- if (!bm_edge_is_manifold_or_boundary(e_iter->l)) {
- return TRUE;
- }
- bm_edge_tag_disable(e_iter);
- } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v2)) != e_first);
-
- /* now enable one side... */
- e_iter = e_first;
- do {
- bm_edge_tag_enable(e_iter);
- } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v1)) != e_first);
-
- /* ... except for the edge we will collapse, we know thats shared,
- * disable this to avoid false positive. We could be smart and never enable these
- * face/edge tags in the first place but easier to do this */
- // bm_edge_tag_disable(e_first);
- /* do inline... */
- {
-#if 0
- BMIter iter;
- BMIter liter;
- BMLoop *l;
- BMVert *v;
- BM_ITER_ELEM (l, &liter, e_first, BM_LOOPS_OF_EDGE) {
- BM_elem_flag_disable(l->f, BM_ELEM_TAG);
- BM_ITER_ELEM (v, &iter, l->f, BM_VERTS_OF_FACE) {
- BM_elem_flag_disable(v, BM_ELEM_TAG);
- }
- }
-#else
- /* we know each face is a triangle, no looping/iterators needed here */
-
- BMLoop *l_radial;
- BMLoop *l_face;
-
- l_radial = e_first->l;
- l_face = l_radial;
- BLI_assert(l_face->f->len == 3);
- BM_elem_flag_disable(l_face->f, BM_ELEM_TAG);
- BM_elem_flag_disable((l_face = l_radial)->v, BM_ELEM_TAG);
- BM_elem_flag_disable((l_face = l_face->next)->v, BM_ELEM_TAG);
- BM_elem_flag_disable(( l_face->next)->v, BM_ELEM_TAG);
- l_face = l_radial->radial_next;
- if (l_radial != l_face) {
- BLI_assert(l_face->f->len == 3);
- BM_elem_flag_disable(l_face->f, BM_ELEM_TAG);
- BM_elem_flag_disable((l_face = l_radial->radial_next)->v, BM_ELEM_TAG);
- BM_elem_flag_disable((l_face = l_face->next)->v, BM_ELEM_TAG);
- BM_elem_flag_disable(( l_face->next)->v, BM_ELEM_TAG);
- }
-#endif
- }
-
- /* and check for overlap */
- e_iter = e_first;
- do {
- if (bm_edge_tag_test(e_iter)) {
- return TRUE;
- }
- } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v2)) != e_first);
-
- return FALSE;
-}
-
-/**
- * special, highly limited edge collapse function
- * intended for speed over flexibiliy.
- * can only collapse edges connected to (1, 2) tris.
- *
- * Important - dont add vert/edge/face data on collapsing!
- *
- * \param e_clear_other let caller know what edges we remove besides \a e_clear
- * \param customdata_flag merge factor, scales from 0 - 1 ('v_clear' -> 'v_other')
- */
-static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e_clear_other[2],
-#ifdef USE_CUSTOMDATA
- const CD_UseFlag customdata_flag,
- const float customdata_fac
-#else
- const CD_UseFlag UNUSED(customdata_flag),
- const float UNUSED(customdata_fac)
-#endif
- )
-{
- BMVert *v_other;
-
- v_other = BM_edge_other_vert(e_clear, v_clear);
- BLI_assert(v_other != NULL);
-
- if (BM_edge_is_manifold(e_clear)) {
- BMLoop *l_a, *l_b;
- BMEdge *e_a_other[2], *e_b_other[2];
- int ok;
-
- ok = BM_edge_loop_pair(e_clear, &l_a, &l_b);
-
- BLI_assert(ok == TRUE);
- BLI_assert(l_a->f->len == 3);
- BLI_assert(l_b->f->len == 3);
-
- /* keep 'v_clear' 0th */
- if (BM_vert_in_edge(l_a->prev->e, v_clear)) {
- e_a_other[0] = l_a->prev->e;
- e_a_other[1] = l_a->next->e;
- }
- else {
- e_a_other[1] = l_a->prev->e;
- e_a_other[0] = l_a->next->e;
- }
-
- if (BM_vert_in_edge(l_b->prev->e, v_clear)) {
- e_b_other[0] = l_b->prev->e;
- e_b_other[1] = l_b->next->e;
- }
- else {
- e_b_other[1] = l_b->prev->e;
- e_b_other[0] = l_b->next->e;
- }
-
- BLI_assert(BM_edge_share_vert(e_a_other[0], e_b_other[0]));
- BLI_assert(BM_edge_share_vert(e_a_other[1], e_b_other[1]));
-
- /* we could assert this case, but better just bail out */
-#if 0
- BLI_assert(e_a_other[0] != e_b_other[0]);
- BLI_assert(e_a_other[0] != e_b_other[1]);
- BLI_assert(e_b_other[0] != e_a_other[0]);
- BLI_assert(e_b_other[0] != e_a_other[1]);
-#endif
- /* not totally common but we want to avoid */
- if (ELEM(e_a_other[0], e_b_other[0], e_b_other[1]) ||
- ELEM(e_a_other[1], e_b_other[0], e_b_other[1]))
- {
- return FALSE;
- }
-
- r_e_clear_other[0] = BM_elem_index_get(e_a_other[0]);
- r_e_clear_other[1] = BM_elem_index_get(e_b_other[0]);
-
-#ifdef USE_CUSTOMDATA
- /* before killing, do customdata */
- if (customdata_flag & CD_DO_VERT) {
- BM_data_interp_from_verts(bm, v_other, v_clear, v_other, customdata_fac);
- }
- if (customdata_flag & CD_DO_EDGE) {
- BM_data_interp_from_edges(bm, e_a_other[1], e_a_other[0], e_a_other[1], customdata_fac);
- BM_data_interp_from_edges(bm, e_b_other[1], e_b_other[0], e_b_other[1], customdata_fac);
- }
- if (customdata_flag & CD_DO_LOOP) {
- bm_edge_collapse_loop_customdata(bm, e_clear->l, v_clear, v_other, customdata_fac);
- bm_edge_collapse_loop_customdata(bm, e_clear->l->radial_next, v_clear, v_other, customdata_fac);
- }
-#endif
-
- BM_edge_kill(bm, e_clear);
-
- v_other->head.hflag |= v_clear->head.hflag;
- BM_vert_splice(bm, v_clear, v_other);
-
- e_a_other[1]->head.hflag |= e_a_other[0]->head.hflag;
- e_b_other[1]->head.hflag |= e_b_other[0]->head.hflag;
- BM_edge_splice(bm, e_a_other[0], e_a_other[1]);
- BM_edge_splice(bm, e_b_other[0], e_b_other[1]);
-
- // BM_mesh_validate(bm);
-
- return TRUE;
- }
- else if (BM_edge_is_boundary(e_clear)) {
- /* same as above but only one triangle */
- BMLoop *l_a;
- BMEdge *e_a_other[2];
-
- l_a = e_clear->l;
-
- BLI_assert(l_a->f->len == 3);
-
- /* keep 'v_clear' 0th */
- if (BM_vert_in_edge(l_a->prev->e, v_clear)) {
- e_a_other[0] = l_a->prev->e;
- e_a_other[1] = l_a->next->e;
- }
- else {
- e_a_other[1] = l_a->prev->e;
- e_a_other[0] = l_a->next->e;
- }
-
- r_e_clear_other[0] = BM_elem_index_get(e_a_other[0]);
- r_e_clear_other[1] = -1;
-
-#ifdef USE_CUSTOMDATA
- /* before killing, do customdata */
- if (customdata_flag & CD_DO_VERT) {
- BM_data_interp_from_verts(bm, v_other, v_clear, v_other, customdata_fac);
- }
- if (customdata_flag & CD_DO_EDGE) {
- BM_data_interp_from_edges(bm, e_a_other[1], e_a_other[0], e_a_other[1], customdata_fac);
- }
- if (customdata_flag & CD_DO_LOOP) {
- bm_edge_collapse_loop_customdata(bm, e_clear->l, v_clear, v_other, customdata_fac);
- }
-#endif
-
- BM_edge_kill(bm, e_clear);
-
- v_other->head.hflag |= v_clear->head.hflag;
- BM_vert_splice(bm, v_clear, v_other);
-
- e_a_other[1]->head.hflag |= e_a_other[0]->head.hflag;
- BM_edge_splice(bm, e_a_other[0], e_a_other[1]);
-
- // BM_mesh_validate(bm);
-
- return TRUE;
- }
- else {
- return FALSE;
- }
-}
-
-
-/* collapse e the edge, removing e->v2 */
-static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e,
- Quadric *vquadrics, float *vweights,
- Heap *eheap, HeapNode **eheap_table,
- const CD_UseFlag customdata_flag)
-{
- int e_clear_other[2];
- BMVert *v_other = e->v1;
- int v_clear_index = BM_elem_index_get(e->v2); /* the vert is removed so only store the index */
- float optimize_co[3];
- float customdata_fac;
-
-#ifdef USE_VERT_NORMAL_INTERP
- float v_clear_no[3];
- copy_v3_v3(v_clear_no, e->v2->no);
-#endif
-
- /* disallow collapsing which results in degenerate cases */
- if (UNLIKELY(bm_edge_collapse_is_degenerate_topology(e))) {
- bm_decim_invalid_edge_cost_single(e, eheap, eheap_table); /* add back with a high cost */
- return;
- }
-
- bm_decim_calc_target_co(e, optimize_co, vquadrics);
-
- /* check if this would result in an overlapping face */
- if (UNLIKELY(bm_edge_collapse_is_degenerate_flip(e, optimize_co))) {
- bm_decim_invalid_edge_cost_single(e, eheap, eheap_table); /* add back with a high cost */
- return;
- }
-
- /* use for customdata merging */
- if (LIKELY(compare_v3v3(e->v1->co, e->v2->co, FLT_EPSILON) == FALSE)) {
- customdata_fac = line_point_factor_v3(optimize_co, e->v1->co, e->v2->co);
-#if 0
- /* simple test for stupid collapse */
- if (customdata_fac < 0.0 - FLT_EPSILON || customdata_fac > 1.0f + FLT_EPSILON) {
- return;
- }
-#endif
- }
- else {
- /* avoid divide by zero */
- customdata_fac = 0.5f;
- }
-
- if (bm_edge_collapse(bm, e, e->v2, e_clear_other, customdata_flag, customdata_fac)) {
- /* update collapse info */
- int i;
-
- if (vweights) {
- const int fac = CLAMPIS(customdata_fac, 0.0f, 1.0f);
- vweights[BM_elem_index_get(v_other)] = (vweights[v_clear_index] * (1.0f - fac)) +
- (vweights[BM_elem_index_get(v_other)] * fac);
- }
-
- e = NULL; /* paranoid safety check */
-
- copy_v3_v3(v_other->co, optimize_co);
-
- /* remove eheap */
- for (i = 0; i < 2; i++) {
- /* highly unlikely 'eheap_table[ke_other[i]]' would be NULL, but do for sanity sake */
- if ((e_clear_other[i] != -1) && (eheap_table[e_clear_other[i]] != NULL)) {
- BLI_heap_remove(eheap, eheap_table[e_clear_other[i]]);
- eheap_table[e_clear_other[i]] = NULL;
- }
- }
-
- /* update vertex quadric, add kept vertex from killed vertex */
- BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(v_other)], &vquadrics[v_clear_index]);
-
- /* update connected normals */
-
- /* in fact face normals are not used for progressive updates, no need to update them */
- // BM_vert_normal_update_all(v);
-#ifdef USE_VERT_NORMAL_INTERP
- interp_v3_v3v3(v_other->no, v_other->no, v_clear_no, customdata_fac);
- normalize_v3(v_other->no);
-#else
- BM_vert_normal_update(v_other);
-#endif
-
-
- /* update error costs and the eheap */
- if (LIKELY(v_other->e)) {
- BMEdge *e_iter;
- BMEdge *e_first;
- e_iter = e_first = v_other->e;
- do {
- BLI_assert(BM_edge_find_double(e_iter) == NULL);
- bm_decim_build_edge_cost_single(e_iter, vquadrics, vweights, eheap, eheap_table);
- } while ((e_iter = bmesh_disk_edge_next(e_iter, v_other)) != e_first);
- }
-
- /* this block used to be disabled,
- * but enable now since surrounding faces may have been
- * set to COST_INVALID because of a face overlap that no longer occurs */
-#if 1
- /* optional, update edges around the vertex face fan */
- {
- BMIter liter;
- BMLoop *l;
- BM_ITER_ELEM (l, &liter, v_other, BM_LOOPS_OF_VERT) {
- if (l->f->len == 3) {
- BMEdge *e_outer;
- if (BM_vert_in_edge(l->prev->e, l->v))
- e_outer = l->next->e;
- else
- e_outer = l->prev->e;
-
- BLI_assert(BM_vert_in_edge(e_outer, l->v) == FALSE);
-
- bm_decim_build_edge_cost_single(e_outer, vquadrics, vweights, eheap, eheap_table);
- }
- }
- }
- /* end optional update */
-#endif
- }
- else {
- /* add back with a high cost */
- bm_decim_invalid_edge_cost_single(e, eheap, eheap_table);
- }
-}
-
-
-/* Main Decimate Function
- * ********************** */
-
-/**
- * \brief BM_mesh_decimate
- * \param bm The mesh
- * \param factor face count multiplier [0 - 1]
- * \param vertex_weights Optional array of vertex aligned weights [0 - 1],
- * a vertex group is the usual source for this.
- */
-void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, const int do_triangulate)
-{
- Heap *eheap; /* edge heap */
- HeapNode **eheap_table; /* edge index aligned table pointing to the eheap */
- Quadric *vquadrics; /* vert index aligned quadrics */
- int tot_edge_orig;
- int face_tot_target;
- int use_triangulate;
-
- CD_UseFlag customdata_flag = 0;
-
-#ifdef USE_TRIANGULATE
- /* temp convert quads to triangles */
- use_triangulate = bm_decim_triangulate_begin(bm);
-#endif
-
-
- /* alloc vars */
- vquadrics = MEM_callocN(sizeof(Quadric) * bm->totvert, __func__);
- /* since some edges may be degenerate, we might be over allocing a little here */
- eheap = BLI_heap_new_ex(bm->totedge);
- eheap_table = MEM_callocN(sizeof(HeapNode *) * bm->totedge, __func__);
- tot_edge_orig = bm->totedge;
-
-
- /* build initial edge collapse cost data */
- bm_decim_build_quadrics(bm, vquadrics);
-
- bm_decim_build_edge_cost(bm, vquadrics, vweights, eheap, eheap_table);
-
- face_tot_target = bm->totface * factor;
- bm->elem_index_dirty |= BM_FACE | BM_EDGE | BM_VERT;
-
-
-#ifdef USE_CUSTOMDATA
- /* initialize customdata flag, we only need math for loops */
- if (CustomData_has_interp(&bm->vdata)) customdata_flag |= CD_DO_VERT;
- if (CustomData_has_interp(&bm->edata)) customdata_flag |= CD_DO_EDGE;
- if (CustomData_has_math(&bm->ldata)) customdata_flag |= CD_DO_LOOP;
-#endif
-
- /* iterative edge collapse and maintain the eheap */
- while ((bm->totface > face_tot_target) &&
- (BLI_heap_is_empty(eheap) == FALSE) &&
- (BLI_heap_node_value(BLI_heap_top(eheap)) != COST_INVALID))
- {
- // const float value = BLI_heap_node_value(BLI_heap_top(eheap));
- BMEdge *e = BLI_heap_popmin(eheap);
- BLI_assert(BM_elem_index_get(e) < tot_edge_orig); /* handy to detect corruptions elsewhere */
-
- // printf("COST %.10f\n", value);
-
- /* under normal conditions wont be accessed again,
- * but NULL just incase so we don't use freed node */
- eheap_table[BM_elem_index_get(e)] = NULL;
-
- bm_decim_edge_collapse(bm, e, vquadrics, vweights, eheap, eheap_table, customdata_flag);
- }
-
-
-#ifdef USE_TRIANGULATE
- if (do_triangulate == FALSE) {
- /* its possible we only had triangles, skip this step in that case */
- if (LIKELY(use_triangulate)) {
- /* temp convert quads to triangles */
- bm_decim_triangulate_end(bm);
- }
- }
-#endif
-
- /* free vars */
- MEM_freeN(vquadrics);
- MEM_freeN(eheap_table);
- BLI_heap_free(eheap, NULL);
-
- /* testing only */
- // BM_mesh_validate(bm);
-
- (void)tot_edge_orig; /* quiet release build warning */
-}
diff --git a/source/blender/bmesh/intern/bmesh_decimate_dissolve.c b/source/blender/bmesh/intern/bmesh_decimate_dissolve.c
deleted file mode 100644
index d1371a18160..00000000000
--- a/source/blender/bmesh/intern/bmesh_decimate_dissolve.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributor(s): Campbell Barton
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/bmesh/intern/bmesh_decimate_dissolve.c
- * \ingroup bmesh
- *
- * BMesh decimator that dissolves flat areas into polygons (ngons).
- */
-
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_math.h"
-
-#include "bmesh.h"
-#include "bmesh_decimate.h" /* own include */
-
-#define UNIT_TO_ANGLE DEG2RADF(90.0f)
-#define ANGLE_TO_UNIT (1.0f / UNIT_TO_ANGLE)
-
-/* multiply vertex edge angle by face angle
- * this means we are not left with sharp corners between _almost_ planer faces
- * convert angles [0-PI/2] -> [0-1], multiply together, then convert back to radians. */
-static float bm_vert_edge_face_angle(BMVert *v)
-{
- const float angle = BM_vert_calc_edge_angle(v);
- /* note: could be either edge, it doesn't matter */
- if (v->e && BM_edge_is_manifold(v->e)) {
- return ((angle * ANGLE_TO_UNIT) * (BM_edge_calc_face_angle(v->e) * ANGLE_TO_UNIT)) * UNIT_TO_ANGLE;
- }
- else {
- return angle;
- }
-}
-
-#undef UNIT_TO_ANGLE
-#undef ANGLE_TO_UNIT
-
-typedef struct DissolveElemWeight {
- BMHeader *ele;
- float weight;
-} DissolveElemWeight;
-
-static int dissolve_elem_cmp(const void *a1, const void *a2)
-{
- const struct DissolveElemWeight *d1 = a1, *d2 = a2;
-
- if (d1->weight > d2->weight) return 1;
- else if (d1->weight < d2->weight) return -1;
- return 0;
-}
-
-/**
- * \param do_all_verts Collapse all verts between 2 faces - don't check their edge angle.
- */
-void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries,
- BMVert **vinput_arr, const int vinput_len,
- BMEdge **einput_arr, const int einput_len)
-{
- const float angle_max = (float)M_PI / 2.0f;
- DissolveElemWeight *weight_elems = MEM_mallocN(max_ii(einput_len, vinput_len) *
- sizeof(DissolveElemWeight), __func__);
- int i, tot_found;
-
- BMIter iter;
- BMEdge *e_iter;
- BMEdge **earray;
-
- int *vert_reverse_lookup;
-
- /* --- first edges --- */
-
- /* wire -> tag */
- BM_ITER_MESH (e_iter, &iter, bm, BM_EDGES_OF_MESH) {
- BM_elem_flag_set(e_iter, BM_ELEM_TAG, BM_edge_is_wire(e_iter));
- }
-
- /* go through and split edge */
- for (i = 0, tot_found = 0; i < einput_len; i++) {
- BMEdge *e = einput_arr[i];
- const float angle = BM_edge_calc_face_angle(e);
-
- if (angle < angle_limit) {
- tot_found++;
- }
- weight_elems[i].ele = (BMHeader *)e;
- weight_elems[i].weight = angle;
- }
-
- if (tot_found != 0) {
- qsort(weight_elems, einput_len, sizeof(DissolveElemWeight), dissolve_elem_cmp);
-
- for (i = 0; i < tot_found; i++) {
- BMEdge *e = (BMEdge *)weight_elems[i].ele;
-
- if (/* may have become non-manifold */
- BM_edge_is_manifold(e) &&
- /* check twice because cumulative effect could dissolve over angle limit */
- (BM_edge_calc_face_angle(e) < angle_limit))
- {
- BMFace *nf = BM_faces_join_pair(bm, e->l->f,
- e->l->radial_next->f,
- e,
- FALSE); /* join faces */
-
- /* there may be some errors, we don't mind, just move on */
- if (nf) {
- BM_face_normal_update(nf);
- }
- else {
- BMO_error_clear(bm);
- }
- }
- }
- }
-
- /* prepare for cleanup */
- BM_mesh_elem_index_ensure(bm, BM_VERT);
- vert_reverse_lookup = MEM_mallocN(sizeof(int) * bm->totvert, __func__);
- fill_vn_i(vert_reverse_lookup, bm->totvert, -1);
- for (i = 0, tot_found = 0; i < vinput_len; i++) {
- BMVert *v = vinput_arr[i];
- vert_reverse_lookup[BM_elem_index_get(v)] = i;
- }
-
- /* --- cleanup --- */
- earray = MEM_mallocN(sizeof(BMEdge *) * bm->totedge, __func__);
- BM_ITER_MESH_INDEX (e_iter, &iter, bm, BM_EDGES_OF_MESH, i) {
- earray[i] = e_iter;
- }
- /* remove all edges/verts left behind from dissolving, NULL'ing the vertex array so we dont re-use */
- for (i = bm->totedge - 1; i != -1; i--) {
- e_iter = earray[i];
-
- if (BM_edge_is_wire(e_iter) && (BM_elem_flag_test(e_iter, BM_ELEM_TAG) == FALSE)) {
- /* edge has become wire */
- int vidx_reverse;
- BMVert *v1 = e_iter->v1;
- BMVert *v2 = e_iter->v2;
- BM_edge_kill(bm, e_iter);
- if (v1->e == NULL) {
- vidx_reverse = vert_reverse_lookup[BM_elem_index_get(v1)];
- if (vidx_reverse != -1) vinput_arr[vidx_reverse] = NULL;
- BM_vert_kill(bm, v1);
- }
- if (v2->e == NULL) {
- vidx_reverse = vert_reverse_lookup[BM_elem_index_get(v2)];
- if (vidx_reverse != -1) vinput_arr[vidx_reverse] = NULL;
- BM_vert_kill(bm, v2);
- }
- }
- }
- MEM_freeN(vert_reverse_lookup);
-
- MEM_freeN(earray);
-
-
- /* --- second verts --- */
- if (do_dissolve_boundaries) {
- /* simple version of the branch below, sincve we will dissolve _all_ verts that use 2 edges */
- for (i = 0; i < vinput_len; i++) {
- BMVert *v = vinput_arr[i];
- if (LIKELY(v != NULL) &&
- BM_vert_edge_count(v) == 2)
- {
- BM_vert_collapse_edge(bm, v->e, v, TRUE); /* join edges */
- }
- }
- }
- else {
- for (i = 0, tot_found = 0; i < vinput_len; i++) {
- BMVert *v = vinput_arr[i];
- const float angle = v ? bm_vert_edge_face_angle(v) : angle_limit;
-
- if (angle < angle_limit) {
- weight_elems[i].ele = (BMHeader *)v;
- weight_elems[i].weight = angle;
- tot_found++;
- }
- else {
- weight_elems[i].ele = NULL;
- weight_elems[i].weight = angle_max;
- }
- }
-
- if (tot_found != 0) {
- qsort(weight_elems, vinput_len, sizeof(DissolveElemWeight), dissolve_elem_cmp);
-
- for (i = 0; i < tot_found; i++) {
- BMVert *v = (BMVert *)weight_elems[i].ele;
- if (LIKELY(v != NULL) &&
- /* topology changes may cause this to be un-collapsable */
- (BM_vert_edge_count(v) == 2) &&
- /* check twice because cumulative effect could dissolve over angle limit */
- bm_vert_edge_face_angle(v) < angle_limit)
- {
- BMEdge *ne = BM_vert_collapse_edge(bm, v->e, v, TRUE); /* join edges */
-
- if (ne && ne->l) {
- BM_edge_normals_update(ne);
- }
- }
- }
- }
- }
-
- MEM_freeN(weight_elems);
-}
-
-void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries)
-{
- int vinput_len;
- int einput_len;
-
- BMVert **vinput_arr = BM_iter_as_arrayN(bm, BM_VERTS_OF_MESH, NULL, &vinput_len);
- BMEdge **einput_arr = BM_iter_as_arrayN(bm, BM_EDGES_OF_MESH, NULL, &einput_len);
-
- BM_mesh_decimate_dissolve_ex(bm, angle_limit, do_dissolve_boundaries,
- vinput_arr, vinput_len,
- einput_arr, einput_len);
-
- MEM_freeN(vinput_arr);
- MEM_freeN(einput_arr);
-}
diff --git a/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c
deleted file mode 100644
index 1ec13010d80..00000000000
--- a/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributor(s): Campbell Barton
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/bmesh/intern/bmesh_decimate_unsubdivide.c
- * \ingroup bmesh
- *
- * BMesh decimator that uses a grid un-subdivide method.
- */
-
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_math.h"
-
-#include "bmesh.h"
-
-#include "intern/bmesh_operators_private.h" /* own include */
-
-
-static int bm_vert_dissolve_fan_test(BMVert *v)
-{
- /* check if we should walk over these verts */
- BMIter iter;
- BMEdge *e;
-
- unsigned int tot_edge = 0;
- unsigned int tot_edge_boundary = 0;
- unsigned int tot_edge_manifold = 0;
- unsigned int tot_edge_wire = 0;
-
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- if (BM_edge_is_boundary(e)) {
- tot_edge_boundary++;
- }
- else if (BM_edge_is_manifold(e)) {
- tot_edge_manifold++;
- }
- else if (BM_edge_is_wire(e)) {
- tot_edge_wire++;
- }
- tot_edge++;
- }
-
- if ((tot_edge == 4) && (tot_edge_boundary == 0) && (tot_edge_manifold == 4)) {
- return TRUE;
- }
- else if ((tot_edge == 3) && (tot_edge_boundary == 0) && (tot_edge_manifold == 3)) {
- return TRUE;
- }
- else if ((tot_edge == 3) && (tot_edge_boundary == 2) && (tot_edge_manifold == 1)) {
- return TRUE;
- }
- else if ((tot_edge == 2) && (tot_edge_wire == 2)) {
- return TRUE;
- }
- return FALSE;
-}
-
-static int bm_vert_dissolve_fan(BMesh *bm, BMVert *v)
-{
- /* collapse under 2 conditions.
- * - vert connects to 4 manifold edges (and 4 faces).
- * - vert connecrs to 1 manifold edge, 2 boundary edges (and 2 faces).
- *
- * This covers boundary verts of a quad grid and center verts.
- * note that surrounding faces dont have to be quads.
- */
-
- BMIter iter;
- BMEdge *e;
-
- unsigned int tot_loop = 0;
- unsigned int tot_edge = 0;
- unsigned int tot_edge_boundary = 0;
- unsigned int tot_edge_manifold = 0;
- unsigned int tot_edge_wire = 0;
-
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- if (BM_edge_is_boundary(e)) {
- tot_edge_boundary++;
- }
- else if (BM_edge_is_manifold(e)) {
- tot_edge_manifold++;
- }
- else if (BM_edge_is_wire(e)) {
- tot_edge_wire++;
- }
- tot_edge++;
- }
-
- if (tot_edge == 2) {
- /* check for 2 wire verts only */
- if (tot_edge_wire == 2) {
- return (BM_vert_collapse_edge(bm, v->e, v, TRUE) != NULL);
- }
- }
- else if (tot_edge == 4) {
- /* check for 4 faces surrounding */
- if (tot_edge_boundary == 0 && tot_edge_manifold == 4) {
- /* good to go! */
- tot_loop = 4;
- }
- }
- else if (tot_edge == 3) {
- /* check for 2 faces surrounding at a boundary */
- if (tot_edge_boundary == 2 && tot_edge_manifold == 1) {
- /* good to go! */
- tot_loop = 2;
- }
- else if (tot_edge_boundary == 0 && tot_edge_manifold == 3) {
- /* good to go! */
- tot_loop = 3;
- }
- }
-
- if (tot_loop) {
- BMLoop *f_loop[4];
- unsigned int i;
-
- /* ensure there are exactly tot_loop loops */
- BLI_assert(BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v, tot_loop) == NULL);
- BM_iter_as_array(bm, BM_LOOPS_OF_VERT, v, (void **)f_loop, tot_loop);
-
- for (i = 0; i < tot_loop; i++) {
- BMLoop *l = f_loop[i];
- if (l->f->len > 3) {
- BMLoop *l_new;
- BLI_assert(l->prev->v != l->next->v);
- BM_face_split(bm, l->f, l->prev->v, l->next->v, &l_new, NULL, TRUE);
- BM_elem_flag_merge_into(l_new->e, l->e, l->prev->e);
- }
- }
-
- return BM_vert_dissolve(bm, v);
- }
-
- return FALSE;
-}
-
-enum {
- VERT_INDEX_DO_COLLAPSE = -1,
- VERT_INDEX_INIT = 0,
- VERT_INDEX_IGNORE = 1
-};
-
-// #define USE_WALKER /* gives uneven results, disable for now */
-
-/* - BMVert.flag & BM_ELEM_TAG: shows we touched this vert
- * - BMVert.index == -1: shows we will remove this vert
- */
-
-/**
- * \param tag_only so we can call this from an operator */
-void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int tag_only)
-{
-#ifdef USE_WALKER
-# define ELE_VERT_TAG 1
-#else
- BMVert **vert_seek_a = MEM_mallocN(sizeof(BMVert *) * bm->totvert, __func__);
- BMVert **vert_seek_b = MEM_mallocN(sizeof(BMVert *) * bm->totvert, __func__);
- unsigned vert_seek_a_tot = 0;
- unsigned vert_seek_b_tot = 0;
-#endif
-
- BMVert *v;
- BMIter iter;
-
- const unsigned int offset = 0;
- const unsigned int nth = 2;
-
- int iter_step;
-
- /* if tag_only is set, we assyme the caller knows what verts to tag
- * needed for the operator */
- if (tag_only == FALSE) {
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_enable(v, BM_ELEM_TAG);
- }
- }
-
- for (iter_step = 0; iter_step < iterations; iter_step++) {
- int iter_done;
-
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG) && bm_vert_dissolve_fan_test(v)) {
-#ifdef USE_WALKER
- BMO_elem_flag_enable(bm, v, ELE_VERT_TAG);
-#endif
- BM_elem_index_set(v, VERT_INDEX_INIT); /* set_dirty! */
- }
- else {
- BM_elem_index_set(v, VERT_INDEX_IGNORE); /* set_dirty! */
- }
- }
- /* done with selecting tagged verts */
-
-
- /* main loop, keep tagging until we can't tag any more islands */
- while (TRUE) {
-#ifdef USE_WALKER
- BMWalker walker;
-#else
- unsigned int depth = 1;
- unsigned int i;
-#endif
- BMVert *v_first = NULL;
- BMVert *v;
-
- /* we could avoid iterating from the start each time */
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (v->e && (BM_elem_index_get(v) == VERT_INDEX_INIT)) {
-#ifdef USE_WALKER
- if (BMO_elem_flag_test(bm, v, ELE_VERT_TAG))
-#endif
- {
- /* check again incase the topology changed */
- if (bm_vert_dissolve_fan_test(v)) {
- v_first = v;
- }
- break;
- }
- }
- }
- if (v_first == NULL) {
- break;
- }
-
-#ifdef USE_WALKER
- /* Walk over selected elements starting at active */
- BMW_init(&walker, bm, BMW_CONNECTED_VERTEX,
- ELE_VERT_TAG, BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_NOP, /* don't use BMW_FLAG_TEST_HIDDEN here since we want to desel all */
- BMW_NIL_LAY);
-
- BLI_assert(walker.order == BMW_BREADTH_FIRST);
- for (v = BMW_begin(&walker, v_first); v != NULL; v = BMW_step(&walker)) {
- /* Deselect elements that aren't at "nth" depth from active */
- if (BM_elem_index_get(v) == VERT_INDEX_INIT) {
- if ((offset + BMW_current_depth(&walker)) % nth) {
- /* tag for removal */
- BM_elem_index_set(v, VERT_INDEX_DO_COLLAPSE); /* set_dirty! */
- }
- else {
- /* works better to allow these verts to be checked again */
- //BM_elem_index_set(v, VERT_INDEX_IGNORE); /* set_dirty! */
- }
- }
- }
- BMW_end(&walker);
-#else
-
- BM_elem_index_set(v_first, (offset + depth) % nth ? VERT_INDEX_IGNORE : VERT_INDEX_DO_COLLAPSE); /* set_dirty! */
-
- vert_seek_b_tot = 0;
- vert_seek_b[vert_seek_b_tot++] = v_first;
-
- while (TRUE) {
- BMEdge *e;
-
- if ((offset + depth) % nth) {
- vert_seek_a_tot = 0;
- for (i = 0; i < vert_seek_b_tot; i++) {
- v = vert_seek_b[i];
- BLI_assert(BM_elem_index_get(v) == VERT_INDEX_IGNORE);
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- BMVert *v_other = BM_edge_other_vert(e, v);
- if (BM_elem_index_get(v_other) == VERT_INDEX_INIT) {
- BM_elem_index_set(v_other, VERT_INDEX_DO_COLLAPSE); /* set_dirty! */
- vert_seek_a[vert_seek_a_tot++] = v_other;
- }
- }
- }
- if (vert_seek_a_tot == 0) {
- break;
- }
- }
- else {
- vert_seek_b_tot = 0;
- for (i = 0; i < vert_seek_a_tot; i++) {
- v = vert_seek_a[i];
- BLI_assert(BM_elem_index_get(v) == VERT_INDEX_DO_COLLAPSE);
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- BMVert *v_other = BM_edge_other_vert(e, v);
- if (BM_elem_index_get(v_other) == VERT_INDEX_INIT) {
- BM_elem_index_set(v_other, VERT_INDEX_IGNORE); /* set_dirty! */
- vert_seek_b[vert_seek_b_tot++] = v_other;
- }
- }
- }
- if (vert_seek_b_tot == 0) {
- break;
- }
- }
-
- depth++;
- }
-#endif /* USE_WALKER */
-
- }
-
- /* now we tagged all verts -1 for removal, lets loop over and rebuild faces */
- iter_done = FALSE;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_index_get(v) == VERT_INDEX_DO_COLLAPSE) {
- iter_done |= bm_vert_dissolve_fan(bm, v);
- }
- }
-
- if (iter_done == FALSE) {
- break;
- }
- }
-
- bm->elem_index_dirty |= BM_VERT;
-
-#ifndef USE_WALKER
- MEM_freeN(vert_seek_a);
- MEM_freeN(vert_seek_b);
-#endif
-}
-
-void BM_mesh_decimate_unsubdivide(BMesh *bm, const int iterations)
-{
- BM_mesh_decimate_unsubdivide_ex(bm, iterations, FALSE);
-}
diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c
index 508b3b8fcdf..caf9f3c70d5 100644
--- a/source/blender/bmesh/intern/bmesh_interp.c
+++ b/source/blender/bmesh/intern/bmesh_interp.c
@@ -174,9 +174,9 @@ void BM_face_interp_from_face(BMesh *bm, BMFace *target, BMFace *source)
void **blocks = NULL;
float (*cos)[3] = NULL, *w = NULL;
- BLI_array_fixedstack_declare(cos, BM_NGON_STACK_SIZE, source->len, __func__);
- BLI_array_fixedstack_declare(w, BM_NGON_STACK_SIZE, source->len, __func__);
- BLI_array_fixedstack_declare(blocks, BM_NGON_STACK_SIZE, source->len, __func__);
+ BLI_array_fixedstack_declare(cos, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__);
+ BLI_array_fixedstack_declare(w, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__);
+ BLI_array_fixedstack_declare(blocks, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__);
int i;
BM_elem_attrs_copy(bm, bm, source, target);
@@ -613,10 +613,10 @@ void BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source,
void **vblocks = NULL;
float (*cos)[3] = NULL, co[3], *w = NULL;
float cent[3] = {0.0f, 0.0f, 0.0f};
- BLI_array_fixedstack_declare(cos, BM_NGON_STACK_SIZE, source->len, __func__);
- BLI_array_fixedstack_declare(w, BM_NGON_STACK_SIZE, source->len, __func__);
- BLI_array_fixedstack_declare(blocks, BM_NGON_STACK_SIZE, source->len, __func__);
- BLI_array_fixedstack_declare(vblocks, BM_NGON_STACK_SIZE, do_vertex ? source->len : 0, __func__);
+ BLI_array_fixedstack_declare(cos, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__);
+ BLI_array_fixedstack_declare(w, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__);
+ BLI_array_fixedstack_declare(blocks, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__);
+ BLI_array_fixedstack_declare(vblocks, BM_DEFAULT_NGON_STACK_SIZE, do_vertex ? source->len : 0, __func__);
int i, ax, ay;
BM_elem_attrs_copy(bm, bm, source, target->f);
@@ -689,9 +689,9 @@ void BM_vert_interp_from_face(BMesh *bm, BMVert *v, BMFace *source)
void **blocks = NULL;
float (*cos)[3] = NULL, *w = NULL;
float cent[3] = {0.0f, 0.0f, 0.0f};
- BLI_array_fixedstack_declare(cos, BM_NGON_STACK_SIZE, source->len, __func__);
- BLI_array_fixedstack_declare(w, BM_NGON_STACK_SIZE, source->len, __func__);
- BLI_array_fixedstack_declare(blocks, BM_NGON_STACK_SIZE, source->len, __func__);
+ BLI_array_fixedstack_declare(cos, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__);
+ BLI_array_fixedstack_declare(w, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__);
+ BLI_array_fixedstack_declare(blocks, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__);
int i;
i = 0;
diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c
index 1cb95d94e9b..c3f33eb95e1 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.c
+++ b/source/blender/bmesh/intern/bmesh_iterators.c
@@ -116,10 +116,14 @@ int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, cons
*
* Caller needs to free the array.
*/
-void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len)
+void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len,
+ /* optional args to avoid an alloc (normally stack array) */
+ void **stack_array, int stack_array_size)
{
BMIter iter;
+ BLI_assert(stack_array_size == 0 || (stack_array_size && stack_array));
+
/* we can't rely on coun't being set */
switch (itype) {
case BM_VERTS_OF_MESH:
@@ -137,7 +141,9 @@ void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len)
if (BM_iter_init(&iter, bm, itype, data) && iter.count > 0) {
BMElem *ele;
- BMElem **array = MEM_mallocN(sizeof(ele) * iter.count, __func__);
+ BMElem **array = iter.count > stack_array_size ?
+ MEM_mallocN(sizeof(ele) * iter.count, __func__) :
+ stack_array;
int i = 0;
*r_len = iter.count; /* set before iterating */
diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h
index 3c42b3d610c..7291bca6356 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.h
+++ b/source/blender/bmesh/intern/bmesh_iterators.h
@@ -107,14 +107,14 @@ typedef struct BMIter {
BMesh *bm;
void (*begin)(struct BMIter *iter);
void *(*step)(struct BMIter *iter);
- /*
+#if 0
union {
void *p;
int i;
long l;
float f;
} filter;
- */
+#endif
int count; /* note, only some iterators set this, don't rely on it */
char itype;
} BMIter;
@@ -125,7 +125,8 @@ __attribute__((warn_unused_result))
#endif
;
int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len);
-void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len)
+void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len,
+ void **stack_array, int stack_array_size)
#ifdef __GNUC__
__attribute__((warn_unused_result))
#endif
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index d3e3bcd3556..ba5e7569c31 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -59,9 +59,45 @@ static void bm_mempool_init(BMesh *bm, const BMAllocTemplate *allocsize)
#ifdef USE_BMESH_HOLES
bm->looplistpool = BLI_mempool_create(sizeof(BMLoopList), 512, 512, 0);
#endif
+}
- /* allocate one flag pool that we don't get rid of. */
- bm->toolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), 512, 512, 0);
+void BM_mesh_elem_toolflags_ensure(BMesh *bm)
+{
+ if (bm->toolflagpool == NULL) {
+ const int totflagpool_size = max_ii(512, bm->totvert + bm->totedge + bm->totface);
+ BLI_mempool *toolflagpool;
+
+ BMIter iter;
+ BMElemF *ele;
+ const char iter_types[3] = {BM_VERTS_OF_MESH,
+ BM_EDGES_OF_MESH,
+ BM_FACES_OF_MESH};
+
+ int i;
+
+ BLI_assert(bm->totflags == 0);
+
+ /* allocate one flag pool that we don't get rid of. */
+ toolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), totflagpool_size, 512, 0);
+
+
+ for (i = 0; i < 3; i++) {
+ BM_ITER_MESH (ele, &iter, bm, iter_types[i]) {
+ ele->oflags = BLI_mempool_calloc(toolflagpool);
+ }
+ }
+
+ bm->toolflagpool = toolflagpool;
+ bm->totflags = 1;
+ }
+}
+
+void BM_mesh_elem_toolflags_clear(BMesh *bm)
+{
+ if (bm->toolflagpool) {
+ BLI_mempool_destroy(bm->toolflagpool);
+ bm->toolflagpool = NULL;
+ }
}
/**
@@ -83,7 +119,7 @@ BMesh *BM_mesh_create(BMAllocTemplate *allocsize)
/* allocate one flag pool that we don't get rid of. */
bm->stackdepth = 1;
- bm->totflags = 1;
+ bm->totflags = 0;
CustomData_reset(&bm->vdata);
CustomData_reset(&bm->edata);
@@ -143,7 +179,7 @@ void BM_mesh_data_free(BMesh *bm)
BLI_mempool_destroy(bm->fpool);
/* destroy flag pool */
- BLI_mempool_destroy(bm->toolflagpool);
+ BM_mesh_elem_toolflags_clear(bm);
#ifdef USE_BMESH_HOLES
BLI_mempool_destroy(bm->looplistpool);
diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h
index 8b6ef9aa3e0..b592f863cd1 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.h
+++ b/source/blender/bmesh/intern/bmesh_mesh.h
@@ -29,6 +29,8 @@
struct BMAllocTemplate;
+void BM_mesh_elem_toolflags_ensure(BMesh *bm);
+void BM_mesh_elem_toolflags_clear(BMesh *bm);
BMesh *BM_mesh_create(struct BMAllocTemplate *allocsize);
void BM_mesh_free(BMesh *bm);
@@ -58,4 +60,8 @@ typedef struct BMAllocTemplate {
extern BMAllocTemplate bm_mesh_allocsize_default;
extern BMAllocTemplate bm_mesh_chunksize_default;
+enum {
+ BM_MESH_CREATE_USE_TOOLFLAGS = (1 << 0)
+};
+
#endif /* __BMESH_MESH_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index 398e6bbedcf..ec07eb5d9f7 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -47,9 +47,9 @@
* "in" (e.g. edgefacein). for three-type slots, use geom.
*
* for output slots, for single-type geometry slots, use the type name plus "out",
- * (e.g. vertout), for double-type slots, use the two type names plus "out",
- * (e.g. vertfaceout), for three-type slots, use geom. note that you can also
- * use more esohteric names (e.g. skirtout) so long as the comment next to the
+ * (e.g. verts.out), for double-type slots, use the two type names plus "out",
+ * (e.g. vertfaces.out), for three-type slots, use geom. note that you can also
+ * use more esohteric names (e.g. geom_skirt.out) so long as the comment next to the
* slot definition tells you what types of elements are in it.
*
*/
@@ -82,7 +82,7 @@
* would be extracted from comments
* next to them, e.g.
*
- * {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, //output slot, boundary region
+ * {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
@@ -99,16 +99,18 @@
*/
static BMOpDefine bmo_smooth_vert_def = {
"smooth_vert",
- {{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, "clipdist"}, /* 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} /* null-terminating sentinel */,
+ /* 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 */
bmo_smooth_vert_exec,
0
};
@@ -117,18 +119,20 @@ static BMOpDefine bmo_smooth_vert_def = {
* Vertext Smooth Laplacian
* Smooths vertices by using Laplacian smoothing propose by.
* Desbrun, et al. Implicit Fairing of Irregular Meshes using Diffusion and Curvature Flow
-*/
+ */
static BMOpDefine bmo_smooth_laplacian_vert_def = {
"smooth_laplacian_vert",
- {{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, "volume_preservation"}, //Apply volume preservation after smooth
- {0} /* null-terminating sentinel */,
+ /* 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},
},
+ {{0}}, /* no output */
bmo_smooth_laplacian_vert_exec,
0
};
@@ -141,10 +145,12 @@ static BMOpDefine bmo_smooth_laplacian_vert_def = {
static BMOpDefine bmo_recalc_face_normals_def = {
"recalc_face_normals",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "faces"},
- {BMO_OP_SLOT_BOOL, "do_flip"}, /* internal flag, used by bmesh_rationalize_normals */
- {0} /* null-terminating sentinel */,
+ {BMO_OP_SLOT_BOOL, "use_flip"}, /* internal flag, used by bmesh_rationalize_normals */
+ {0},
},
+ {{0}}, /* no output */
bmo_recalc_face_normals_exec,
BMO_OP_FLAG_UNTAN_MULTIRES,
};
@@ -154,18 +160,22 @@ static BMOpDefine bmo_recalc_face_normals_def = {
*
* used to implement the select more/less tools.
* this puts some geometry surrounding regions of
- * geometry in geom into geomout.
+ * geometry in geom into geom.out.
*
- * if usefaces is 0 then geomout spits out verts and edges,
+ * if usefaces is 0 then geom.out spits out verts and edges,
* otherwise it spits out faces.
*/
static BMOpDefine bmo_region_extend_def = {
"region_extend",
- {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry */
- {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* output slot, computed boundary geometry. */
- {BMO_OP_SLOT_BOOL, "constrict"}, /* find boundary inside the regions, not outside. */
- {BMO_OP_SLOT_BOOL, "use_faces"}, /* extend from faces instead of edges */
- {0} /* null-terminating sentinel */,
+ /* 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},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* output slot, computed boundary geometry. */
+ {0},
},
bmo_region_extend_exec,
0
@@ -179,10 +189,14 @@ static BMOpDefine bmo_region_extend_def = {
*/
static BMOpDefine bmo_rotate_edges_def = {
"rotate_edges",
- {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */
- {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* newly spun edges */
- {BMO_OP_SLOT_BOOL, "ccw"}, /* rotate edge counter-clockwise if true, othewise clockwise */
- {0} /* null-terminating sentinel */,
+ /* 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},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* newly spun edges */
+ {0},
},
bmo_rotate_edges_exec,
BMO_OP_FLAG_UNTAN_MULTIRES
@@ -196,9 +210,11 @@ static BMOpDefine bmo_rotate_edges_def = {
*/
static BMOpDefine bmo_reverse_faces_def = {
"reverse_faces",
- {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */
- {0} /* null-terminating sentinel */,
+ /* slots_in */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */
+ {0},
},
+ {{0}}, /* no output */
bmo_reverse_faces_exec,
BMO_OP_FLAG_UNTAN_MULTIRES,
};
@@ -211,10 +227,14 @@ 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, "numcuts"}, /* number of cuts */
- {BMO_OP_SLOT_ELEMENT_BUF, "outsplit"}, /* newly created vertices and edges */
- {0} /* null-terminating sentinel */,
+ {BMO_OP_SLOT_INT, "cuts"}, /* number of cuts */
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "geom_split.out"}, /* newly created vertices and edges */
+ {0},
},
bmo_bisect_edges_exec,
BMO_OP_FLAG_UNTAN_MULTIRES
@@ -224,20 +244,25 @@ static BMOpDefine bmo_bisect_edges_def = {
* Mirror
*
* Mirrors geometry along an axis. The resulting geometry is welded on using
- * mergedist. Pairs of original/mirrored vertices are welded using the mergedist
+ * 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",
- {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry */
- {BMO_OP_SLOT_MAT, "mat"}, /* matrix defining the mirror transformation */
- {BMO_OP_SLOT_FLT, "mergedist"}, /* maximum distance for merging. does no merging if 0. */
- {BMO_OP_SLOT_ELEMENT_BUF, "newout"}, /* output geometry, mirrored */
- {BMO_OP_SLOT_INT, "axis"}, /* the axis to use, 0, 1, or 2 for x, y, z */
+ /* 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, /* null-terminating sentinel */}},
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* output geometry, mirrored */
+ {0},
+ },
bmo_mirror_exec,
0,
};
@@ -253,11 +278,16 @@ 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 */
- {BMO_OP_SLOT_MAPPING, "targetmapout"},
- {0, /* null-terminating sentinel */}},
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_MAPPING, "targetmap.out"},
+ {0},
+ },
bmo_find_doubles_exec,
0,
};
@@ -270,9 +300,12 @@ 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, /* null-terminating sentinel */}},
+ {0},
+ },
+ {{0}}, /* no output */
bmo_remove_doubles_exec,
BMO_OP_FLAG_UNTAN_MULTIRES,
};
@@ -286,9 +319,12 @@ static BMOpDefine bmo_remove_doubles_def = {
*/
static BMOpDefine bmo_automerge_def = {
"automerge",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input verts */
{BMO_OP_SLOT_FLT, "dist"}, /* minimum distance */
- {0, /* null-terminating sentinel */}},
+ {0},
+ },
+ {{0}}, /* no output */
bmo_automerge_exec,
BMO_OP_FLAG_UNTAN_MULTIRES,
};
@@ -300,8 +336,11 @@ static BMOpDefine bmo_automerge_def = {
*/
static BMOpDefine bmo_collapse_def = {
"collapse",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */
- {0, /* null-terminating sentinel */}},
+ {0},
+ },
+ {{0}}, /* no output */
bmo_collapse_exec,
BMO_OP_FLAG_UNTAN_MULTIRES,
};
@@ -314,9 +353,12 @@ static BMOpDefine bmo_collapse_def = {
*/
static BMOpDefine bmo_pointmerge_facedata_def = {
"pointmerge_facedata",
- {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertice */
- {BMO_OP_SLOT_ELEMENT_BUF, "snapv"}, /* snap verte */
- {0, /* null-terminating sentinel */}},
+ /* slots_in */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */
+ {BMO_OP_SLOT_ELEMENT_BUF, "snapv"}, /* snap vertex */
+ {0},
+ },
+ {{0}}, /* no output */
bmo_pointmerge_facedata_exec,
0,
};
@@ -330,8 +372,11 @@ 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, /* null-terminating sentinel */}},
+ {0},
+ },
+ {{0}}, /* no output */
bmo_average_vert_facedata_exec,
0,
};
@@ -343,9 +388,12 @@ static BMOpDefine bmo_average_vert_facedata_def = {
*/
static BMOpDefine bmo_pointmerge_def = {
"pointmerge",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertice */
{BMO_OP_SLOT_VEC, "merge_co"},
- {0, /* null-terminating sentinel */}},
+ {0},
+ },
+ {{0}}, /* no output */
bmo_pointmerge_exec,
BMO_OP_FLAG_UNTAN_MULTIRES,
};
@@ -357,8 +405,11 @@ static BMOpDefine bmo_pointmerge_def = {
*/
static BMOpDefine bmo_collapse_uvs_def = {
"collapse_uvs",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */
- {0, /* null-terminating sentinel */}},
+ {0},
+ },
+ {{0}}, /* no output */
bmo_collapse_uvs_exec,
0,
};
@@ -372,8 +423,11 @@ static BMOpDefine bmo_collapse_uvs_def = {
*/
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, /* null-terminating sentinel */}},
+ {0},
+ },
+ {{0}}, /* no output */
bmo_weld_verts_exec,
BMO_OP_FLAG_UNTAN_MULTIRES,
};
@@ -386,9 +440,14 @@ 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 */
- {BMO_OP_SLOT_ELEMENT_BUF, "newvertout"}, /* the new vert */
- {0, /* null-terminating sentinel */}},
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "vert.out"}, /* the new vert */
+ {0},
+ },
bmo_create_vert_exec,
0,
};
@@ -401,14 +460,19 @@ 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_ELEMENT_BUF, "faceout"}, /* joined faces */
{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, /* null-terminating sentinel */}},
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* joined faces */
+ {0},
+ },
bmo_join_triangles_exec,
BMO_OP_FLAG_UNTAN_MULTIRES,
};
@@ -426,13 +490,18 @@ static BMOpDefine bmo_join_triangles_def = {
*/
static BMOpDefine bmo_contextual_create_def = {
"contextual_create",
- {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry. */
- {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* newly-made face(s) */
+ /* 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},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* 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, "edgeout"}, /* newly-made edge(s) */
- {BMO_OP_SLOT_INT, "mat_nr"}, /* material to use */
- {BMO_OP_SLOT_BOOL, "use_smooth"}, /* material to use */
- {0, /* null-terminating sentinel */}},
+ {BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* newly-made edge(s) */
+ {0},
+ },
bmo_contextual_create_exec,
BMO_OP_FLAG_UNTAN_MULTIRES,
};
@@ -442,27 +511,37 @@ static BMOpDefine bmo_contextual_create_def = {
*/
static BMOpDefine bmo_bridge_loops_def = {
"bridge_loops",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */
- {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* new face */
{BMO_OP_SLOT_BOOL, "use_merge"},
{BMO_OP_SLOT_FLT, "merge_factor"},
- {0, /* null-terminating sentinel */}},
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* new faces */
+ {0},
+ },
bmo_bridge_loops_exec,
0,
};
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, "excludefaces"}, /* list of faces to ignore for manifold check */
- {BMO_OP_SLOT_MAPPING, "faceout_groupmap"}, /* maps new faces to the group numbers they came fro */
- {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* new face */
+ {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, /* null-terminating sentinel */}},
+ {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},
+ },
bmo_edgenet_fill_exec,
0,
};
@@ -479,9 +558,14 @@ static BMOpDefine bmo_edgenet_fill_def = {
*/
static BMOpDefine bmo_edgenet_prepare_def = {
"edgenet_prepare",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */
- {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* new edges */
- {0, /* null-terminating sentinel */}},
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* new edges */
+ {0},
+ },
bmo_edgenet_prepare,
0,
};
@@ -494,10 +578,13 @@ static BMOpDefine bmo_edgenet_prepare_def = {
*/
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, /* null-terminating sentinel */}},
+ {0},
+ },
+ {{0}}, /* no output */
bmo_rotate_exec,
0,
};
@@ -510,9 +597,12 @@ static BMOpDefine bmo_rotate_def = {
*/
static BMOpDefine bmo_translate_def = {
"translate",
+ /* slots_in */
{{BMO_OP_SLOT_VEC, "vec"}, /* translation offset */
{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */
- {0, /* null-terminating sentinel */}},
+ {0},
+ },
+ {{0}}, /* no output */
bmo_translate_exec,
0,
};
@@ -524,9 +614,12 @@ static BMOpDefine bmo_translate_def = {
*/
static BMOpDefine bmo_scale_def = {
"scale",
+ /* slots_in */
{{BMO_OP_SLOT_VEC, "vec"}, /* scale factor */
{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */
- {0, /* null-terminating sentinel */}},
+ {0},
+ },
+ {{0}}, /* no output */
bmo_scale_exec,
0,
};
@@ -540,9 +633,12 @@ 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, /* null-terminating sentinel */}},
+ {0},
+ },
+ {{0}}, /* no output */
bmo_transform_exec,
0,
};
@@ -555,9 +651,12 @@ 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, /* null-terminating sentinel */}},
+ {0},
+ },
+ {{0}}, /* no output */
bmo_object_load_bmesh_exec,
0,
};
@@ -570,10 +669,13 @@ static BMOpDefine bmo_object_load_bmesh_def = {
*/
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, "notessellation"}, /* don't calculate mfaces */
- {0, /* null-terminating sentinel */}},
+ {BMO_OP_SLOT_BOOL, "skip_tessface"}, /* don't calculate mfaces */
+ {0},
+ },
+ {{0}}, /* no output */
bmo_bmesh_to_mesh_exec,
0,
};
@@ -586,10 +688,13 @@ 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, "set_shapekey"}, /* load active shapekey coordinates into verts */
- {0, /* null-terminating sentinel */}},
+ {BMO_OP_SLOT_BOOL, "use_shapekey"}, /* load active shapekey coordinates into verts */
+ {0},
+ },
+ {{0}}, /* no output */
bmo_mesh_to_bmesh_exec,
0
};
@@ -601,10 +706,15 @@ static BMOpDefine bmo_mesh_to_bmesh_def = {
*/
static BMOpDefine bmo_extrude_discrete_faces_def = {
"extrude_discrete_faces",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */
- {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */
- {BMO_OP_SLOT_ELEMENT_BUF, "skirtout"}, /* output skirt geometry, faces and edges */
- {0} /* null-terminating sentinel */},
+ {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},
+ },
bmo_extrude_discrete_faces_exec,
0
};
@@ -617,9 +727,14 @@ 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 */
- {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* output geometry */
- {0} /* null-terminating sentinel */},
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* output geometry */
+ {0},
+ },
bmo_extrude_edge_only_exec,
0
};
@@ -631,125 +746,171 @@ static BMOpDefine bmo_extrude_edge_only_def = {
*/
static BMOpDefine bmo_extrude_vert_indiv_def = {
"extrude_vert_indiv",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */
- {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* output wire edges */
- {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output vertices */
- {0} /* null-terminating sentinel */},
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* output wire edges */
+ {BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output vertices */
+ {0},
+ },
bmo_extrude_vert_indiv_exec,
0
};
static BMOpDefine bmo_connect_verts_def = {
"connect_verts",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "verts"},
- {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"},
- {0} /* null-terminating sentinel */},
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"},
+ {0},
+ },
bmo_connect_verts_exec,
BMO_OP_FLAG_UNTAN_MULTIRES
};
static BMOpDefine bmo_extrude_face_region_def = {
"extrude_face_region",
- {{BMO_OP_SLOT_ELEMENT_BUF, "edgefacein"},
- {BMO_OP_SLOT_MAPPING, "exclude"},
- {BMO_OP_SLOT_BOOL, "alwayskeeporig"},
- {BMO_OP_SLOT_ELEMENT_BUF, "geomout"},
- {0} /* null-terminating sentinel */},
+ /* 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},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"},
+ {0},
+ },
bmo_extrude_face_region_exec,
0
};
static BMOpDefine bmo_dissolve_verts_def = {
"dissolve_verts",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "verts"},
- {0} /* null-terminating sentinel */},
+ {0},
+ },
+ {{0}}, /* no output */
bmo_dissolve_verts_exec,
BMO_OP_FLAG_UNTAN_MULTIRES
};
static BMOpDefine bmo_dissolve_edges_def = {
"dissolve_edges",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "edges"},
- {BMO_OP_SLOT_ELEMENT_BUF, "regionout"},
{BMO_OP_SLOT_BOOL, "use_verts"}, /* dissolve verts left between only 2 edges. */
- {0} /* null-terminating sentinel */},
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "region.out"},
+ {0},
+ },
bmo_dissolve_edges_exec,
BMO_OP_FLAG_UNTAN_MULTIRES
};
static BMOpDefine bmo_dissolve_edge_loop_def = {
"dissolve_edge_loop",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "edges"},
- {BMO_OP_SLOT_ELEMENT_BUF, "regionout"},
- {0} /* null-terminating sentinel */},
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "region.out"},
+ {0},
+ },
bmo_dissolve_edgeloop_exec,
BMO_OP_FLAG_UNTAN_MULTIRES
};
static BMOpDefine bmo_dissolve_faces_def = {
"dissolve_faces",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "faces"},
- {BMO_OP_SLOT_ELEMENT_BUF, "regionout"},
{BMO_OP_SLOT_BOOL, "use_verts"}, /* dissolve verts left between only 2 edges. */
- {0} /* null-terminating sentinel */},
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "region.out"},
+ {0},
+ },
bmo_dissolve_faces_exec,
BMO_OP_FLAG_UNTAN_MULTIRES
};
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} /* null-terminating sentinel */},
+ {0},
+ },
+ {{0}}, /* no output */
bmo_dissolve_limit_exec,
BMO_OP_FLAG_UNTAN_MULTIRES
};
static BMOpDefine bmo_triangulate_def = {
"triangulate",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "faces"},
- {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"},
- {BMO_OP_SLOT_ELEMENT_BUF, "faceout"},
- {BMO_OP_SLOT_MAPPING, "facemap"},
{BMO_OP_SLOT_BOOL, "use_beauty"},
- {0} /* null-terminating sentinel */},
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"},
+ {BMO_OP_SLOT_ELEMENT_BUF, "faces.out"},
+ {BMO_OP_SLOT_MAPPING, "facemap.out"},
+ {0},
+ },
bmo_triangulate_exec,
BMO_OP_FLAG_UNTAN_MULTIRES
};
static BMOpDefine bmo_unsubdivide_def = {
"unsubdivide",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */
{BMO_OP_SLOT_INT, "iterations"},
- {0} /* null-terminating sentinel */},
+ {0},
+ },
+ {{0}}, /* no output */
bmo_unsubdivide_exec,
BMO_OP_FLAG_UNTAN_MULTIRES
};
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, "numcuts"},
+ {BMO_OP_SLOT_INT, "cuts"},
{BMO_OP_SLOT_INT, "seed"},
{BMO_OP_SLOT_MAPPING, "custompatterns"},
{BMO_OP_SLOT_MAPPING, "edgepercents"},
- /* these next three can have multiple types of elements in them */
- {BMO_OP_SLOT_ELEMENT_BUF, "outinner"},
- {BMO_OP_SLOT_ELEMENT_BUF, "outsplit"},
- {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* contains all output geometr */
-
- {BMO_OP_SLOT_INT, "quadcornertype"}, /* quad corner type, see bmesh_operators.h */
+ {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} /* null-terminating sentinel */,
+ {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},
},
bmo_subdivide_edges_exec,
BMO_OP_FLAG_UNTAN_MULTIRES
@@ -757,38 +918,51 @@ static BMOpDefine bmo_subdivide_edges_def = {
static BMOpDefine bmo_delete_def = {
"delete",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "geom"},
{BMO_OP_SLOT_INT, "context"},
- {0} /* null-terminating sentinel */},
+ {0},
+ },
+ {{0}}, /* no output */
bmo_delete_exec,
0
};
static BMOpDefine bmo_duplicate_def = {
"duplicate",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "geom"},
- {BMO_OP_SLOT_ELEMENT_BUF, "origout"},
- {BMO_OP_SLOT_ELEMENT_BUF, "newout"},
+ {BMO_OP_SLOT_PTR, "dest"}, /* destination bmesh, if NULL will use current on */
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "geom_orig.out"},
+ {BMO_OP_SLOT_ELEMENT_BUF, "geom.out"},
/* facemap maps from source faces to dupe
* faces, and from dupe faces to source faces */
- {BMO_OP_SLOT_MAPPING, "facemap"},
- {BMO_OP_SLOT_MAPPING, "boundarymap"},
- {BMO_OP_SLOT_MAPPING, "isovertmap"},
- {BMO_OP_SLOT_PTR, "dest"}, /* destination bmesh, if NULL will use current on */
- {0} /* null-terminating sentinel */},
+ {BMO_OP_SLOT_MAPPING, "facemap.out"},
+ {BMO_OP_SLOT_MAPPING, "boundarymap.out"},
+ {BMO_OP_SLOT_MAPPING, "isovertmap.out"},
+ {0},
+ },
bmo_duplicate_exec,
0
};
static BMOpDefine bmo_split_def = {
"split",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "geom"},
- {BMO_OP_SLOT_ELEMENT_BUF, "geomout"},
- {BMO_OP_SLOT_MAPPING, "boundarymap"},
- {BMO_OP_SLOT_MAPPING, "isovertmap"},
- {BMO_OP_SLOT_PTR, "dest"}, /* destination bmesh, if NULL will use current on */
- {BMO_OP_SLOT_BOOL, "use_only_faces"}, /* when enabled. don't duplicate loose verts/edges */
- {0} /* null-terminating sentinel */},
+ {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},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"},
+ {BMO_OP_SLOT_MAPPING, "boundarymap.out"},
+ {BMO_OP_SLOT_MAPPING, "isovertmap.out"},
+ {0},
+ },
bmo_split_exec,
0
};
@@ -801,15 +975,20 @@ static BMOpDefine bmo_split_def = {
*/
static BMOpDefine bmo_spin_def = {
"spin",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "geom"},
- {BMO_OP_SLOT_ELEMENT_BUF, "lastout"}, /* result of last step */
- {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, "ang"}, /* total rotation angle (degrees) */
- {BMO_OP_SLOT_INT, "steps"}, /* number of steps */
- {BMO_OP_SLOT_BOOL, "do_dupli"}, /* duplicate or extrude? */
- {0} /* null-terminating sentinel */},
+ {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},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "geom_last.out"}, /* result of last step */
+ {0},
+ },
bmo_spin_exec,
0
};
@@ -822,12 +1001,17 @@ static BMOpDefine bmo_spin_def = {
*/
static BMOpDefine bmo_similar_faces_def = {
"similar_faces",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */
- {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output 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} /* null-terminating sentinel */},
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* output faces */
+ {0},
+ },
bmo_similar_faces_exec,
0
};
@@ -839,12 +1023,17 @@ static BMOpDefine bmo_similar_faces_def = {
*/
static BMOpDefine bmo_similar_edges_def = {
"similar_edges",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */
- {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* output 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} /* null-terminating sentinel */},
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* output edges */
+ {0},
+ },
bmo_similar_edges_exec,
0
};
@@ -856,12 +1045,17 @@ static BMOpDefine bmo_similar_edges_def = {
*/
static BMOpDefine bmo_similar_verts_def = {
"similar_verts",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */
- {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output 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} /* null-terminating sentinel */},
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output vertices */
+ {0},
+ },
bmo_similar_verts_exec,
0
};
@@ -872,9 +1066,13 @@ static BMOpDefine bmo_similar_verts_def = {
*/
static BMOpDefine bmo_rotate_uvs_def = {
"rotate_uvs",
- {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */
- {BMO_OP_SLOT_INT, "dir"}, /* direction */
- {0} /* null-terminating sentinel */},
+ /* slots_in */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */
+ {BMO_OP_SLOT_BOOL, "use_ccw"}, /* rotate counter-clockwise if true, othewise clockwise */
+ {0},
+ },
+ /* slots_out */
+ {{0}}, /* no output */
bmo_rotate_uvs_exec,
0
};
@@ -885,8 +1083,11 @@ static BMOpDefine bmo_rotate_uvs_def = {
*/
static BMOpDefine bmo_reverse_uvs_def = {
"reverse_uvs",
- {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */
- {0} /* null-terminating sentinel */},
+ /* slots_in */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */
+ {0},
+ },
+ {{0}}, /* no output */
bmo_reverse_uvs_exec,
0
};
@@ -897,9 +1098,12 @@ static BMOpDefine bmo_reverse_uvs_def = {
*/
static BMOpDefine bmo_rotate_colors_def = {
"rotate_colors",
- {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */
- {BMO_OP_SLOT_INT, "dir"}, /* direction */
- {0} /* null-terminating sentinel */},
+ /* slots_in */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */
+ {BMO_OP_SLOT_BOOL, "use_ccw"}, /* rotate counter-clockwise if true, othewise clockwise */
+ {0},
+ },
+ {{0}}, /* no output */
bmo_rotate_colors_exec,
0
};
@@ -910,8 +1114,11 @@ static BMOpDefine bmo_rotate_colors_def = {
*/
static BMOpDefine bmo_reverse_colors_def = {
"reverse_colors",
- {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */
- {0} /* null-terminating sentinel */},
+ /* slots_in */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */
+ {0},
+ },
+ {{0}}, /* no output */
bmo_reverse_colors_exec,
0
};
@@ -923,11 +1130,16 @@ static BMOpDefine bmo_reverse_colors_def = {
*/
static BMOpDefine bmo_shortest_path_def = {
"shortest_path",
- {{BMO_OP_SLOT_ELEMENT_BUF, "startv"}, /* start vertex */
- {BMO_OP_SLOT_ELEMENT_BUF, "endv"}, /* end vertex */
- {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output vertices */
- {BMO_OP_SLOT_INT, "type"}, /* type of selection */
- {0} /* null-terminating sentinel */},
+ /* 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},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output vertices */
+ {0},
+ },
bmo_shortest_path_exec,
0
};
@@ -939,12 +1151,17 @@ static BMOpDefine bmo_shortest_path_def = {
*/
static BMOpDefine bmo_split_edges_def = {
"split_edges",
- {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */
- {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* old output disconnected edges */
+ /* slots_in */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* 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_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} /* null-terminating sentinel */},
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* old output disconnected edges */
+ {0},
+ },
bmo_split_edges_exec,
BMO_OP_FLAG_UNTAN_MULTIRES
};
@@ -956,12 +1173,17 @@ static BMOpDefine bmo_split_edges_def = {
*/
static BMOpDefine bmo_create_grid_def = {
"create_grid",
- {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */
- {BMO_OP_SLOT_INT, "xsegments"}, /* number of x segments */
- {BMO_OP_SLOT_INT, "ysegments"}, /* 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, /* null-terminating sentinel */}},
+ /* 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},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */
+ {0},
+ },
bmo_create_grid_exec,
0,
};
@@ -973,12 +1195,17 @@ static BMOpDefine bmo_create_grid_def = {
*/
static BMOpDefine bmo_create_uvsphere_def = {
"create_uvsphere",
- {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */
- {BMO_OP_SLOT_INT, "segments"}, /* number of u segments */
- {BMO_OP_SLOT_INT, "revolutions"}, /* number of v segment */
+ /* 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, /* null-terminating sentinel */}},
+ {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */
+ {0},
+ },
bmo_create_uvsphere_exec,
0,
};
@@ -990,11 +1217,16 @@ static BMOpDefine bmo_create_uvsphere_def = {
*/
static BMOpDefine bmo_create_icosphere_def = {
"create_icosphere",
- {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */
- {BMO_OP_SLOT_INT, "subdivisions"}, /* how many times to recursively subdivide the sphere */
+ /* 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, /* null-terminating sentinel */}},
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */
+ {0},
+ },
bmo_create_icosphere_exec,
0,
};
@@ -1006,9 +1238,14 @@ static BMOpDefine bmo_create_icosphere_def = {
*/
static BMOpDefine bmo_create_monkey_def = {
"create_monkey",
- {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */
- {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with-- */
- {0, /* null-terminating sentinel */}},
+ /* slots_in */
+ {{BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */
+ {0},
+ },
bmo_create_monkey_exec,
0,
};
@@ -1020,15 +1257,20 @@ static BMOpDefine bmo_create_monkey_def = {
*/
static BMOpDefine bmo_create_cone_def = {
"create_cone",
- {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */
- {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 */
+ /* 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, /* null-terminating sentinel */}},
+ {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},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */
+ {0},
+ },
bmo_create_cone_exec,
0,
};
@@ -1038,13 +1280,18 @@ static BMOpDefine bmo_create_cone_def = {
*/
static BMOpDefine bmo_create_circle_def = {
"create_circle",
- {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */
- {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 */
+ /* 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, /* null-terminating sentinel */}},
+ {BMO_OP_SLOT_FLT, "diameter"}, /* diameter of one end */
+ {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */
+ {0},
+ },
bmo_create_circle_exec,
0,
};
@@ -1056,15 +1303,19 @@ static BMOpDefine bmo_create_circle_def = {
*/
static BMOpDefine bmo_create_cube_def = {
"create_cube",
- {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */
- {BMO_OP_SLOT_FLT, "size"}, /* size of the cube */
- {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with-- */
- {0, /* null-terminating sentinel */}},
+ /* slots_in */
+ {{BMO_OP_SLOT_FLT, "size"}, /* size of the cube */
+ {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */
+ {0},
+ },
bmo_create_cube_exec,
0,
};
-#define NEW_BEVEL 1
/*
* Bevel
*
@@ -1072,12 +1323,17 @@ static BMOpDefine bmo_create_cube_def = {
*/
static BMOpDefine bmo_bevel_def = {
"bevel",
-#ifdef NEW_BEVEL
- {{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} /* null-terminating sentinel */},
-#else
+ /* 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},
+ },
+ /* 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 */
@@ -1087,7 +1343,8 @@ static BMOpDefine bmo_bevel_def = {
* 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} /* null-terminating sentinel */},
+ {0},
+ },
#endif
bmo_bevel_exec,
BMO_OP_FLAG_UNTAN_MULTIRES
@@ -1100,10 +1357,15 @@ static BMOpDefine bmo_bevel_def = {
*/
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 */
- {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* new flipped faces and edges */
- {0} /* null-terminating sentinel */},
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* new flipped faces and edges */
+ {0},
+ },
bmo_beautify_fill_exec,
BMO_OP_FLAG_UNTAN_MULTIRES
};
@@ -1115,9 +1377,14 @@ static BMOpDefine bmo_beautify_fill_def = {
*/
static BMOpDefine bmo_triangle_fill_def = {
"triangle_fill",
- {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */
- {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* new faces and edges */
- {0} /* null-terminating sentinel */},
+ /* slots_in */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* new faces and edges */
+ {0},
+ },
bmo_triangle_fill_exec,
BMO_OP_FLAG_UNTAN_MULTIRES
};
@@ -1129,10 +1396,15 @@ static BMOpDefine bmo_triangle_fill_def = {
*/
static BMOpDefine bmo_solidify_def = {
"solidify",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "geom"},
{BMO_OP_SLOT_FLT, "thickness"},
- {BMO_OP_SLOT_ELEMENT_BUF, "geomout"},
- {0}},
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"},
+ {0},
+ },
bmo_solidify_face_region_exec,
0
};
@@ -1144,15 +1416,20 @@ static BMOpDefine bmo_solidify_def = {
*/
static BMOpDefine bmo_inset_def = {
"inset",
- {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */
- {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */
+ /* 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} /* null-terminating sentinel */},
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* output faces */
+ {0},
+ },
bmo_inset_exec,
0
};
@@ -1164,15 +1441,20 @@ static BMOpDefine bmo_inset_def = {
*/
static BMOpDefine bmo_wireframe_def = {
"wireframe",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */
- {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output 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} /* null-terminating sentinel */},
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* output faces */
+ {0},
+ },
bmo_wireframe_exec,
0
};
@@ -1184,11 +1466,16 @@ static BMOpDefine bmo_wireframe_def = {
*/
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_ELEMENT_BUF, "vertout"},
{BMO_OP_SLOT_FLT, "distance_t"},
- {0} /* null-terminating sentinel */},
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"},
+ {0},
+ },
bmo_slide_vert_exec,
BMO_OP_FLAG_UNTAN_MULTIRES
};
@@ -1202,7 +1489,7 @@ static BMOpDefine bmo_slide_vert_def = {
* If 'use_existing_faces' is true, the hull will not output triangles
* that are covered by a pre-existing face.
*
- * All hull vertices, faces, and edges are added to 'geomout'. Any
+ * All hull vertices, faces, and edges are added to 'geom.out'. Any
* input elements that end up inside the hull (i.e. are not used by an
* output face) are added to the 'interior_geom' slot. The
* 'unused_geom' slot will contain all interior geometry that is
@@ -1211,15 +1498,18 @@ 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"},
-
- /* Outputs */
- {BMO_OP_SLOT_ELEMENT_BUF, "geomout"},
- {BMO_OP_SLOT_ELEMENT_BUF, "interior_geom"},
- {BMO_OP_SLOT_ELEMENT_BUF, "unused_geom"},
- {BMO_OP_SLOT_ELEMENT_BUF, "holes_geom"},
- {0} /* null-terminating sentinel */},
+ {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},
+ },
bmo_convex_hull_exec,
0
};
@@ -1233,17 +1523,19 @@ static BMOpDefine bmo_convex_hull_def = {
* the "direction" slot. The edges and faces that cross the plane of
* symmetry are split as needed to enforce symmetry.
*
- * All new vertices, edges, and faces are added to the "geomout" slot.
+ * All new vertices, edges, and faces are added to the "geom.out" slot.
*/
static BMOpDefine bmo_symmetrize_def = {
"symmetrize",
+ /* slots_in */
{{BMO_OP_SLOT_ELEMENT_BUF, "input"},
{BMO_OP_SLOT_INT, "direction"},
-
- /* Outputs */
- {BMO_OP_SLOT_ELEMENT_BUF, "geomout"},
-
- {0} /* null-terminating sentinel */},
+ {0},
+ },
+ /* slots_out */
+ {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"},
+ {0},
+ },
bmo_symmetrize_exec,
0
};
diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h
index 671cfbbc55e..b87e023e63a 100644
--- a/source/blender/bmesh/intern/bmesh_operator_api.h
+++ b/source/blender/bmesh/intern/bmesh_operator_api.h
@@ -116,30 +116,45 @@ enum {
* for when your defining an operator with BMOpDefine.*/
typedef struct BMOpSlot {
+ const char *slot_name; /* pointer to BMOpDefine.slot_args */
int slot_type;
int len;
- int flag;
- int index; /* index within slot array */
+// int flag; /* UNUSED */
+// int index; /* index within slot array */ /* UNUSED */
union {
int i;
float f;
void *p;
float vec[3];
- void *buf;
+ void **buf;
GHash *ghash;
} data;
} BMOpSlot;
-#define BMO_OP_MAX_SLOTS 16 /* way more than probably needed */
+/* mainly for use outside bmesh internal code */
+#define BMO_SLOT_AS_BOOL(slot) ((slot)->data.i)
+#define BMO_SLOT_AS_INT(slot) ((slot)->data.i)
+#define BMO_SLOT_AS_FLOAT(slot) ((slot)->data.f)
+#define BMO_SLOT_AS_VECTOR(slot) ((slot)->data.vec)
+#define BMO_SLOT_AS_MATRIX(slot ) ((float (*)[4])((slot)->data.p))
+#define BMO_SLOT_AS_BUFFER(slot ) ((slot)->data.buf)
+#define BMO_SLOT_AS_GHASH(slot ) ((slot)->data.ghash)
+
+#define BMO_ASSERT_SLOT_IN_OP(slot, op) \
+ BLI_assert(((slot >= (op)->slots_in) && (slot < &(op)->slots_in[BMO_OP_MAX_SLOTS])) || \
+ ((slot >= (op)->slots_out) && (slot < &(op)->slots_out[BMO_OP_MAX_SLOTS])))
+
+/* way more than probably needed, compiler complains if limit hit */
+#define BMO_OP_MAX_SLOTS 16
typedef struct BMOperator {
+ struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS];
+ struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS];
+ void (*exec)(BMesh *bm, struct BMOperator *op);
+ struct MemArena *arena;
int type;
- int slot_type;
int type_flag;
int flag; /* runtime options */
- struct BMOpSlot slot_args[BMO_OP_MAX_SLOTS];
- void (*exec)(BMesh *bm, struct BMOperator *op);
- struct MemArena *arena;
} BMOperator;
enum {
@@ -156,8 +171,9 @@ typedef struct BMOSlotType {
} BMOSlotType;
typedef struct BMOpDefine {
- const char *name;
- BMOSlotType slot_types[BMO_OP_MAX_SLOTS];
+ const char *opname;
+ BMOSlotType slot_types_in[BMO_OP_MAX_SLOTS];
+ BMOSlotType slot_types_out[BMO_OP_MAX_SLOTS];
void (*exec)(BMesh *bm, BMOperator *op);
int type_flag;
} BMOpDefine;
@@ -245,15 +261,22 @@ int BMO_op_initf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, ...
int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, va_list vlist);
/* test whether a named slot exists */
-int BMO_slot_exists(BMOperator *op, const char *slot_name);
+int BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier);
/* get a pointer to a slot. this may be removed layer on from the public API. */
-BMOpSlot *BMO_slot_get(BMOperator *op, const char *slot_name);
+BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier);
/* copies the data of a slot from one operator to another. src and dst are the
* source/destination slot codes, respectively. */
-void BMO_slot_copy(BMOperator *source_op, BMOperator *dest_op,
- const char *src, const char *dst);
+#define BMO_slot_copy(op_src, slots_src, slot_name_src, \
+ op_dst, slots_dst, slot_name_dst) \
+ _bmo_slot_copy((op_src)->slots_src, slot_name_src, \
+ (op_dst)->slots_dst, slot_name_dst, \
+ (op_dst)->arena)
+
+void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
+ BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
+ struct MemArena *arena_dst);
/* del "context" slot values, used for operator too */
enum {
@@ -279,13 +302,13 @@ typedef enum {
void BMO_op_flag_enable(BMesh *bm, BMOperator *op, const int op_flag);
void BMO_op_flag_disable(BMesh *bm, BMOperator *op, const int op_flag);
-void BMO_slot_float_set(BMOperator *op, const char *slot_name, const float f);
-float BMO_slot_float_get(BMOperator *op, const char *slot_name);
-void BMO_slot_int_set(BMOperator *op, const char *slot_name, const int i);
-int BMO_slot_int_get(BMOperator *op, const char *slot_name);
-void BMO_slot_bool_set(BMOperator *op, const char *slot_name, const int i);
-int BMO_slot_bool_get(BMOperator *op, const char *slot_name);
-void *BMO_slot_as_arrayN(BMOperator *op, const char *slot_name, int *len);
+void BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float f);
+float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
+void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i);
+int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
+void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i);
+int BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
+void *BMO_slot_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int *len);
/* don't pass in arrays that are supposed to map to elements this way.
@@ -293,69 +316,81 @@ void *BMO_slot_as_arrayN(BMOperator *op, const char *slot_name, int *len);
* so, e.g. passing in list of floats per element in another slot is bad.
* passing in, e.g. pointer to an editmesh for the conversion operator is fine
* though. */
-void BMO_slot_ptr_set(BMOperator *op, const char *slot_name, void *p);
-void *BMO_slot_ptr_get(BMOperator *op, const char *slot_name);
-void BMO_slot_vec_set(BMOperator *op, const char *slot_name, const float vec[3]);
-void BMO_slot_vec_get(BMOperator *op, const char *slot_name, float r_vec[3]);
+void BMO_slot_ptr_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, void *p);
+void *BMO_slot_ptr_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
+void BMO_slot_vec_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float vec[3]);
+void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_vec[3]);
/* only supports square mats */
/* size must be 3 or 4; this api is meant only for transformation matrices.
* note that internally the matrix is stored in 4x4 form, and it's safe to
* call whichever BMO_Get_MatXXX function you want. */
-void BMO_slot_mat_set(BMOperator *op, const char *slot_name, const float *mat, int size);
-void BMO_slot_mat4_get(BMOperator *op, const char *slot_name, float r_mat[4][4]);
-void BMO_slot_mat3_set(BMOperator *op, const char *slot_name, float r_mat[3][3]);
+void BMO_slot_mat_set(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float *mat, int size);
+void BMO_slot_mat4_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[4][4]);
+void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[3][3]);
void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *op, const char htype, const short oflag);
/* copies the values from another slot to the end of the output slot */
-void BMO_slot_buffer_append(BMOperator *output_op, const char *output_op_slot,
- BMOperator *other_op, const char *other_op_slot);
+#define BMO_slot_buffer_append(op_src, slots_src, slot_name_src, \
+ op_dst, slots_dst, slot_name_dst) \
+ _bmo_slot_buffer_append((op_src)->slots_src, slot_name_src, \
+ (op_dst)->slots_dst, slot_name_dst, \
+ (op_dst)->arena)
+void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
+ BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
+ struct MemArena *arena_dst);
/* puts every element of type 'type' (which is a bitmask) with tool
* flag 'flag', into a slot. */
-void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, const char *slot_name,
+void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
const char htype, const short oflag);
/* puts every element of type 'type' (which is a bitmask) without tool
* flag 'flag', into a slot. */
-void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, const char *slot_name,
+void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
const char htype, const short oflag);
/* tool-flags all elements inside an element slot array with flag flag. */
-void BMO_slot_buffer_flag_enable(BMesh *bm, BMOperator *op, const char *slot_name,
+void BMO_slot_buffer_flag_enable(BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
const char htype, const short oflag);
/* clears tool-flag flag from all elements inside a slot array. */
-void BMO_slot_buffer_flag_disable(BMesh *bm, BMOperator *op, const char *slot_name,
+void BMO_slot_buffer_flag_disable(BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
const char htype, const short oflag);
/* tool-flags all elements inside an element slot array with flag flag. */
-void BMO_slot_buffer_hflag_enable(BMesh *bm, BMOperator *op, const char *slot_name,
+void BMO_slot_buffer_hflag_enable(BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
const char htype, const char hflag, const char do_flush);
/* clears tool-flag flag from all elements inside a slot array. */
-void BMO_slot_buffer_hflag_disable(BMesh *bm, BMOperator *op, const char *slot_name,
+void BMO_slot_buffer_hflag_disable(BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
const char htype, const char hflag, const char do_flush);
/* puts every element of type 'type' (which is a bitmask) with header
* flag 'flag', into a slot. note: ignores hidden elements
* (e.g. elements with header flag BM_ELEM_HIDDEN set).*/
void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op,
- const char *slot_name,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
const char htype, const char hflag);
/* puts every element of type 'type' (which is a bitmask) without
* header flag 'flag', into a slot. note: ignores hidden elements
* (e.g. elements with header flag BM_ELEM_HIDDEN set).*/
void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op,
- const char *slot_name,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
const char htype, const char hflag);
/* counts number of elements inside a slot array. */
-int BMO_slot_buffer_count(BMesh *bm, BMOperator *op, const char *slot_name);
-int BMO_slot_map_count(BMesh *bm, BMOperator *op, const char *slot_name);
+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(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name,
- void *element, void *data, int len);
+void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot,
+ const void *element, void *data, int len);
/* Counts the number of edges with tool flag toolflag around
*/
@@ -363,13 +398,14 @@ int BMO_vert_edge_flags_count(BMesh *bm, BMVert *v, const short oflag);
/* flags all elements in a mapping. note that the mapping must only have
* bmesh elements in it.*/
-void BMO_slot_map_to_flag(BMesh *bm, BMOperator *op, const char *slot_name,
- const char hflag, const short oflag);
+void BMO_slot_map_to_flag(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name, const char hflag, const short oflag);
-void *BMO_slot_buffer_alloc(BMOperator *op, const char *slot_name, const int len);
+void *BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name, const int len);
-void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, const char *slot_name,
- const char htype);
+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
* mapping slots.
@@ -412,10 +448,11 @@ typedef struct BMOIter {
char restrictmask; /* bitwise '&' with BMHeader.htype */
} BMOIter;
-void *BMO_slot_buffer_elem_first(BMOperator *op, const char *slot_name);
+void *BMO_slot_buffer_elem_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
-void *BMO_iter_new(BMOIter *iter, BMesh *bm, BMOperator *op,
- const char *slot_name, const char restrictmask);
+void *BMO_iter_new(BMOIter *iter,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char restrictmask);
void *BMO_iter_step(BMOIter *iter);
/* returns a pointer to the key value when iterating over mappings.
@@ -428,8 +465,8 @@ void *BMO_iter_map_value_p(BMOIter *iter);
/* use this for float mappings */
float BMO_iter_map_value_f(BMOIter *iter);
-#define BMO_ITER(ele, iter, bm, op, slot_name, restrict) \
- for (ele = BMO_iter_new(iter, bm, op, slot_name, restrict); ele; ele = BMO_iter_step(iter))
+#define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag) \
+ for (ele = BMO_iter_new(iter, slot_args, slot_name, restrict_flag); ele; ele = BMO_iter_step(iter))
/******************* Inlined Functions********************/
typedef void (*opexec)(BMesh *bm, BMOperator *op);
diff --git a/source/blender/bmesh/intern/bmesh_operator_api_inline.h b/source/blender/bmesh/intern/bmesh_operator_api_inline.h
index 16c2b8b0505..b405ecc1841 100644
--- a/source/blender/bmesh/intern/bmesh_operator_api_inline.h
+++ b/source/blender/bmesh/intern/bmesh_operator_api_inline.h
@@ -69,16 +69,16 @@ BLI_INLINE void _bmo_elem_flag_toggle(BMesh *bm, BMFlagLayer *oflags, const shor
oflags[bm->stackdepth - 1].f ^= oflag;
}
-BLI_INLINE void BMO_slot_map_int_insert(BMesh *bm, BMOperator *op, const char *slot_name,
+BLI_INLINE void BMO_slot_map_int_insert(BMOperator *op, BMOpSlot *slot,
void *element, int val)
{
- BMO_slot_map_insert(bm, op, slot_name, element, &val, sizeof(int));
+ BMO_slot_map_insert(op, slot, element, &val, sizeof(int));
}
-BLI_INLINE void BMO_slot_map_float_insert(BMesh *bm, BMOperator *op, const char *slot_name,
+BLI_INLINE void BMO_slot_map_float_insert(BMOperator *op, BMOpSlot *slot,
void *element, float val)
{
- BMO_slot_map_insert(bm, op, slot_name, element, &val, sizeof(float));
+ BMO_slot_map_insert(op, slot, element, &val, sizeof(float));
}
@@ -87,62 +87,62 @@ BLI_INLINE void BMO_slot_map_float_insert(BMesh *bm, BMOperator *op, const char
* do NOT use these for non-operator-api-allocated memory! instead
* use BMO_slot_map_data_get and BMO_slot_map_insert, which copies the data. */
-BLI_INLINE void BMO_slot_map_ptr_insert(BMesh *bm, BMOperator *op, const char *slot_name,
- void *element, void *val)
+BLI_INLINE void BMO_slot_map_ptr_insert(BMOperator *op, BMOpSlot *slot,
+ const void *element, void *val)
{
- BMO_slot_map_insert(bm, op, slot_name, element, &val, sizeof(void *));
+ BMO_slot_map_insert(op, slot, element, &val, sizeof(void *));
}
-BLI_INLINE int BMO_slot_map_contains(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name, void *element)
+BLI_INLINE int BMO_slot_map_contains(BMOpSlot *slot, const void *element)
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING);
/* sanity check */
- if (!slot->data.ghash) return 0;
+ if (UNLIKELY(slot->data.ghash == NULL)) {
+ return 0;
+ }
return BLI_ghash_haskey(slot->data.ghash, element);
}
-BLI_INLINE void *BMO_slot_map_data_get(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name,
- void *element)
+BLI_INLINE void *BMO_slot_map_data_get(BMOpSlot *slot, const void *element)
{
BMOElemMapping *mapping;
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING);
/* sanity check */
- if (!slot->data.ghash) return NULL;
+ if (UNLIKELY(slot->data.ghash == NULL)) {
+ return NULL;
+ }
mapping = (BMOElemMapping *)BLI_ghash_lookup(slot->data.ghash, element);
- if (!mapping) return NULL;
+ if (!mapping) {
+ return NULL;
+ }
return mapping + 1;
}
-BLI_INLINE float BMO_slot_map_float_get(BMesh *bm, BMOperator *op, const char *slot_name,
- void *element)
+BLI_INLINE float BMO_slot_map_float_get(BMOpSlot *slot, const void *element)
{
- float *val = (float *) BMO_slot_map_data_get(bm, op, slot_name, element);
+ float *val = (float *) BMO_slot_map_data_get(slot, element);
if (val) return *val;
return 0.0f;
}
-BLI_INLINE int BMO_slot_map_int_get(BMesh *bm, BMOperator *op, const char *slot_name,
- void *element)
+BLI_INLINE int BMO_slot_map_int_get(BMOpSlot *slot, const void *element)
{
- int *val = (int *) BMO_slot_map_data_get(bm, op, slot_name, element);
+ int *val = (int *) BMO_slot_map_data_get(slot, element);
if (val) return *val;
return 0;
}
-BLI_INLINE void *BMO_slot_map_ptr_get(BMesh *bm, BMOperator *op, const char *slot_name,
- void *element)
+BLI_INLINE void *BMO_slot_map_ptr_get(BMOpSlot *slot, const void *element)
{
- void **val = (void **) BMO_slot_map_data_get(bm, op, slot_name, element);
+ void **val = (void **) BMO_slot_map_data_get(slot, element);
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 9d1054dc042..157837a13c0 100644
--- a/source/blender/bmesh/intern/bmesh_operators.c
+++ b/source/blender/bmesh/intern/bmesh_operators.c
@@ -45,8 +45,8 @@
static void bmo_flag_layer_alloc(BMesh *bm);
static void bmo_flag_layer_free(BMesh *bm);
static void bmo_flag_layer_clear(BMesh *bm);
-static int bmo_name_to_slotcode(BMOpDefine *def, const char *name);
-static int bmo_name_to_slotcode_check(BMOpDefine *def, const char *name);
+static int bmo_name_to_slotcode(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier);
+static int bmo_name_to_slotcode_check(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier);
static int bmo_opname_to_opcode(const char *opname);
static const char *bmo_error_messages[] = {
@@ -80,7 +80,7 @@ const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES] = {
};
/* Dummy slot so there is something to return when slot name lookup fails */
-static BMOpSlot BMOpEmptySlot = {0};
+// static BMOpSlot BMOpEmptySlot = {0};
void BMO_op_flag_enable(BMesh *UNUSED(bm), BMOperator *op, const int op_flag)
{
@@ -101,6 +101,8 @@ void BMO_push(BMesh *bm, BMOperator *UNUSED(op))
{
bm->stackdepth++;
+ BLI_assert(bm->totflags > 0);
+
/* add flag layer, if appropriate */
if (bm->stackdepth > 1)
bmo_flag_layer_alloc(bm);
@@ -123,6 +125,18 @@ void BMO_pop(BMesh *bm)
bm->stackdepth--;
}
+
+/* use for both slot_types_in and slot_types_out */
+static void bmo_op_slots_init(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].index = i; // UNUSED
+ }
+}
+
/**
* \brief BMESH OPSTACK INIT OP
*
@@ -130,7 +144,7 @@ void BMO_pop(BMesh *bm)
*/
void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname)
{
- int i, opcode = bmo_opname_to_opcode(opname);
+ int opcode = bmo_opname_to_opcode(opname);
#ifdef DEBUG
BM_ELEM_INDEX_VALIDATE(bm, "pre bmo", opname);
@@ -148,10 +162,8 @@ void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname)
op->flag = flag;
/* initialize the operator slot types */
- for (i = 0; opdefines[opcode]->slot_types[i].type; i++) {
- op->slot_args[i].slot_type = opdefines[opcode]->slot_types[i].type;
- op->slot_args[i].index = i;
- }
+ bmo_op_slots_init(opdefines[opcode]->slot_types_in, op->slots_in);
+ bmo_op_slots_init(opdefines[opcode]->slot_types_out, op->slots_out);
/* callback */
op->exec = opdefines[opcode]->exec;
@@ -172,7 +184,9 @@ void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname)
*/
void BMO_op_exec(BMesh *bm, BMOperator *op)
{
-
+ /* allocate tool flags on demand */
+ BM_mesh_elem_toolflags_ensure(bm);
+
BMO_push(bm, op);
if (bm->stackdepth == 2)
@@ -185,6 +199,20 @@ void BMO_op_exec(BMesh *bm, BMOperator *op)
BMO_pop(bm);
}
+static void bmo_op_slots_free(BMOSlotType *slot_types, BMOpSlot *slot_args)
+{
+ BMOpSlot *slot;
+ unsigned int i;
+ for (i = 0; slot_types[i].type; i++) {
+ slot = &slot_args[i];
+ if (slot->slot_type == BMO_OP_SLOT_MAPPING) {
+ if (slot->data.ghash) {
+ BLI_ghash_free(slot->data.ghash, NULL, NULL);
+ }
+ }
+ }
+}
+
/**
* \brief BMESH OPSTACK FINISH OP
*
@@ -192,21 +220,13 @@ void BMO_op_exec(BMesh *bm, BMOperator *op)
*/
void BMO_op_finish(BMesh *bm, BMOperator *op)
{
- BMOpSlot *slot;
- int i;
-
- for (i = 0; opdefines[op->type]->slot_types[i].type; i++) {
- slot = &op->slot_args[i];
- if (slot->slot_type == BMO_OP_SLOT_MAPPING) {
- if (slot->data.ghash)
- BLI_ghash_free(slot->data.ghash, NULL, NULL);
- }
- }
+ 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);
BLI_memarena_free(op->arena);
#ifdef DEBUG
- BM_ELEM_INDEX_VALIDATE(bm, "post bmo", opdefines[op->type]->name);
+ BM_ELEM_INDEX_VALIDATE(bm, "post bmo", opdefines[op->type]->opname);
#else
(void)bm;
#endif
@@ -217,9 +237,9 @@ void BMO_op_finish(BMesh *bm, BMOperator *op)
*
* \return Success if the slot if found.
*/
-int BMO_slot_exists(BMOperator *op, const char *slot_name)
+int BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
{
- int slot_code = bmo_name_to_slotcode(opdefines[op->type], slot_name);
+ int slot_code = bmo_name_to_slotcode(slot_args, identifier);
return (slot_code >= 0);
}
@@ -228,73 +248,78 @@ int BMO_slot_exists(BMOperator *op, const char *slot_name)
*
* Returns a pointer to the slot of type 'slot_code'
*/
-BMOpSlot *BMO_slot_get(BMOperator *op, const char *slot_name)
+BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
{
- int slot_code = bmo_name_to_slotcode_check(opdefines[op->type], slot_name);
+ int slot_code = bmo_name_to_slotcode_check(slot_args, identifier);
- if (slot_code < 0) {
- return &BMOpEmptySlot;
+ if (UNLIKELY(slot_code < 0)) {
+ //return &BMOpEmptySlot;
+ BLI_assert(0);
+ NULL; /* better crash */
}
- return &(op->slot_args[slot_code]);
+ return &slot_args[slot_code];
}
/**
* \brief BMESH OPSTACK COPY SLOT
*
+ * define used.
* Copies data from one slot to another.
*/
-void BMO_slot_copy(BMOperator *source_op, BMOperator *dest_op, const char *src, const char *dst)
+void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
+ BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
+ struct MemArena *arena_dst)
{
- BMOpSlot *source_slot = BMO_slot_get(source_op, src);
- BMOpSlot *dest_slot = BMO_slot_get(dest_op, dst);
+ BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src);
+ BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst);
- if (source_slot == dest_slot)
+ if (slot_src == slot_dst)
return;
- if (source_slot->slot_type != dest_slot->slot_type) {
- /* possibly assert here? */
+ BLI_assert(slot_src->slot_type == slot_dst->slot_type);
+ if (slot_src->slot_type != slot_dst->slot_type) {
return;
}
- if (dest_slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) {
+ if (slot_dst->slot_type == BMO_OP_SLOT_ELEMENT_BUF) {
/* do buffer copy */
- dest_slot->data.buf = NULL;
- dest_slot->len = source_slot->len;
- if (dest_slot->len) {
- const int slot_alloc_size = BMO_OPSLOT_TYPEINFO[dest_slot->slot_type] * dest_slot->len;
- dest_slot->data.buf = BLI_memarena_alloc(dest_op->arena, slot_alloc_size);
- memcpy(dest_slot->data.buf, source_slot->data.buf, slot_alloc_size);
+ 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);
}
}
- else if (dest_slot->slot_type == BMO_OP_SLOT_MAPPING) {
+ else if (slot_dst->slot_type == BMO_OP_SLOT_MAPPING) {
GHashIterator it;
BMOElemMapping *srcmap, *dstmap;
/* sanity check */
- if (!source_slot->data.ghash) {
+ if (!slot_src->data.ghash) {
return;
}
- if (!dest_slot->data.ghash) {
- dest_slot->data.ghash = BLI_ghash_ptr_new("bmesh operator 2");
+ if (!slot_dst->data.ghash) {
+ slot_dst->data.ghash = BLI_ghash_ptr_new("bmesh operator 2");
}
- BLI_ghashIterator_init(&it, source_slot->data.ghash);
- for ( ; (srcmap = BLI_ghashIterator_getValue(&it));
- BLI_ghashIterator_step(&it))
+ for (BLI_ghashIterator_init(&it, slot_src->data.ghash);
+ (srcmap = BLI_ghashIterator_getValue(&it));
+ BLI_ghashIterator_step(&it))
{
- dstmap = BLI_memarena_alloc(dest_op->arena, sizeof(*dstmap) + srcmap->len);
+ dstmap = BLI_memarena_alloc(arena_dst, sizeof(*dstmap) + srcmap->len);
dstmap->element = srcmap->element;
dstmap->len = srcmap->len;
memcpy(dstmap + 1, srcmap + 1, srcmap->len);
- BLI_ghash_insert(dest_slot->data.ghash, dstmap->element, dstmap);
+ BLI_ghash_insert(slot_dst->data.ghash, dstmap->element, dstmap);
}
}
else {
- dest_slot->data = source_slot->data;
+ slot_dst->data = slot_src->data;
}
}
@@ -304,9 +329,9 @@ void BMO_slot_copy(BMOperator *source_op, BMOperator *dest_op, const char *src,
* Sets the value of a slot depending on it's type
*/
-void BMO_slot_float_set(BMOperator *op, const char *slot_name, const float f)
+void BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float f)
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BLI_assert(slot->slot_type == BMO_OP_SLOT_FLT);
if (!(slot->slot_type == BMO_OP_SLOT_FLT))
return;
@@ -314,9 +339,9 @@ void BMO_slot_float_set(BMOperator *op, const char *slot_name, const float f)
slot->data.f = f;
}
-void BMO_slot_int_set(BMOperator *op, const char *slot_name, const int i)
+void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i)
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BLI_assert(slot->slot_type == BMO_OP_SLOT_INT);
if (!(slot->slot_type == BMO_OP_SLOT_INT))
return;
@@ -324,9 +349,9 @@ void BMO_slot_int_set(BMOperator *op, const char *slot_name, const int i)
slot->data.i = i;
}
-void BMO_slot_bool_set(BMOperator *op, const char *slot_name, const int i)
+void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i)
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BLI_assert(slot->slot_type == BMO_OP_SLOT_BOOL);
if (!(slot->slot_type == BMO_OP_SLOT_BOOL))
return;
@@ -335,9 +360,9 @@ void BMO_slot_bool_set(BMOperator *op, const char *slot_name, const int i)
}
/* only supports square mats */
-void BMO_slot_mat_set(BMOperator *op, const char *slot_name, const float *mat, int size)
+void BMO_slot_mat_set(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float *mat, int size)
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT);
if (!(slot->slot_type == BMO_OP_SLOT_MAT))
return;
@@ -358,39 +383,39 @@ void BMO_slot_mat_set(BMOperator *op, const char *slot_name, const float *mat, i
}
}
-void BMO_slot_mat4_get(BMOperator *op, const char *slot_name, float r_mat[4][4])
+void BMO_slot_mat4_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[4][4])
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT);
if (!(slot->slot_type == BMO_OP_SLOT_MAT))
return;
if (slot->data.p) {
- copy_m4_m4(r_mat, (float (*)[4])slot->data.p);
+ copy_m4_m4(r_mat, BMO_SLOT_AS_MATRIX(slot));
}
else {
unit_m4(r_mat);
}
}
-void BMO_slot_mat3_set(BMOperator *op, const char *slot_name, float r_mat[3][3])
+void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[3][3])
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT);
if (!(slot->slot_type == BMO_OP_SLOT_MAT))
return;
if (slot->data.p) {
- copy_m3_m4(r_mat, slot->data.p);
+ copy_m3_m4(r_mat, BMO_SLOT_AS_MATRIX(slot));
}
else {
unit_m3(r_mat);
}
}
-void BMO_slot_ptr_set(BMOperator *op, const char *slot_name, void *p)
+void BMO_slot_ptr_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, void *p)
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BLI_assert(slot->slot_type == BMO_OP_SLOT_PTR);
if (!(slot->slot_type == BMO_OP_SLOT_PTR))
return;
@@ -398,9 +423,9 @@ void BMO_slot_ptr_set(BMOperator *op, const char *slot_name, void *p)
slot->data.p = p;
}
-void BMO_slot_vec_set(BMOperator *op, const char *slot_name, const float vec[3])
+void BMO_slot_vec_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float vec[3])
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BLI_assert(slot->slot_type == BMO_OP_SLOT_VEC);
if (!(slot->slot_type == BMO_OP_SLOT_VEC))
return;
@@ -409,9 +434,9 @@ void BMO_slot_vec_set(BMOperator *op, const char *slot_name, const float vec[3])
}
-float BMO_slot_float_get(BMOperator *op, const char *slot_name)
+float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BLI_assert(slot->slot_type == BMO_OP_SLOT_FLT);
if (!(slot->slot_type == BMO_OP_SLOT_FLT))
return 0.0f;
@@ -419,9 +444,9 @@ float BMO_slot_float_get(BMOperator *op, const char *slot_name)
return slot->data.f;
}
-int BMO_slot_int_get(BMOperator *op, const char *slot_name)
+int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BLI_assert(slot->slot_type == BMO_OP_SLOT_INT);
if (!(slot->slot_type == BMO_OP_SLOT_INT))
return 0;
@@ -429,9 +454,9 @@ int BMO_slot_int_get(BMOperator *op, const char *slot_name)
return slot->data.i;
}
-int BMO_slot_bool_get(BMOperator *op, const char *slot_name)
+int BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BLI_assert(slot->slot_type == BMO_OP_SLOT_BOOL);
if (!(slot->slot_type == BMO_OP_SLOT_BOOL))
return 0;
@@ -440,23 +465,23 @@ int BMO_slot_bool_get(BMOperator *op, const char *slot_name)
}
/* if you want a copy of the elem buffer */
-void *BMO_slot_as_arrayN(BMOperator *op, const char *slot_name, int *len)
+void *BMO_slot_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int *len)
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
void *ret;
/* could add support for mapping type */
BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
- ret = MEM_mallocN(sizeof(void *) * slot->len, __func__);
- memcpy(ret, slot->data.buf, sizeof(void *) * slot->len);
+ ret = MEM_mallocN(sizeof(void **) * slot->len, __func__);
+ memcpy(ret, slot->data.buf, sizeof(void **) * slot->len);
*len = slot->len;
return ret;
}
-void *BMO_slot_ptr_get(BMOperator *op, const char *slot_name)
+void *BMO_slot_ptr_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BLI_assert(slot->slot_type == BMO_OP_SLOT_PTR);
if (!(slot->slot_type == BMO_OP_SLOT_PTR))
return NULL;
@@ -464,9 +489,9 @@ void *BMO_slot_ptr_get(BMOperator *op, const char *slot_name)
return slot->data.p;
}
-void BMO_slot_vec_get(BMOperator *op, const char *slot_name, float r_vec[3])
+void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_vec[3])
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BLI_assert(slot->slot_type == BMO_OP_SLOT_VEC);
if (!(slot->slot_type == BMO_OP_SLOT_VEC))
return;
@@ -542,9 +567,9 @@ void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char hty
}
}
-int BMO_slot_buffer_count(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name)
+int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
/* check if its actually a buffer */
@@ -554,9 +579,9 @@ int BMO_slot_buffer_count(BMesh *UNUSED(bm), BMOperator *op, const char *slot_na
return slot->len;
}
-int BMO_slot_map_count(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name)
+int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING);
/* check if its actually a buffer */
@@ -569,12 +594,12 @@ int BMO_slot_map_count(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name)
/* inserts a key/value mapping into a mapping slot. note that it copies the
* value, it doesn't store a reference to it. */
-void BMO_slot_map_insert(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name,
- void *element, void *data, int len)
+void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot,
+ const void *element, void *data, int len)
{
BMOElemMapping *mapping;
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING);
+ BMO_ASSERT_SLOT_IN_OP(slot, op);
mapping = (BMOElemMapping *) BLI_memarena_alloc(op->arena, sizeof(*mapping) + len);
@@ -586,7 +611,7 @@ void BMO_slot_map_insert(BMesh *UNUSED(bm), BMOperator *op, const char *slot_nam
slot->data.ghash = BLI_ghash_ptr_new("bmesh slot map hash");
}
- BLI_ghash_insert(slot->data.ghash, element, mapping);
+ BLI_ghash_insert(slot->data.ghash, (void *)element, mapping);
}
#if 0
@@ -632,11 +657,11 @@ void *bmo_slot_buffer_grow(BMesh *bm, BMOperator *op, int slot_code, int totadd)
}
#endif
-void BMO_slot_map_to_flag(BMesh *bm, BMOperator *op, const char *slot_name,
+void BMO_slot_map_to_flag(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
const char htype, const short oflag)
{
GHashIterator it;
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BMElemF *ele_f;
BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING);
@@ -652,18 +677,22 @@ void BMO_slot_map_to_flag(BMesh *bm, BMOperator *op, const char *slot_name,
}
}
-void *BMO_slot_buffer_alloc(BMOperator *op, const char *slot_name, const int len)
+void *BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int len)
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
- BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
/* check if its actually a buffer */
if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF)
return NULL;
slot->len = len;
- if (len)
+ if (len) {
slot->data.buf = BLI_memarena_alloc(op->arena, BMO_OPSLOT_TYPEINFO[slot->slot_type] * len);
+ }
+ else {
+ slot->data.buf = NULL;
+ }
+
return slot->data.buf;
}
@@ -672,9 +701,10 @@ void *BMO_slot_buffer_alloc(BMOperator *op, const char *slot_name, const int len
*
* Copies all elements of a certain type into an operator slot.
*/
-void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, const char *slot_name, const char htype)
+void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name, const char htype)
{
- BMOpSlot *output = BMO_slot_get(op, slot_name);
+ BMOpSlot *output = BMO_slot_get(slot_args, slot_name);
int totelement = 0, i = 0;
if (htype & BM_VERT) totelement += bm->totvert;
@@ -685,27 +715,27 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, const char *slot_name,
BMIter iter;
BMHeader *ele;
- BMO_slot_buffer_alloc(op, slot_name, totelement);
+ BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement);
/* TODO - collapse these loops into one */
if (htype & BM_VERT) {
BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
- ((BMHeader **)output->data.p)[i] = ele;
+ output->data.buf[i] = ele;
i++;
}
}
if (htype & BM_EDGE) {
BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
- ((BMHeader **)output->data.p)[i] = ele;
+ output->data.buf[i] = ele;
i++;
}
}
if (htype & BM_FACE) {
BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
- ((BMHeader **)output->data.p)[i] = ele;
+ output->data.buf[i] = ele;
i++;
}
}
@@ -718,11 +748,11 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, const char *slot_name,
* Copies elements of a certain type, which have a certain header flag
* enabled/disabled into a slot for an operator.
*/
-static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *slot_name,
+static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
const char htype, const char hflag,
const short test_for_enabled)
{
- BMOpSlot *output = BMO_slot_get(op, slot_name);
+ BMOpSlot *output = BMO_slot_get(slot_args, slot_name);
int totelement = 0, i = 0;
const int respecthide = (op->flag & BMO_FLAG_RESPECT_HIDE) != 0;
@@ -737,7 +767,7 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl
BMIter iter;
BMElem *ele;
- BMO_slot_buffer_alloc(op, slot_name, totelement);
+ BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement);
/* TODO - collapse these loops into one */
@@ -746,7 +776,7 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl
if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) &&
BM_elem_flag_test_bool(ele, hflag) == test_for_enabled)
{
- ((BMElem **)output->data.p)[i] = ele;
+ output->data.buf[i] = ele;
i++;
}
}
@@ -757,7 +787,7 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl
if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) &&
BM_elem_flag_test_bool(ele, hflag) == test_for_enabled)
{
- ((BMElem **)output->data.p)[i] = ele;
+ output->data.buf[i] = ele;
i++;
}
}
@@ -768,7 +798,7 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl
if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) &&
BM_elem_flag_test_bool(ele, hflag) == test_for_enabled)
{
- ((BMElem **)output->data.p)[i] = ele;
+ output->data.buf[i] = ele;
i++;
}
}
@@ -779,46 +809,51 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl
}
}
-void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op, const char *slot_name,
+void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
const char htype, const char hflag)
{
- bmo_slot_buffer_from_hflag(bm, op, slot_name, htype, hflag, TRUE);
+ bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, TRUE);
}
-void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op, const char *slot_name,
+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)
{
- bmo_slot_buffer_from_hflag(bm, op, slot_name, htype, hflag, FALSE);
+ bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, FALSE);
}
/**
* Copies the values from another slot to the end of the output slot.
*/
-void BMO_slot_buffer_append(BMOperator *output_op, const char *output_slot_name,
- BMOperator *other_op, const char *other_slot_name)
+void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
+ BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
+ struct MemArena *arena_dst)
{
- BMOpSlot *output_slot = BMO_slot_get(output_op, output_slot_name);
- BMOpSlot *other_slot = BMO_slot_get(other_op, other_slot_name);
+ BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst);
+ BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src);
- BLI_assert(output_slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF &&
- other_slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
+ BLI_assert(slot_dst->slot_type == BMO_OP_SLOT_ELEMENT_BUF &&
+ slot_src->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
- if (output_slot->len == 0) {
+ if (slot_dst->len == 0) {
/* output slot is empty, copy rather than append */
- BMO_slot_copy(other_op, output_op, other_slot_name, output_slot_name);
+ _bmo_slot_copy(slot_args_src, slot_name_src,
+ slot_args_dst, slot_name_dst,
+ arena_dst);
}
- else if (other_slot->len != 0) {
- int elem_size = BMO_OPSLOT_TYPEINFO[output_slot->slot_type];
- int alloc_size = elem_size * (output_slot->len + other_slot->len);
+ else if (slot_src->len != 0) {
+ int elem_size = BMO_OPSLOT_TYPEINFO[slot_dst->slot_type];
+ int alloc_size = elem_size * (slot_dst->len + slot_src->len);
/* allocate new buffer */
- void *buf = BLI_memarena_alloc(output_op->arena, alloc_size);
+ void *buf = BLI_memarena_alloc(arena_dst, alloc_size);
/* copy slot data */
- memcpy(buf, output_slot->data.buf, elem_size * output_slot->len);
- memcpy(((char *)buf) + elem_size * output_slot->len, other_slot->data.buf, elem_size * other_slot->len);
+ memcpy(buf, slot_dst->data.buf, elem_size * slot_dst->len);
+ memcpy(((char *)buf) + elem_size * slot_dst->len, slot_src->data.buf, elem_size * slot_src->len);
- output_slot->data.buf = buf;
- output_slot->len += other_slot->len;
+ slot_dst->data.buf = buf;
+ slot_dst->len += slot_src->len;
}
}
@@ -828,13 +863,15 @@ void BMO_slot_buffer_append(BMOperator *output_op, const char *output_slot_name,
* Copies elements of a certain type, which have a certain flag set
* into an output slot for an operator.
*/
-static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, const char *slot_name,
+static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
const char htype, const short oflag,
const short test_for_enabled)
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
int totelement, i = 0;
+ BLI_assert(op->slots_in == slot_args || op->slots_out == slot_args);
BLI_assert(ELEM(TRUE, FALSE, test_for_enabled));
if (test_for_enabled)
@@ -849,9 +886,9 @@ static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, const char *slo
BMHeader *ele;
BMHeader **ele_array;
- BMO_slot_buffer_alloc(op, slot_name, totelement);
+ BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement);
- ele_array = (BMHeader **)slot->data.p;
+ ele_array = (BMHeader **)slot->data.buf;
/* TODO - collapse these loops into one */
@@ -887,16 +924,18 @@ static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, const char *slo
}
}
-void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, const char *slot_name,
+void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
const char htype, const short oflag)
{
- bmo_slot_buffer_from_flag(bm, op, slot_name, htype, oflag, TRUE);
+ bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, TRUE);
}
-void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, const char *slot_name,
+void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
const char htype, const short oflag)
{
- bmo_slot_buffer_from_flag(bm, op, slot_name, htype, oflag, FALSE);
+ bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, FALSE);
}
/**
@@ -905,11 +944,12 @@ void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, const char *s
* Header Flags elements in a slots buffer, automatically
* using the selection API where appropriate.
*/
-void BMO_slot_buffer_hflag_enable(BMesh *bm, BMOperator *op, const char *slot_name,
+void BMO_slot_buffer_hflag_enable(BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
const char htype, const char hflag, const char do_flush)
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
- BMElem **data = slot->data.p;
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BMElem **data = (BMElem **)slot->data.buf;
int i;
const char do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT));
const char do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN));
@@ -938,11 +978,12 @@ void BMO_slot_buffer_hflag_enable(BMesh *bm, BMOperator *op, const char *slot_na
* Removes flags from elements in a slots buffer, automatically
* using the selection API where appropriate.
*/
-void BMO_slot_buffer_hflag_disable(BMesh *bm, BMOperator *op, const char *slot_name,
+void BMO_slot_buffer_hflag_disable(BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
const char htype, const char hflag, const char do_flush)
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
- BMElem **data = slot->data.p;
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BMElem **data = (BMElem **)slot->data.buf;
int i;
const char do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT));
const char do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN));
@@ -989,10 +1030,11 @@ int BMO_vert_edge_flags_count(BMesh *bm, BMVert *v, const short oflag)
*
* Flags elements in a slots buffer
*/
-void BMO_slot_buffer_flag_enable(BMesh *bm, BMOperator *op, const char *slot_name,
+void BMO_slot_buffer_flag_enable(BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
const char htype, const short oflag)
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BMHeader **data = slot->data.p;
int i;
@@ -1011,11 +1053,12 @@ void BMO_slot_buffer_flag_enable(BMesh *bm, BMOperator *op, const char *slot_nam
*
* Removes flags from elements in a slots buffer
*/
-void BMO_slot_buffer_flag_disable(BMesh *bm, BMOperator *op, const char *slot_name,
+void BMO_slot_buffer_flag_disable(BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
const char htype, const short oflag)
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
- BMHeader **data = slot->data.p;
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BMHeader **data = (BMHeader **)slot->data.buf;
int i;
BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
@@ -1056,7 +1099,9 @@ static void bmo_flag_layer_alloc(BMesh *bm)
/* store memcpy size for reuse */
const size_t old_totflags_size = (bm->totflags * sizeof(BMFlagLayer));
-
+
+ BLI_assert(oldpool != NULL);
+
bm->totflags++;
/* allocate new flag poo */
@@ -1068,18 +1113,21 @@ static void bmo_flag_layer_alloc(BMesh *bm)
ele->oflags = BLI_mempool_calloc(newpool);
memcpy(ele->oflags, oldflags, old_totflags_size);
BM_elem_index_set(ele, i); /* set_inline */
+ BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele);
}
BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) {
oldflags = ele->oflags;
ele->oflags = BLI_mempool_calloc(newpool);
memcpy(ele->oflags, oldflags, old_totflags_size);
BM_elem_index_set(ele, i); /* set_inline */
+ BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele);
}
BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) {
oldflags = ele->oflags;
ele->oflags = BLI_mempool_calloc(newpool);
memcpy(ele->oflags, oldflags, old_totflags_size);
BM_elem_index_set(ele, i); /* set_inline */
+ BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele);
}
bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE);
@@ -1113,18 +1161,21 @@ static void bmo_flag_layer_free(BMesh *bm)
ele->oflags = BLI_mempool_calloc(newpool);
memcpy(ele->oflags, oldflags, new_totflags_size);
BM_elem_index_set(ele, i); /* set_inline */
+ BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele);
}
BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) {
oldflags = ele->oflags;
ele->oflags = BLI_mempool_calloc(newpool);
memcpy(ele->oflags, oldflags, new_totflags_size);
BM_elem_index_set(ele, i); /* set_inline */
+ BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele);
}
BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) {
oldflags = ele->oflags;
ele->oflags = BLI_mempool_calloc(newpool);
memcpy(ele->oflags, oldflags, new_totflags_size);
BM_elem_index_set(ele, i); /* set_inline */
+ BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele);
}
bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE);
@@ -1159,14 +1210,14 @@ static void bmo_flag_layer_clear(BMesh *bm)
bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE);
}
-void *BMO_slot_buffer_elem_first(BMOperator *op, const char *slot_name)
+void *BMO_slot_buffer_elem_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF)
return NULL;
- return slot->data.buf ? *(void **)slot->data.buf : NULL;
+ return slot->data.buf ? *slot->data.buf : NULL;
}
/**
@@ -1175,10 +1226,11 @@ void *BMO_slot_buffer_elem_first(BMOperator *op, const char *slot_name)
* \param restrictmask restricts the iteration to certain element types
* (e.g. combination of BM_VERT, BM_EDGE, BM_FACE), if iterating
* over an element buffer (not a mapping). */
-void *BMO_iter_new(BMOIter *iter, BMesh *UNUSED(bm), BMOperator *op,
- const char *slot_name, const char restrictmask)
+void *BMO_iter_new(BMOIter *iter,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
+ const char restrictmask)
{
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
memset(iter, 0, sizeof(BMOIter));
@@ -1207,13 +1259,13 @@ void *BMO_iter_step(BMOIter *iter)
return NULL;
}
- h = ((void **)iter->slot->data.buf)[iter->cur++];
+ h = iter->slot->data.buf[iter->cur++];
while (!(iter->restrictmask & h->htype)) {
if (iter->cur >= iter->slot->len) {
return NULL;
}
- h = ((void **)iter->slot->data.buf)[iter->cur++];
+ h = iter->slot->data.buf[iter->cur++];
}
return h;
@@ -1312,24 +1364,26 @@ int BMO_error_pop(BMesh *bm, const char **msg, BMOperator **op)
#define NEXT_CHAR(fmt) ((fmt)[0] != 0 ? (fmt)[1] : 0)
-static int bmo_name_to_slotcode(BMOpDefine *def, const char *name)
+static int bmo_name_to_slotcode(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
{
- int i;
+ int i = 0;
- for (i = 0; def->slot_types[i].type; i++) {
- if (!strncmp(name, def->slot_types[i].name, MAX_SLOTNAME)) {
+ while (slot_args->slot_name) {
+ if (strncmp(identifier, slot_args->slot_name, MAX_SLOTNAME) == 0) {
return i;
}
+ slot_args++;
+ i++;
}
return -1;
}
-static int bmo_name_to_slotcode_check(BMOpDefine *def, const char *name)
+static int bmo_name_to_slotcode_check(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
{
- int i = bmo_name_to_slotcode(def, name);
+ int i = bmo_name_to_slotcode(slot_args, identifier);
if (i < 0) {
- fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, name);
+ fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, identifier);
}
return i;
@@ -1340,12 +1394,12 @@ static int bmo_opname_to_opcode(const char *opname)
int i;
for (i = 0; i < bmesh_total_ops; i++) {
- if (!strcmp(opname, opdefines[i]->name)) {
+ if (!strcmp(opname, opdefines[i]->opname)) {
return i;
}
}
- fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, opname);
+ fprintf(stderr, "%s: could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, opname);
return -1;
}
@@ -1355,6 +1409,8 @@ static int bmo_opname_to_opcode(const char *opname)
* 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)
@@ -1368,7 +1424,7 @@ static int bmo_opname_to_opcode(const char *opname)
int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, va_list vlist)
{
- BMOpDefine *def;
+// BMOpDefine *def;
char *opname, *ofmt, *fmt;
char slot_name[64] = {0};
int i /*, n = strlen(fmt) */, stop /*, slot_code = -1 */, type, state;
@@ -1407,7 +1463,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 = opdefines[i];
i = 0;
state = 1; /* 0: not inside slot_code name, 1: inside slot_code name */
@@ -1430,7 +1486,7 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v
fmt[i] = 0;
- if (bmo_name_to_slotcode_check(def, fmt) < 0) {
+ if (bmo_name_to_slotcode_check(op->slots_in, fmt) < 0) {
GOTO_ERROR("name to slot code check failed");
}
@@ -1456,47 +1512,57 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v
else if (c == '4') size = 4;
else GOTO_ERROR("matrix size was not 3 or 4");
- BMO_slot_mat_set(op, slot_name, va_arg(vlist, void *), size);
+ BMO_slot_mat_set(op, op->slots_in, slot_name, va_arg(vlist, void *), size);
state = 1;
break;
}
case 'v':
{
- BMO_slot_vec_set(op, slot_name, va_arg(vlist, float *));
+ BMO_slot_vec_set(op->slots_in, slot_name, va_arg(vlist, float *));
state = 1;
break;
}
case 'e':
{
BMHeader *ele = va_arg(vlist, void *);
- BMOpSlot *slot = BMO_slot_get(op, slot_name);
+ BMOpSlot *slot = BMO_slot_get(op->slots_in, slot_name);
slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(void *) * 4);
slot->len = 1;
- *((void **)slot->data.buf) = ele;
+ *slot->data.buf = ele;
state = 1;
break;
}
case 's':
+ case 'S':
{
- BMOperator *op2 = va_arg(vlist, void *);
- const char *slot_name2 = va_arg(vlist, char *);
+ BMOperator *op_other = va_arg(vlist, void *);
+ const char *slot_name_other = va_arg(vlist, char *);
- BMO_slot_copy(op2, op, slot_name2, slot_name);
+ if (*fmt == 's') {
+ BLI_assert(bmo_name_to_slotcode_check(op_other->slots_in, slot_name_other) != -1);
+ BMO_slot_copy(op_other, slots_in, slot_name_other,
+ op, slots_in, slot_name);
+ }
+ else {
+ BLI_assert(bmo_name_to_slotcode_check(op_other->slots_out, slot_name_other) != -1);
+ BMO_slot_copy(op_other, slots_out, slot_name_other,
+ op, slots_in, slot_name);
+ }
state = 1;
break;
}
case 'i':
- BMO_slot_int_set(op, slot_name, va_arg(vlist, int));
+ BMO_slot_int_set(op->slots_in, slot_name, va_arg(vlist, int));
state = 1;
break;
case 'b':
- BMO_slot_bool_set(op, slot_name, va_arg(vlist, int));
+ BMO_slot_bool_set(op->slots_in, slot_name, va_arg(vlist, int));
state = 1;
break;
case 'p':
- BMO_slot_ptr_set(op, slot_name, va_arg(vlist, void *));
+ BMO_slot_ptr_set(op->slots_in, slot_name, va_arg(vlist, void *));
state = 1;
break;
case 'f':
@@ -1507,7 +1573,7 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v
type = *fmt;
if (NEXT_CHAR(fmt) == ' ' || NEXT_CHAR(fmt) == '\0') {
- BMO_slot_float_set(op, slot_name, va_arg(vlist, double));
+ BMO_slot_float_set(op->slots_in, slot_name, va_arg(vlist, double));
}
else {
htype = 0;
@@ -1529,19 +1595,19 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v
}
if (type == 'h') {
- BMO_slot_buffer_from_enabled_hflag(bm, op, slot_name, htype, va_arg(vlist, int));
+ BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int));
}
else if (type == 'H') {
- BMO_slot_buffer_from_disabled_hflag(bm, op, slot_name, htype, va_arg(vlist, int));
+ BMO_slot_buffer_from_disabled_hflag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int));
}
else if (type == 'a') {
- BMO_slot_buffer_from_all(bm, op, slot_name, htype);
+ BMO_slot_buffer_from_all(bm, op, op->slots_in, slot_name, htype);
}
else if (type == 'f') {
- BMO_slot_buffer_from_enabled_flag(bm, op, slot_name, htype, va_arg(vlist, int));
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int));
}
else if (type == 'F') {
- BMO_slot_buffer_from_disabled_flag(bm, op, slot_name, htype, va_arg(vlist, int));
+ BMO_slot_buffer_from_disabled_flag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int));
}
}
diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h
index 14da93302b9..b74d97c9bb5 100644
--- a/source/blender/bmesh/intern/bmesh_operators.h
+++ b/source/blender/bmesh/intern/bmesh_operators.h
@@ -88,11 +88,6 @@ enum {
OPUVC_AXIS_Y
};
-enum {
- DIRECTION_CW = 1,
- DIRECTION_CCW
-};
-
/* vertex path selection values */
enum {
VPATH_SELECT_EDGE_LENGTH = 0,
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index 98edceb30a2..2e0471863d4 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -162,7 +162,7 @@ float BM_face_calc_area(BMFace *f)
float area;
int i;
- BLI_array_fixedstack_declare(verts, BM_NGON_STACK_SIZE, f->len, __func__);
+ BLI_array_fixedstack_declare(verts, BM_DEFAULT_NGON_STACK_SIZE, f->len, __func__);
BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, i) {
copy_v3_v3(verts[i], l->v->co);
@@ -677,6 +677,7 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], const int use_beauty, floa
BMLoop *l_first;
const float cos_threshold = 0.9f;
+ const float bias = 1.0f + 1e-6f;
if (f->len == 4) {
BMLoop *larr[4];
@@ -691,7 +692,7 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], const int use_beauty, floa
/* pick 0/1 based on best lenth */
/* XXX Can't only rely on such test, also must check we do not get (too much) degenerated triangles!!! */
i = (((len_squared_v3v3(larr[0]->v->co, larr[2]->v->co) >
- len_squared_v3v3(larr[1]->v->co, larr[3]->v->co))) != use_beauty);
+ len_squared_v3v3(larr[1]->v->co, larr[3]->v->co) * bias)) != use_beauty);
i4 = (i + 3) % 4;
/* Check produced tris aren’t too flat/narrow...
* Probably not the best test, but is quite efficient and should at least avoid null-area faces! */
@@ -965,8 +966,8 @@ void BM_face_legal_splits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len)
float fac1 = 1.0000001f, fac2 = 0.9f; //9999f; //0.999f;
int i, j, a = 0, clen;
- BLI_array_fixedstack_declare(projverts, BM_NGON_STACK_SIZE, f->len, "projvertsb");
- BLI_array_fixedstack_declare(edgeverts, BM_NGON_STACK_SIZE * 2, len * 2, "edgevertsb");
+ BLI_array_fixedstack_declare(projverts, BM_DEFAULT_NGON_STACK_SIZE, f->len, "projvertsb");
+ BLI_array_fixedstack_declare(edgeverts, BM_DEFAULT_NGON_STACK_SIZE * 2, len * 2, "edgevertsb");
i = 0;
l = BM_iter_new(&iter, bm, BM_LOOPS_OF_FACE, f);
diff --git a/source/blender/bmesh/intern/bmesh_private.h b/source/blender/bmesh/intern/bmesh_private.h
index b3fe3676ab8..850e81ba3ac 100644
--- a/source/blender/bmesh/intern/bmesh_private.h
+++ b/source/blender/bmesh/intern/bmesh_private.h
@@ -56,15 +56,21 @@ int bmesh_elem_check(void *element, const char htype);
int bmesh_radial_length(BMLoop *l);
int bmesh_disk_count(BMVert *v);
-/* NOTE: ensure different parts of the API do not conflict
+/**
+ * Internal BMHeader.api_flag
+ * \note Ensure different parts of the API do not conflict
* on using these internal flags!*/
-#define _FLAG_JF 1 /* join faces */
-#define _FLAG_MF 2 /* make face */
-#define _FLAG_MV 2 /* make face, vertex */
+enum {
+ _FLAG_JF = (1 << 0), /* join faces */
+ _FLAG_MF = (1 << 1), /* make face */
+ _FLAG_MV = (1 << 1), /* make face, vertex */
+ _FLAG_OVERLAP = (1 << 2) /* general overlap flag */
+};
-#define BM_ELEM_API_FLAG_ENABLE(element, f) ((element)->oflags[0].pflag |= (f))
-#define BM_ELEM_API_FLAG_DISABLE(element, f) ((element)->oflags[0].pflag &= ~(f))
-#define BM_ELEM_API_FLAG_TEST(element, f) ((element)->oflags[0].pflag & (f))
+#define BM_ELEM_API_FLAG_ENABLE(element, f) ((element)->head.api_flag |= (f))
+#define BM_ELEM_API_FLAG_DISABLE(element, f) ((element)->head.api_flag &= ~(f))
+#define BM_ELEM_API_FLAG_TEST(element, f) ((element)->head.api_flag & (f))
+#define BM_ELEM_API_FLAG_CLEAR(element) ((element)->head.api_flag = 0)
void calc_poly_plane(float (*verts)[3], const int nverts);
void poly_rotate_plane(const float normal[3], float (*verts)[3], const int nverts);
diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
index 1e1d7d1becb..ec2e90591cc 100644
--- a/source/blender/bmesh/intern/bmesh_queries.c
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -39,8 +39,6 @@
#include "bmesh.h"
#include "intern/bmesh_private.h"
-#define BM_OVERLAP (1 << 13)
-
/**
* Returns whether or not a given vertex is
* is part of a given edge.
@@ -240,7 +238,7 @@ int BM_vert_in_face(BMFace *f, BMVert *v)
* Compares the number of vertices in an array
* that appear in a given face
*/
-int BM_verts_in_face(BMesh *bm, BMFace *f, BMVert **varr, int len)
+int BM_verts_in_face(BMFace *f, BMVert **varr, int len)
{
BMLoop *l_iter, *l_first;
@@ -251,7 +249,7 @@ int BM_verts_in_face(BMesh *bm, BMFace *f, BMVert **varr, int len)
int i, count = 0;
for (i = 0; i < len; i++) {
- BMO_elem_flag_enable(bm, varr[i], BM_OVERLAP);
+ BM_ELEM_API_FLAG_ENABLE(varr[i], _FLAG_OVERLAP);
}
#ifdef USE_BMESH_HOLES
@@ -266,14 +264,16 @@ int BM_verts_in_face(BMesh *bm, BMFace *f, BMVert **varr, int len)
#endif
do {
- if (BMO_elem_flag_test(bm, l_iter->v, BM_OVERLAP)) {
+ if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP)) {
count++;
}
} while ((l_iter = l_iter->next) != l_first);
}
- for (i = 0; i < len; i++) BMO_elem_flag_disable(bm, varr[i], BM_OVERLAP);
+ for (i = 0; i < len; i++) {
+ BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP);
+ }
return count;
}
@@ -1217,7 +1217,7 @@ BMEdge *BM_edge_find_double(BMEdge *e)
* \returns TRUE for overlap
*
*/
-int BM_face_exists_overlap(BMesh *bm, BMVert **varr, int len, BMFace **r_overlapface)
+int BM_face_exists_overlap(BMVert **varr, int len, BMFace **r_overlapface)
{
BMIter viter;
BMFace *f;
@@ -1225,7 +1225,7 @@ int BM_face_exists_overlap(BMesh *bm, BMVert **varr, int len, BMFace **r_overlap
for (i = 0; i < len; i++) {
BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
- amount = BM_verts_in_face(bm, f, varr, len);
+ amount = BM_verts_in_face(f, varr, len);
if (amount >= len) {
if (r_overlapface) {
*r_overlapface = f;
@@ -1247,7 +1247,7 @@ int BM_face_exists_overlap(BMesh *bm, BMVert **varr, int len, BMFace **r_overlap
* there is a face with exactly those vertices
* (and only those vertices).
*/
-int BM_face_exists(BMesh *bm, BMVert **varr, int len, BMFace **r_existface)
+int BM_face_exists(BMVert **varr, int len, BMFace **r_existface)
{
BMIter viter;
BMFace *f;
@@ -1255,7 +1255,7 @@ int BM_face_exists(BMesh *bm, BMVert **varr, int len, BMFace **r_existface)
for (i = 0; i < len; i++) {
BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
- amount = BM_verts_in_face(bm, f, varr, len);
+ amount = BM_verts_in_face(f, varr, len);
if (amount == len && amount == f->len) {
if (r_existface) {
*r_existface = f;
@@ -1393,7 +1393,7 @@ int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len)
int BM_face_exists_multi_edge(BMEdge **earr, int len)
{
BMVert **varr;
- BLI_array_fixedstack_declare(varr, BM_NGON_STACK_SIZE, len, __func__);
+ BLI_array_fixedstack_declare(varr, BM_DEFAULT_NGON_STACK_SIZE, len, __func__);
int ok;
int i, i_next;
@@ -1419,3 +1419,38 @@ int BM_face_exists_multi_edge(BMEdge **earr, int len)
return ok;
}
+
+/* convenience functions for checking flags */
+int BM_edge_is_any_vert_flag_test(BMEdge *e, const char hflag)
+{
+ return (BM_elem_flag_test(e->v1, hflag) ||
+ BM_elem_flag_test(e->v2, hflag));
+}
+
+int BM_face_is_any_vert_flag_test(BMFace *f, const char hflag)
+{
+ BMLoop *l_iter;
+ BMLoop *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (BM_elem_flag_test(l_iter->v, hflag)) {
+ return TRUE;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ return FALSE;
+}
+
+int BM_face_is_any_edge_flag_test(BMFace *f, const char hflag)
+{
+ BMLoop *l_iter;
+ BMLoop *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (BM_elem_flag_test(l_iter->e, hflag)) {
+ return TRUE;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ return FALSE;
+}
diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h
index 579a1397b0c..d97faebf021 100644
--- a/source/blender/bmesh/intern/bmesh_queries.h
+++ b/source/blender/bmesh/intern/bmesh_queries.h
@@ -28,7 +28,7 @@
*/
int BM_vert_in_face(BMFace *f, BMVert *v);
-int BM_verts_in_face(BMesh *bm, BMFace *f, BMVert **varr, int len);
+int BM_verts_in_face(BMFace *f, BMVert **varr, int len);
int BM_edge_in_face(BMFace *f, BMEdge *e);
int BM_edge_in_loop(BMEdge *e, BMLoop *l);
@@ -77,9 +77,9 @@ BMLoop *BM_face_find_longest_loop(BMFace *f);
BMEdge *BM_edge_exists(BMVert *v1, BMVert *v2);
BMEdge *BM_edge_find_double(BMEdge *e);
-int BM_face_exists_overlap(BMesh *bm, BMVert **varr, int len, BMFace **r_existface);
+int BM_face_exists_overlap(BMVert **varr, int len, BMFace **r_existface);
-int BM_face_exists(BMesh *bm, BMVert **varr, int len, BMFace **r_existface);
+int BM_face_exists(BMVert **varr, int len, BMFace **r_existface);
int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len);
int BM_face_exists_multi_edge(BMEdge **earr, int len);
@@ -100,4 +100,8 @@ void BM_edge_ordered_verts(BMEdge *edge, BMVert **r_v1, BMVert **r_v2);
void BM_edge_ordered_verts_ex(BMEdge *edge, BMVert **r_v1, BMVert **r_v2,
BMLoop *edge_loop);
+int BM_edge_is_any_vert_flag_test(BMEdge *e, const char hflag);
+int BM_face_is_any_vert_flag_test(BMFace *f, const char hflag);
+int BM_face_is_any_edge_flag_test(BMFace *f, const char hflag);
+
#endif /* __BMESH_QUERIES_H__ */