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:
Diffstat (limited to 'source/blender/bmesh/intern')
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c144
-rw-r--r--source/blender/bmesh/intern/bmesh_core.h1
-rw-r--r--source/blender/bmesh/intern/bmesh_edgeloop.c4
-rw-r--r--source/blender/bmesh/intern/bmesh_interp.c4
-rw-r--r--source/blender/bmesh/intern/bmesh_interp.h4
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators_inline.h10
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c28
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.h9
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c55
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.h8
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.c592
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.h4
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c276
-rw-r--r--source/blender/bmesh/intern/bmesh_operator_api.h8
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c51
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_private.h3
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c20
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.h168
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.h42
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers.c2
21 files changed, 1122 insertions, 313 deletions
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index 1c93eccf8bd..1f942dad048 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -62,6 +62,8 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3],
{
BMVert *v = BLI_mempool_alloc(bm->vpool);
+ BLI_assert((v_example == NULL) || (v_example->head.htype == BM_VERT));
+ BLI_assert(!(create_flag & 1));
/* --- assign all members --- */
v->head.data = NULL;
@@ -136,6 +138,8 @@ BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2,
BLI_assert(v1 != v2);
BLI_assert(v1->head.htype == BM_VERT && v2->head.htype == BM_VERT);
+ BLI_assert((e_example == NULL) || (e_example->head.htype == BM_EDGE));
+ BLI_assert(!(create_flag & 1));
if ((create_flag & BM_CREATE_NO_DOUBLE) && (e = BM_edge_exists(v1, v2)))
return e;
@@ -191,12 +195,15 @@ BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2,
}
static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f,
- const BMLoop *example, const eBMCreateFlag create_flag)
+ const BMLoop *l_example, const eBMCreateFlag create_flag)
{
BMLoop *l = NULL;
l = BLI_mempool_alloc(bm->lpool);
+ BLI_assert((l_example == NULL) || (l_example->head.htype == BM_LOOP));
+ BLI_assert(!(create_flag & 1));
+
/* --- assign all members --- */
l->head.data = NULL;
@@ -226,8 +233,8 @@ static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f,
bm->totloop++;
if (!(create_flag & BM_CREATE_SKIP_CD)) {
- if (example) {
- CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, example->head.data, &l->head.data);
+ if (l_example) {
+ CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, l_example->head.data, &l->head.data);
}
else {
CustomData_bmesh_set_default(&bm->ldata, &l->head.data);
@@ -388,7 +395,10 @@ BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len,
BMFace *f = NULL;
BMLoop *l, *startl, *lastl;
int i;
-
+
+ BLI_assert((f_example == NULL) || (f_example->head.htype == BM_FACE));
+ BLI_assert(!(create_flag & 1));
+
if (len == 0) {
/* just return NULL for now */
return NULL;
@@ -956,54 +966,38 @@ bool bmesh_loop_reverse(BMesh *bm, BMFace *f)
#endif
}
-static void bm_elements_systag_enable(void *veles, int tot, int flag)
+static void bm_elements_systag_enable(void *veles, int tot, const char api_flag)
{
BMHeader **eles = veles;
int i;
for (i = 0; i < tot; i++) {
- BM_ELEM_API_FLAG_ENABLE((BMElemF *)eles[i], flag);
+ BM_ELEM_API_FLAG_ENABLE((BMElemF *)eles[i], api_flag);
}
}
-static void bm_elements_systag_disable(void *veles, int tot, int flag)
+static void bm_elements_systag_disable(void *veles, int tot, const char api_flag)
{
BMHeader **eles = veles;
int i;
for (i = 0; i < tot; i++) {
- BM_ELEM_API_FLAG_DISABLE((BMElemF *)eles[i], flag);
+ BM_ELEM_API_FLAG_DISABLE((BMElemF *)eles[i], api_flag);
}
}
-static int count_flagged_radial(BMesh *bm, BMLoop *l, int flag)
+static int bm_loop_systag_count_radial(BMLoop *l, const char api_flag)
{
- BMLoop *l2 = l;
- int i = 0, c = 0;
-
+ BMLoop *l_iter = l;
+ int i = 0;
do {
- if (UNLIKELY(!l2)) {
- BMESH_ASSERT(0);
- goto error;
- }
-
- i += BM_ELEM_API_FLAG_TEST(l2->f, flag) ? 1 : 0;
- l2 = l2->radial_next;
- if (UNLIKELY(c >= BM_LOOP_RADIAL_MAX)) {
- BMESH_ASSERT(0);
- goto error;
- }
- c++;
- } while (l2 != l);
+ i += BM_ELEM_API_FLAG_TEST(l_iter->f, api_flag) ? 1 : 0;
+ } while ((l_iter = l_iter->radial_next) != l);
return i;
-
-error:
- BMO_error_raise(bm, bm->currentop, BMERR_MESH_ERROR, NULL);
- return 0;
}
-static int UNUSED_FUNCTION(count_flagged_disk)(BMVert *v, int flag)
+static int UNUSED_FUNCTION(bm_vert_systag_count_disk)(BMVert *v, const char api_flag)
{
BMEdge *e = v->e;
int i = 0;
@@ -1012,13 +1006,13 @@ static int UNUSED_FUNCTION(count_flagged_disk)(BMVert *v, int flag)
return 0;
do {
- i += BM_ELEM_API_FLAG_TEST(e, flag) ? 1 : 0;
+ i += BM_ELEM_API_FLAG_TEST(e, api_flag) ? 1 : 0;
} while ((e = bmesh_disk_edge_next(e, v)) != v->e);
return i;
}
-static bool disk_is_flagged(BMVert *v, int flag)
+static bool disk_is_flagged(BMVert *v, const char api_flag)
{
BMEdge *e = v->e;
@@ -1036,7 +1030,7 @@ static bool disk_is_flagged(BMVert *v, int flag)
return false;
do {
- if (!BM_ELEM_API_FLAG_TEST(l->f, flag))
+ if (!BM_ELEM_API_FLAG_TEST(l->f, api_flag))
return false;
} while ((l = l->radial_next) != e->l);
} while ((e = bmesh_disk_edge_next(e, v)) != v->e);
@@ -1093,7 +1087,7 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del)
f = faces[i];
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
- int rlen = count_flagged_radial(bm, l_iter, _FLAG_JF);
+ int rlen = bm_loop_systag_count_radial(l_iter, _FLAG_JF);
if (rlen > 2) {
err = N_("Input faces do not form a contiguous manifold region");
@@ -1318,7 +1312,7 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMLoop *l_v1, BMLoop *l_v2,
#ifdef USE_BMESH_HOLES
ListBase *holes,
#endif
- BMEdge *example,
+ BMEdge *e_example,
const bool no_double
)
{
@@ -1338,7 +1332,7 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMLoop *l_v1, BMLoop *l_v2,
BLI_assert(f == l_v1->f && f == l_v2->f);
/* allocate new edge between v1 and v2 */
- e = BM_edge_create(bm, v1, v2, example, no_double ? BM_CREATE_NO_DOUBLE : BM_CREATE_NOP);
+ e = BM_edge_create(bm, v1, v2, e_example, no_double ? BM_CREATE_NO_DOUBLE : BM_CREATE_NOP);
f2 = bm_face_create__sfme(bm, f);
l_f1 = bm_loop_create(bm, v2, e, f, l_v2, 0);
@@ -1748,8 +1742,7 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
l_kill = l_kill->radial_next;
}
for (i = 0; i < radlen; i++) {
- bm->totloop--;
- BLI_mempool_free(bm->lpool, loops[i]);
+ bm_kill_only_loop(bm, loops[i]);
}
}
#ifndef NDEBUG
@@ -1957,6 +1950,44 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
}
/**
+ * Check if splicing vertices would create any double edges.
+ *
+ * \note assume caller will handle case where verts share an edge.
+ */
+bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b)
+{
+ bool is_double = false;
+
+ BLI_assert(BM_edge_exists(v_a, v_b) == false);
+
+ if (v_a->e && v_b->e) {
+ SmallHash visit;
+ BMEdge *e, *e_first;
+
+ BLI_smallhash_init(&visit);
+
+ e = e_first = v_a->e;
+ do {
+ BMVert *v_other = BM_edge_other_vert(e, v_a);
+ BLI_smallhash_insert(&visit, (uintptr_t)v_other, NULL);
+ } while ((e = BM_DISK_EDGE_NEXT(e, v_a)) != e_first);
+
+ e = e_first = v_b->e;
+ do {
+ BMVert *v_other = BM_edge_other_vert(e, v_b);
+ if (BLI_smallhash_haskey(&visit, (uintptr_t)v_other)) {
+ is_double = true;
+ break;
+ }
+ } while ((e = BM_DISK_EDGE_NEXT(e, v_b)) != e_first);
+
+ BLI_smallhash_release(&visit);
+ }
+
+ return is_double;
+}
+
+/**
* \brief Splice Vert
*
* Merges two verts into one (\a v into \a vtarget).
@@ -1969,10 +2000,6 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
*/
bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target)
{
- void *loops_stack[BM_DEFAULT_ITER_STACK_SIZE];
- BMLoop **loops;
- int i, loops_tot;
-
BMEdge *e;
/* verts already spliced */
@@ -1980,21 +2007,25 @@ bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *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,
- loops_stack, BM_DEFAULT_ITER_STACK_SIZE);
-
- if (LIKELY(loops != NULL)) {
- for (i = 0; i < loops_tot; i++) {
- loops[i]->v = v_target;
- }
- if (loops != (BMLoop **)loops_stack) {
- MEM_freeN(loops);
- }
- }
+ BLI_assert(BM_vert_pair_share_face_check(v, v_target) == false);
/* move all the edges from v's disk to vtarget's disk */
while ((e = v->e)) {
+
+ /* loop */
+ BMLoop *l_first;
+ if ((l_first = e->l)) {
+ BMLoop *l_iter = l_first;
+ do {
+ if (l_iter->v == v) {
+ l_iter->v = v_target;
+ }
+ /* else if (l_iter->prev->v == v) {...}
+ * (this case will be handled by a different edge) */
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+
+ /* disk */
bmesh_disk_edge_remove(e, v);
bmesh_edge_swapverts(e, v, v_target);
bmesh_disk_edge_append(e, v_target);
@@ -2048,15 +2079,16 @@ void bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len
/* Considering only edges and faces incident on vertex v, walk
* the edges & faces and assign an index to each connected set */
+ BLI_smallhash_insert(&visithash, (uintptr_t)e, SET_INT_IN_POINTER(maxindex));
do {
- BLI_smallhash_insert(&visithash, (uintptr_t)e, SET_INT_IN_POINTER(maxindex));
-
if (e->l) {
BMLoop *l_iter, *l_first;
l_iter = l_first = e->l;
do {
l_new = (l_iter->v == v) ? l_iter->prev : l_iter->next;
+ BLI_assert(BM_vert_in_edge(l_new->e, v));
if (!BLI_smallhash_haskey(&visithash, (uintptr_t)l_new->e)) {
+ BLI_smallhash_insert(&visithash, (uintptr_t)l_new->e, SET_INT_IN_POINTER(maxindex));
STACK_PUSH(stack, l_new->e);
}
} while ((l_iter = l_iter->radial_next) != l_first);
diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h
index 4a2b4b7feca..ab847fc82eb 100644
--- a/source/blender/bmesh/intern/bmesh_core.h
+++ b/source/blender/bmesh/intern/bmesh_core.h
@@ -61,6 +61,7 @@ void bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep,
const bool copy_select);
bool BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target);
bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target);
+bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b);
void bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
const bool copy_select);
diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.c b/source/blender/bmesh/intern/bmesh_edgeloop.c
index f01e1197bb7..e83a1d5b00a 100644
--- a/source/blender/bmesh/intern/bmesh_edgeloop.c
+++ b/source/blender/bmesh/intern/bmesh_edgeloop.c
@@ -682,12 +682,12 @@ void BM_edgeloop_expand(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store, int el_sto
LinkData *node_curr_init = node_curr;
LinkData *node_curr_copy;
int i = 0;
- LISTBASE_CIRCULAR_FORWARD_BEGIN (&el_store->verts, node_curr, node_curr_init) {
+ BLI_LISTBASE_CIRCULAR_FORWARD_BEGIN (&el_store->verts, node_curr, node_curr_init) {
if (i++ < step) {
break;
}
}
- LISTBASE_CIRCULAR_FORWARD_END (&el_store->verts, node_curr, node_curr_init);
+ BLI_LISTBASE_CIRCULAR_FORWARD_END (&el_store->verts, node_curr, node_curr_init);
node_curr_copy = MEM_dupallocN(node_curr);
BLI_insertlinkafter(&el_store->verts, node_curr, node_curr_copy);
diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c
index 2250b8135d7..306b6e74350 100644
--- a/source/blender/bmesh/intern/bmesh_interp.c
+++ b/source/blender/bmesh/intern/bmesh_interp.c
@@ -397,8 +397,8 @@ static float bm_loop_flip_equotion(float mat[2][2], float b[2], const float targ
return mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0];
}
-static void bm_loop_flip_disp(float source_axis_x[3], float source_axis_y[3],
- float target_axis_x[3], float target_axis_y[3], float disp[3])
+static void bm_loop_flip_disp(const float source_axis_x[3], const float source_axis_y[3],
+ const float target_axis_x[3], const float target_axis_y[3], float disp[3])
{
float vx[3], vy[3], coord[3];
float n[3], vec[3];
diff --git a/source/blender/bmesh/intern/bmesh_interp.h b/source/blender/bmesh/intern/bmesh_interp.h
index 2a3b5190ece..c605ad31ae7 100644
--- a/source/blender/bmesh/intern/bmesh_interp.h
+++ b/source/blender/bmesh/intern/bmesh_interp.h
@@ -33,9 +33,9 @@ void BM_vert_interp_from_face(BMesh *bm, BMVert *v, BMFace *source);
void BM_data_interp_from_verts(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v, const float fac);
void BM_data_interp_from_edges(BMesh *bm, BMEdge *e1, BMEdge *e2, BMEdge *e, const float fac);
void BM_data_interp_face_vert_edge(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v, BMEdge *e1, const float fac);
-void BM_data_layer_add(BMesh *em, CustomData *data, int type);
+void BM_data_layer_add(BMesh *bm, CustomData *data, int type);
void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name);
-void BM_data_layer_free(BMesh *em, CustomData *data, int type);
+void BM_data_layer_free(BMesh *bm, CustomData *data, int type);
void BM_data_layer_free_n(BMesh *bm, CustomData *data, int type, int n);
void BM_data_layer_copy(BMesh *bm, CustomData *data, int type, int src_n, int dst_n);
diff --git a/source/blender/bmesh/intern/bmesh_iterators_inline.h b/source/blender/bmesh/intern/bmesh_iterators_inline.h
index 6a0eb0e0a30..b9733d4702f 100644
--- a/source/blender/bmesh/intern/bmesh_iterators_inline.h
+++ b/source/blender/bmesh/intern/bmesh_iterators_inline.h
@@ -80,60 +80,70 @@ BLI_INLINE bool BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *da
break;
case BM_EDGES_OF_VERT:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_VERT);
iter->begin = (BMIter__begin_cb)bmiter__edge_of_vert_begin;
iter->step = (BMIter__step_cb)bmiter__edge_of_vert_step;
iter->data.edge_of_vert.vdata = (BMVert *)data;
break;
case BM_FACES_OF_VERT:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_VERT);
iter->begin = (BMIter__begin_cb)bmiter__face_of_vert_begin;
iter->step = (BMIter__step_cb)bmiter__face_of_vert_step;
iter->data.face_of_vert.vdata = (BMVert *)data;
break;
case BM_LOOPS_OF_VERT:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_VERT);
iter->begin = (BMIter__begin_cb)bmiter__loop_of_vert_begin;
iter->step = (BMIter__step_cb)bmiter__loop_of_vert_step;
iter->data.loop_of_vert.vdata = (BMVert *)data;
break;
case BM_VERTS_OF_EDGE:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_EDGE);
iter->begin = (BMIter__begin_cb)bmiter__vert_of_edge_begin;
iter->step = (BMIter__step_cb)bmiter__vert_of_edge_step;
iter->data.vert_of_edge.edata = (BMEdge *)data;
break;
case BM_FACES_OF_EDGE:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_EDGE);
iter->begin = (BMIter__begin_cb)bmiter__face_of_edge_begin;
iter->step = (BMIter__step_cb)bmiter__face_of_edge_step;
iter->data.face_of_edge.edata = (BMEdge *)data;
break;
case BM_VERTS_OF_FACE:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_FACE);
iter->begin = (BMIter__begin_cb)bmiter__vert_of_face_begin;
iter->step = (BMIter__step_cb)bmiter__vert_of_face_step;
iter->data.vert_of_face.pdata = (BMFace *)data;
break;
case BM_EDGES_OF_FACE:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_FACE);
iter->begin = (BMIter__begin_cb)bmiter__edge_of_face_begin;
iter->step = (BMIter__step_cb)bmiter__edge_of_face_step;
iter->data.edge_of_face.pdata = (BMFace *)data;
break;
case BM_LOOPS_OF_FACE:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_FACE);
iter->begin = (BMIter__begin_cb)bmiter__loop_of_face_begin;
iter->step = (BMIter__step_cb)bmiter__loop_of_face_step;
iter->data.loop_of_face.pdata = (BMFace *)data;
break;
case BM_LOOPS_OF_LOOP:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_LOOP);
iter->begin = (BMIter__begin_cb)bmiter__loop_of_loop_begin;
iter->step = (BMIter__step_cb)bmiter__loop_of_loop_step;
iter->data.loop_of_loop.ldata = (BMLoop *)data;
break;
case BM_LOOPS_OF_EDGE:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_EDGE);
iter->begin = (BMIter__begin_cb)bmiter__loop_of_edge_begin;
iter->step = (BMIter__step_cb)bmiter__loop_of_edge_step;
iter->data.loop_of_edge.edata = (BMEdge *)data;
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
index e23a5721234..19e6f646564 100644
--- a/source/blender/bmesh/intern/bmesh_marking.c
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -864,7 +864,9 @@ void BM_select_history_validate(BMesh *bm)
}
}
-/* utility function */
+/**
+ * Get the active mesh element (with active-face fallback).
+ */
bool BM_select_history_active_get(BMesh *bm, BMEditSelection *ese)
{
BMEditSelection *ese_last = bm->selected.last;
@@ -887,7 +889,8 @@ bool BM_select_history_active_get(BMesh *bm, BMEditSelection *ese)
ese->htype = ese_last->htype;
}
}
- else if (efa) { /* no */
+ else if (efa) {
+ /* no edit-selection, fallback to active face */
ese->ele = (BMElem *)efa;
ese->htype = BM_FACE;
}
@@ -899,6 +902,27 @@ bool BM_select_history_active_get(BMesh *bm, BMEditSelection *ese)
return true;
}
+/**
+ * Return a map from BMVert/Edge/Face -> BMEditSelection
+ */
+GHash *BM_select_history_map_create(BMesh *bm)
+{
+ BMEditSelection *ese;
+ GHash *map;
+
+ if (BLI_listbase_is_empty(&bm->selected)) {
+ return NULL;
+ }
+
+ map = BLI_ghash_ptr_new(__func__);
+
+ for (ese = bm->selected.first; ese; ese = ese->next) {
+ BLI_ghash_insert(map, ese->ele, ese);
+ }
+
+ return map;
+}
+
void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hflag,
const bool respecthide, const bool overwrite, const char hflag_test)
{
diff --git a/source/blender/bmesh/intern/bmesh_marking.h b/source/blender/bmesh/intern/bmesh_marking.h
index 99456ea2c98..9e0c0923164 100644
--- a/source/blender/bmesh/intern/bmesh_marking.h
+++ b/source/blender/bmesh/intern/bmesh_marking.h
@@ -98,7 +98,14 @@ void _bm_select_history_store_after(BMesh *bm, BMEditSelection *ese_ref, BMHead
void _bm_select_history_store_after_notest(BMesh *bm, BMEditSelection *ese_ref, BMHeader *ele);
void BM_select_history_validate(BMesh *bm);
-void BM_select_history_clear(BMesh *em);
+void BM_select_history_clear(BMesh *bm);
bool BM_select_history_active_get(BMesh *bm, struct BMEditSelection *ese);
+struct GHash *BM_select_history_map_create(BMesh *bm);
+
+#define BM_SELECT_HISTORY_BACKUP(bm) { \
+ ListBase _bm_prev_selected = (bm)->selected; BLI_listbase_clear(&(bm)->selected)
+
+#define BM_SELECT_HISTORY_RESTORE(bm) \
+ (bm)->selected = _bm_prev_selected; } (void)0
#endif /* __BMESH_MARKING_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index e66d1263578..b16ea42304a 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -641,11 +641,13 @@ static void bm_mesh_loops_calc_normals(BMesh *bm, const float (*vcos)[3], const
copy_v3_v3(nor, lnor);
}
}
+ else {
+ /* We still have to clear the stack! */
+ while (BLI_SMALLSTACK_POP(normal));
+ }
}
} while ((l_curr = l_curr->next) != l_first);
}
-
- BLI_SMALLSTACK_FREE(normal);
}
#if 0 /* Unused currently */
@@ -764,6 +766,8 @@ void bmesh_edit_begin(BMesh *UNUSED(bm), BMOpTypeFlag UNUSED(type_flag))
*/
void bmesh_edit_end(BMesh *bm, BMOpTypeFlag type_flag)
{
+ ListBase select_history;
+
/* BMO_OPTYPE_FLAG_UNTAN_MULTIRES disabled for now, see comment above in bmesh_edit_begin. */
#ifdef BMOP_UNTAN_MULTIRES_ENABLED
/* switch multires data into tangent space */
@@ -782,9 +786,19 @@ void bmesh_edit_end(BMesh *bm, BMOpTypeFlag type_flag)
BM_mesh_normals_update(bm);
}
+
+ if ((type_flag & BMO_OPTYPE_FLAG_SELECT_VALIDATE) == 0) {
+ select_history = bm->selected;
+ BLI_listbase_clear(&bm->selected);
+ }
+
if (type_flag & BMO_OPTYPE_FLAG_SELECT_FLUSH) {
BM_mesh_select_mode_flush(bm);
}
+
+ if ((type_flag & BMO_OPTYPE_FLAG_SELECT_VALIDATE) == 0) {
+ bm->selected = select_history;
+ }
}
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
@@ -800,7 +814,7 @@ void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
}
/* skip if we only need to operate on one element */
-#pragma omp parallel sections if ((!ELEM5(htype_needed, BM_VERT, BM_EDGE, BM_FACE, BM_LOOP, BM_FACE | BM_LOOP)) && \
+#pragma omp parallel sections if ((!ELEM(htype_needed, BM_VERT, BM_EDGE, BM_FACE, BM_LOOP, BM_FACE | BM_LOOP)) && \
(bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT))
{
#pragma omp section
@@ -1054,7 +1068,7 @@ void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
}
/* skip if we only need to operate on one element */
-#pragma omp parallel sections if ((!ELEM3(htype_needed, BM_VERT, BM_EDGE, BM_FACE)) && \
+#pragma omp parallel sections if ((!ELEM(htype_needed, BM_VERT, BM_EDGE, BM_FACE)) && \
(bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT))
{
#pragma omp section
@@ -1179,7 +1193,11 @@ int BM_mesh_elem_count(BMesh *bm, const char htype)
*
* WARNING: Be careful if you keep pointers to affected BM elements, or arrays, when using this func!
*/
-void BM_mesh_remap(BMesh *bm, unsigned int *vert_idx, unsigned int *edge_idx, unsigned int *face_idx)
+void BM_mesh_remap(
+ BMesh *bm,
+ const unsigned int *vert_idx,
+ const unsigned int *edge_idx,
+ const unsigned int *face_idx)
{
/* Mapping old to new pointers. */
GHash *vptr_map = NULL, *eptr_map = NULL, *fptr_map = NULL;
@@ -1192,18 +1210,23 @@ void BM_mesh_remap(BMesh *bm, unsigned int *vert_idx, unsigned int *edge_idx, un
if (!(vert_idx || edge_idx || face_idx))
return;
+ BM_mesh_elem_table_ensure(
+ bm,
+ (vert_idx ? BM_VERT : 0) |
+ (edge_idx ? BM_EDGE : 0) |
+ (face_idx ? BM_FACE : 0));
+
/* Remap Verts */
if (vert_idx) {
BMVert **verts_pool, *verts_copy, **vep;
int i, totvert = bm->totvert;
- unsigned int *new_idx = NULL;
+ const unsigned int *new_idx;
/* Init the old-to-new vert pointers mapping */
vptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap vert pointers mapping", bm->totvert);
/* Make a copy of all vertices. */
- verts_pool = MEM_callocN(sizeof(BMVert *) * totvert, "BM_mesh_remap verts pool");
- BM_iter_as_array(bm, BM_VERTS_OF_MESH, NULL, (void **)verts_pool, totvert);
+ verts_pool = bm->vtable;
verts_copy = MEM_mallocN(sizeof(BMVert) * totvert, "BM_mesh_remap verts copy");
for (i = totvert, ve = verts_copy + totvert - 1, vep = verts_pool + totvert - 1; i--; ve--, vep--) {
*ve = **vep;
@@ -1221,8 +1244,8 @@ void BM_mesh_remap(BMesh *bm, unsigned int *vert_idx, unsigned int *edge_idx, un
BLI_ghash_insert(vptr_map, (void *)*vep, (void *)new_vep);
}
bm->elem_index_dirty |= BM_VERT;
+ bm->elem_table_dirty |= BM_VERT;
- MEM_freeN(verts_pool);
MEM_freeN(verts_copy);
}
@@ -1230,14 +1253,13 @@ void BM_mesh_remap(BMesh *bm, unsigned int *vert_idx, unsigned int *edge_idx, un
if (edge_idx) {
BMEdge **edges_pool, *edges_copy, **edp;
int i, totedge = bm->totedge;
- unsigned int *new_idx = NULL;
+ const unsigned int *new_idx;
/* Init the old-to-new vert pointers mapping */
eptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap edge pointers mapping", bm->totedge);
/* Make a copy of all vertices. */
- edges_pool = MEM_callocN(sizeof(BMEdge *) * totedge, "BM_mesh_remap edges pool");
- BM_iter_as_array(bm, BM_EDGES_OF_MESH, NULL, (void **)edges_pool, totedge);
+ edges_pool = bm->etable;
edges_copy = MEM_mallocN(sizeof(BMEdge) * totedge, "BM_mesh_remap edges copy");
for (i = totedge, ed = edges_copy + totedge - 1, edp = edges_pool + totedge - 1; i--; ed--, edp--) {
*ed = **edp;
@@ -1254,8 +1276,8 @@ void BM_mesh_remap(BMesh *bm, unsigned int *vert_idx, unsigned int *edge_idx, un
/* printf("mapping edge from %d to %d (%p/%p to %p)\n", i, *new_idx, *edp, edges_pool[i], new_edp);*/
}
bm->elem_index_dirty |= BM_EDGE;
+ bm->elem_table_dirty |= BM_EDGE;
- MEM_freeN(edges_pool);
MEM_freeN(edges_copy);
}
@@ -1263,14 +1285,13 @@ void BM_mesh_remap(BMesh *bm, unsigned int *vert_idx, unsigned int *edge_idx, un
if (face_idx) {
BMFace **faces_pool, *faces_copy, **fap;
int i, totface = bm->totface;
- unsigned int *new_idx = NULL;
+ const unsigned int *new_idx;
/* Init the old-to-new vert pointers mapping */
fptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap face pointers mapping", bm->totface);
/* Make a copy of all vertices. */
- faces_pool = MEM_callocN(sizeof(BMFace *) * totface, "BM_mesh_remap faces pool");
- BM_iter_as_array(bm, BM_FACES_OF_MESH, NULL, (void **)faces_pool, totface);
+ faces_pool = bm->ftable;
faces_copy = MEM_mallocN(sizeof(BMFace) * totface, "BM_mesh_remap faces copy");
for (i = totface, fa = faces_copy + totface - 1, fap = faces_pool + totface - 1; i--; fa--, fap--) {
*fa = **fap;
@@ -1287,8 +1308,8 @@ void BM_mesh_remap(BMesh *bm, unsigned int *vert_idx, unsigned int *edge_idx, un
}
bm->elem_index_dirty |= BM_FACE | BM_LOOP;
+ bm->elem_table_dirty |= BM_FACE;
- MEM_freeN(faces_pool);
MEM_freeN(faces_copy);
}
diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h
index 3923c2515a3..22e50502aee 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.h
+++ b/source/blender/bmesh/intern/bmesh_mesh.h
@@ -50,7 +50,7 @@ void BM_mesh_elem_index_validate(BMesh *bm, const char *location, const char *fu
const char *msg_a, const char *msg_b);
#ifndef NDEBUG
-bool BM_mesh_elem_table_check(BMesh *em);
+bool BM_mesh_elem_table_check(BMesh *bm);
#endif
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype);
@@ -69,7 +69,11 @@ BMFace *BM_face_at_index_find(BMesh *bm, const int index);
int BM_mesh_elem_count(BMesh *bm, const char htype);
-void BM_mesh_remap(BMesh *bm, unsigned int *vert_idx, unsigned int *edge_idx, unsigned int *face_idx);
+void BM_mesh_remap(
+ BMesh *bm,
+ const unsigned int *vert_idx,
+ const unsigned int *edge_idx,
+ const unsigned int *face_idx);
typedef struct BMAllocTemplate {
int totvert, totedge, totloop, totface;
diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c
index 2d7a2cf93d6..6e8591da0f3 100644
--- a/source/blender/bmesh/intern/bmesh_mods.c
+++ b/source/blender/bmesh/intern/bmesh_mods.c
@@ -32,12 +32,19 @@
#include "BLI_math.h"
#include "BLI_array.h"
+#include "BLI_alloca.h"
+#include "BLI_stackdefines.h"
+#include "BLI_linklist_stack.h"
+#include "BLI_sort_utils.h"
#include "BKE_customdata.h"
#include "bmesh.h"
#include "intern/bmesh_private.h"
+// #define DEBUG_PRINT
+
+
/**
* \brief Dissolve Vert
*
@@ -416,6 +423,547 @@ BMFace *BM_face_split_n(BMesh *bm, BMFace *f,
return f_new;
}
+
+/* -------------------------------------------------------------------- */
+/* Face Split Edge-Net */
+
+/** \name BM_face_split_edgenet and helper functions.
+ *
+ * \note Don't use #BM_edge_is_wire or #BM_edge_is_boundary
+ * since we need to take flagged faces into account.
+ * Also take care accessing e->l directly.
+ *
+ * \{ */
+
+/* Note: All these flags _must_ be cleared on exit */
+
+/* face is apart of the edge-net (including the original face we're splitting) */
+#define FACE_NET _FLAG_WALK
+/* edge is apart of the edge-net we're filling */
+#define EDGE_NET _FLAG_WALK
+/* tag verts we've visit */
+#define VERT_VISIT _FLAG_WALK
+
+struct VertOrder {
+ float angle;
+ BMVert *v;
+};
+
+static unsigned int bm_edge_flagged_radial_count(BMEdge *e)
+{
+ unsigned int count = 0;
+ BMLoop *l;
+
+ if ((l = e->l)) {
+ do {
+ if (BM_ELEM_API_FLAG_TEST(l->f, FACE_NET)) {
+ count++;
+ }
+ } while ((l = l->radial_next) != e->l);
+ }
+ return count;
+}
+
+static BMLoop *bm_edge_flagged_radial_first(BMEdge *e)
+{
+ BMLoop *l;
+
+ if ((l = e->l)) {
+ do {
+ if (BM_ELEM_API_FLAG_TEST(l->f, FACE_NET)) {
+ return l;
+ }
+ } while ((l = l->radial_next) != e->l);
+ }
+ return NULL;
+}
+
+static bool bm_face_split_edgenet_find_loop_pair(
+ BMVert *v_init, const float face_normal[3],
+ BMEdge *e_pair[2])
+{
+ /* Always find one boundary edge (to determine winding)
+ * and one wire (if available), otherwise another boundary.
+ */
+ BMIter iter;
+ BMEdge *e;
+
+ /* detect winding */
+ BMLoop *l_walk;
+ bool swap;
+
+ BLI_SMALLSTACK_DECLARE(edges_boundary, BMEdge *);
+ BLI_SMALLSTACK_DECLARE(edges_wire, BMEdge *);
+ int edges_boundary_len = 0;
+ int edges_wire_len = 0;
+
+ BM_ITER_ELEM (e, &iter, v_init, BM_EDGES_OF_VERT) {
+ if (BM_ELEM_API_FLAG_TEST(e, EDGE_NET)) {
+ const unsigned int count = bm_edge_flagged_radial_count(e);
+ if (count == 1) {
+ BLI_SMALLSTACK_PUSH(edges_boundary, e);
+ edges_boundary_len++;
+ }
+ else if (count == 0) {
+ BLI_SMALLSTACK_PUSH(edges_wire, e);
+ edges_wire_len++;
+ }
+ }
+ }
+
+ /* first edge should always be boundary */
+ if (edges_boundary_len == 0) {
+ return false;
+ }
+ e_pair[0] = BLI_SMALLSTACK_POP(edges_boundary);
+
+ /* attempt one boundary and one wire, or 2 boundary */
+ if (edges_wire_len == 0) {
+ if (edges_boundary_len >= 2) {
+ e_pair[1] = BLI_SMALLSTACK_POP(edges_boundary);
+ }
+ else {
+ /* one boundary and no wire */
+ return false;
+ }
+ }
+ else {
+ e_pair[1] = BLI_SMALLSTACK_POP(edges_wire);
+
+ if (edges_wire_len > 1) {
+ BMVert *v_prev = BM_edge_other_vert(e_pair[0], v_init);
+ BMVert *v_next;
+ float angle_best;
+
+ v_next = BM_edge_other_vert(e_pair[1], v_init);
+ angle_best = angle_on_axis_v3v3v3_v3(v_prev->co, v_init->co, v_next->co, face_normal);
+
+ while ((e = BLI_SMALLSTACK_POP(edges_wire))) {
+ float angle_test;
+ v_next = BM_edge_other_vert(e, v_init);
+ angle_test = angle_on_axis_v3v3v3_v3(v_prev->co, v_init->co, v_next->co, face_normal);
+ if (angle_test < angle_best) {
+ angle_best = angle_test;
+ e_pair[1] = e;
+ }
+ }
+ }
+ }
+
+
+ /* flip based on winding */
+ l_walk = bm_edge_flagged_radial_first(e_pair[0]);
+ swap = false;
+ if (face_normal == l_walk->f->no) {
+ swap = !swap;
+ }
+ if (l_walk->v != v_init) {
+ swap = !swap;
+ }
+ if (swap) {
+ SWAP(BMEdge *, e_pair[0], e_pair[1]);
+ }
+
+ return true;
+}
+
+static bool bm_face_split_edgenet_find_loop_walk(
+ BMVert *v_init, const float face_normal[3],
+ /* cache to avoid realloc every time */
+ struct VertOrder *edge_order, const unsigned int edge_order_len,
+ BMEdge *e_pair[2])
+{
+ /* fast-path for the common case (avoid push-pop).
+ * Also avoids tagging as visited since we know we
+ * can't reach these verts some other way */
+#define USE_FASTPATH_NOFORK
+
+ BMVert *v;
+ BMVert *v_dst;
+ bool found = false;
+
+ struct VertOrder *eo;
+ STACK_DECLARE(edge_order);
+
+ /* store visited verts so we can clear the visit flag after execution */
+ BLI_SMALLSTACK_DECLARE(vert_visit, BMVert *);
+
+ /* likely this will stay very small
+ * all verts pushed into this stack _must_ have their previous edges set! */
+ BLI_SMALLSTACK_DECLARE(vert_stack, BMVert *);
+ BLI_SMALLSTACK_DECLARE(vert_stack_next, BMVert *);
+
+ STACK_INIT(edge_order, edge_order_len);
+
+ /* start stepping */
+ v = BM_edge_other_vert(e_pair[0], v_init);
+ v->e = e_pair[0];
+ BLI_SMALLSTACK_PUSH(vert_stack, v);
+
+ v_dst = BM_edge_other_vert(e_pair[1], v_init);
+
+#ifdef DEBUG_PRINT
+ printf("%s: vert (search) %d\n", __func__, BM_elem_index_get(v_init));
+#endif
+
+ /* This loop will keep stepping over the best possible edge,
+ * in most cases it finds the direct route to close the face.
+ *
+ * In cases where paths can't be closed,
+ * alternatives are stored in the 'vert_stack'.
+ */
+ while ((v = BLI_SMALLSTACK_POP_EX(vert_stack, vert_stack_next))) {
+ BMIter eiter;
+ BMEdge *e_next;
+
+#ifdef USE_FASTPATH_NOFORK
+walk_nofork:
+#else
+ BLI_SMALLSTACK_PUSH(vert_visit, v);
+ BM_ELEM_API_FLAG_ENABLE(v, VERT_VISIT);
+#endif
+
+ BLI_assert(STACK_SIZE(edge_order) == 0);
+
+ /* check if we're done! */
+ if (v == v_dst) {
+ found = true;
+ goto finally;
+ }
+
+ BM_ITER_ELEM (e_next, &eiter, v, BM_EDGES_OF_VERT) {
+ if ((v->e != e_next) &&
+ (BM_ELEM_API_FLAG_TEST(e_next, EDGE_NET)) &&
+ (bm_edge_flagged_radial_count(e_next) < 2))
+ {
+ BMVert *v_next;
+
+ v_next = BM_edge_other_vert(e_next, v);
+
+#ifdef DEBUG_PRINT
+ /* indent and print */
+ {
+ BMVert *_v = v;
+ do {
+ printf(" ");
+ } while ((_v = BM_edge_other_vert(_v->e, _v)) != v_init);
+ printf("vert %d -> %d (add=%d)\n",
+ BM_elem_index_get(v), BM_elem_index_get(v_next),
+ BM_ELEM_API_FLAG_TEST(v_next, VERT_VISIT) == 0);
+ }
+#endif
+
+ if (!BM_ELEM_API_FLAG_TEST(v_next, VERT_VISIT)) {
+ eo = STACK_PUSH_RET_PTR(edge_order);
+ eo->v = v_next;
+
+ v_next->e = e_next;
+ }
+ }
+ }
+
+#ifdef USE_FASTPATH_NOFORK
+ if (STACK_SIZE(edge_order) == 1) {
+ eo = STACK_POP_PTR(edge_order);
+ v = eo->v;
+
+ goto walk_nofork;
+ }
+#endif
+
+ /* sort by angle if needed */
+ if (STACK_SIZE(edge_order) > 1) {
+ unsigned int j;
+ BMVert *v_prev = BM_edge_other_vert(v->e, v);
+
+ for (j = 0; j < STACK_SIZE(edge_order); j++) {
+ edge_order[j].angle = angle_signed_on_axis_v3v3v3_v3(v_prev->co, v->co, edge_order[j].v->co, face_normal);
+ }
+ qsort(edge_order, STACK_SIZE(edge_order), sizeof(struct VertOrder), BLI_sortutil_cmp_float_reverse);
+
+#ifdef USE_FASTPATH_NOFORK
+ /* only tag forks */
+ BLI_SMALLSTACK_PUSH(vert_visit, v);
+ BM_ELEM_API_FLAG_ENABLE(v, VERT_VISIT);
+#endif
+ }
+
+ while ((eo = STACK_POP_PTR(edge_order))) {
+ BLI_SMALLSTACK_PUSH(vert_stack_next, eo->v);
+ }
+
+ if (!BLI_SMALLSTACK_IS_EMPTY(vert_stack_next)) {
+ BLI_SMALLSTACK_SWAP(vert_stack, vert_stack_next);
+ }
+ }
+
+
+finally:
+ /* clear flag for next execution */
+ while ((v = BLI_SMALLSTACK_POP(vert_visit))) {
+ BM_ELEM_API_FLAG_DISABLE(v, VERT_VISIT);
+ }
+
+ return found;
+
+#undef USE_FASTPATH_NOFORK
+}
+
+static bool bm_face_split_edgenet_find_loop(
+ BMVert *v_init, const float face_normal[3],
+ /* cache to avoid realloc every time */
+ struct VertOrder *edge_order, const unsigned int edge_order_len,
+ BMVert **r_face_verts, int *r_face_verts_len)
+{
+ BMEdge *e_pair[2];
+ BMVert *v;
+
+ if (!bm_face_split_edgenet_find_loop_pair(v_init, face_normal, e_pair)) {
+ return false;
+ }
+
+ BLI_assert((bm_edge_flagged_radial_count(e_pair[0]) == 1) ||
+ (bm_edge_flagged_radial_count(e_pair[1]) == 1));
+
+ if (bm_face_split_edgenet_find_loop_walk(v_init, face_normal, edge_order, edge_order_len, e_pair)) {
+ unsigned int i = 0;
+
+ r_face_verts[i++] = v_init;
+ v = BM_edge_other_vert(e_pair[1], v_init);
+ do {
+ r_face_verts[i++] = v;
+ } while ((v = BM_edge_other_vert(v->e, v)) != v_init);
+ *r_face_verts_len = i;
+ return (i > 2) ? true : false;
+ }
+ else {
+ return false;
+ }
+}
+
+/**
+ * Splits a face into many smaller faces defined by an edge-net.
+ * handle customdata and degenerate cases.
+ *
+ * - isolated holes or unsupported face configurations, will be ignored.
+ * - customdata calculations aren't efficient
+ * (need to calculate weights for each vert).
+ */
+bool BM_face_split_edgenet(
+ BMesh *bm,
+ BMFace *f, BMEdge **edge_net, const int edge_net_len,
+ BMFace ***r_face_arr, int *r_face_arr_len)
+{
+ /* re-use for new face verts */
+ BMVert **face_verts;
+ int face_verts_len;
+
+ BMFace **face_arr = NULL;
+ BLI_array_declare(face_arr);
+
+ BMVert **vert_queue;
+ STACK_DECLARE(vert_queue);
+ int i;
+
+ struct VertOrder *edge_order;
+ const unsigned int edge_order_len = edge_net_len + 2;
+
+ BMVert *v;
+
+ BMLoop *l_iter, *l_first;
+
+
+ if (!edge_net_len) {
+ if (r_face_arr) {
+ *r_face_arr = NULL;
+ *r_face_arr_len = 0;
+ }
+ return false;
+ }
+
+ /* over-alloc (probably 2-4 is only used in most cases), for the biggest-fan */
+ edge_order = BLI_array_alloca(edge_order, edge_order_len);
+
+ /* use later */
+ face_verts = BLI_array_alloca(face_verts, edge_net_len + f->len);
+
+ vert_queue = BLI_array_alloca(vert_queue, edge_net_len + f->len);
+ STACK_INIT(vert_queue, f->len + edge_net_len);
+
+ BLI_assert(BM_ELEM_API_FLAG_TEST(f, FACE_NET) == 0);
+ BM_ELEM_API_FLAG_ENABLE(f, FACE_NET);
+
+#ifdef DEBUG
+ for (i = 0; i < edge_net_len; i++) {
+ BLI_assert(BM_ELEM_API_FLAG_TEST(edge_net[i], EDGE_NET) == 0);
+ BLI_assert(BM_edge_in_face(edge_net[i], f) == false);
+ }
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BLI_assert(BM_ELEM_API_FLAG_TEST(l_iter->e, EDGE_NET) == 0);
+ } while ((l_iter = l_iter->next) != l_first);
+#endif
+
+
+ for (i = 0; i < edge_net_len; i++) {
+ BM_ELEM_API_FLAG_ENABLE(edge_net[i], EDGE_NET);
+ }
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_ELEM_API_FLAG_ENABLE(l_iter->e, EDGE_NET);
+ } while ((l_iter = l_iter->next) != l_first);
+
+
+ /* any vert can be used to begin with */
+ STACK_PUSH(vert_queue, l_first->v);
+
+ while ((v = STACK_POP(vert_queue))) {
+ if (bm_face_split_edgenet_find_loop(v, f->no, edge_order, edge_order_len, face_verts, &face_verts_len)) {
+ BMFace *f_new;
+
+ f_new = BM_face_create_verts(bm, face_verts, face_verts_len, f, BM_CREATE_NOP, false);
+
+ for (i = 0; i < edge_net_len; i++) {
+ BLI_assert(BM_ELEM_API_FLAG_TEST(edge_net[i], EDGE_NET));
+ }
+
+ if (f_new) {
+ bool l_prev_is_boundary;
+ BLI_array_append(face_arr, f_new);
+ copy_v3_v3(f_new->no, f->no);
+
+ BM_ELEM_API_FLAG_ENABLE(f_new, FACE_NET);
+
+ /* add new verts to keep finding loops for
+ * (verts between boundary and manifold edges) */
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
+ l_prev_is_boundary = (bm_edge_flagged_radial_count(l_iter->prev->e) == 1);
+ do {
+ bool l_iter_is_boundary = (bm_edge_flagged_radial_count(l_iter->e) == 1);
+ if (l_prev_is_boundary != l_iter_is_boundary) {
+ STACK_PUSH(vert_queue, l_iter->v);
+ }
+ l_prev_is_boundary = l_iter_is_boundary;
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+ }
+
+
+ if (CustomData_has_math(&bm->ldata)) {
+ /* reuse VERT_VISIT here to tag vert's already interpolated */
+ BMIter iter;
+ BMLoop *l_other;
+
+ /* see: #BM_loop_interp_from_face for similar logic */
+ void **blocks = BLI_array_alloca(blocks, f->len);
+ float (*cos_2d)[2] = BLI_array_alloca(cos_2d, f->len);
+ float *w = BLI_array_alloca(w, f->len);
+ float axis_mat[3][3];
+ float co[2];
+
+ /* interior loops */
+ axis_dominant_v3_to_m3(axis_mat, f->no);
+
+
+ /* first simply copy from existing face */
+ i = 0;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_ITER_ELEM (l_other, &iter, l_iter->v, BM_LOOPS_OF_VERT) {
+ if ((l_other->f != f) && BM_ELEM_API_FLAG_TEST(l_other->f, FACE_NET)) {
+ CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata,
+ l_iter->head.data, &l_other->head.data);
+ }
+ }
+ /* tag not to interpolate */
+ BM_ELEM_API_FLAG_ENABLE(l_iter->v, VERT_VISIT);
+
+
+ mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
+ blocks[i] = l_iter->head.data;
+
+ } while (i++, (l_iter = l_iter->next) != l_first);
+
+
+ for (i = 0; i < edge_net_len; i++) {
+ BM_ITER_ELEM (v, &iter, edge_net[i], BM_VERTS_OF_EDGE) {
+ if (!BM_ELEM_API_FLAG_TEST(v, VERT_VISIT)) {
+ BMIter liter;
+
+ BM_ELEM_API_FLAG_ENABLE(v, VERT_VISIT);
+
+ /* interpolate this loop, then copy to the rest */
+ l_first = NULL;
+
+ BM_ITER_ELEM (l_iter, &liter, v, BM_LOOPS_OF_VERT) {
+ if (BM_ELEM_API_FLAG_TEST(l_iter->f, FACE_NET)) {
+ if (l_first == NULL) {
+ mul_v2_m3v3(co, axis_mat, v->co);
+ interp_weights_poly_v2(w, cos_2d, f->len, co);
+ CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, f->len, l_iter->head.data);
+ l_first = l_iter;
+ }
+ else {
+ CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata,
+ l_first->head.data, &l_iter->head.data);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+
+ /* cleanup */
+ for (i = 0; i < edge_net_len; i++) {
+ BM_ELEM_API_FLAG_DISABLE(edge_net[i], EDGE_NET);
+ /* from interp only */
+ BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v1, VERT_VISIT);
+ BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v2, VERT_VISIT);
+ }
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_ELEM_API_FLAG_DISABLE(l_iter->e, EDGE_NET);
+ /* from interp only */
+ BM_ELEM_API_FLAG_DISABLE(l_iter->v, VERT_VISIT);
+ } while ((l_iter = l_iter->next) != l_first);
+
+ if (BLI_array_count(face_arr)) {
+ bmesh_face_swap_data(f, face_arr[0]);
+ BM_face_kill(bm, face_arr[0]);
+ face_arr[0] = f;
+ }
+ else {
+ BM_ELEM_API_FLAG_DISABLE(f, FACE_NET);
+ }
+
+ for (i = 0; i < BLI_array_count(face_arr); i++) {
+ BM_ELEM_API_FLAG_DISABLE(face_arr[i], FACE_NET);
+ }
+
+ if (r_face_arr) {
+ *r_face_arr = face_arr;
+ *r_face_arr_len = BLI_array_count(face_arr);
+ }
+ else {
+ if (face_arr) {
+ MEM_freeN(face_arr);
+ }
+ }
+
+ return true;
+}
+
+#undef FACE_NET
+#undef VERT_VISIT
+#undef EDGE_NET
+
+/** \} */
+
+
/**
* \brief Vert Collapse Faces
*
@@ -589,22 +1137,32 @@ BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
/**
* \brief Edge Split
*
- * Splits an edge. \a v should be one of the vertices in \a e and defines
- * the "from" end of the splitting operation: the new vertex will be
- * \a percent of the way from \a v to the other end.
- * The newly created edge is attached to \a v and is returned in \a r_e.
- * The original edge \a e will be the other half of the split.
+ * <pre>
+ * Before: v
+ * +-----------------------------------+
+ * e
+ *
+ * After: v v_new (returned)
+ * +-----------------+-----------------+
+ * r_e e
+ * </pre>
*
- * \return The new vert
+ * \param e The edge to split.
+ * \param v One of the vertices in \a e and defines the the "from" end of the splitting operation,
+ * the new vertex will be \a fac of the way from \a v to the other end.
+ * \param r_e The newly created edge.
+ * \return The new vertex.
*/
-BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float percent)
+BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac)
{
- BMVert *v_new, *v2;
+ BMVert *v_new, *v_other;
BMFace **oldfaces = NULL;
BMEdge *e_dummy;
BLI_array_staticdeclare(oldfaces, 32);
const bool do_mdisp = (e->l && CustomData_has_layer(&bm->ldata, CD_MDISPS));
+ BLI_assert(BM_vert_in_edge(e, v) == true);
+
/* we need this for handling multi-res */
if (!r_e) {
r_e = &e_dummy;
@@ -629,22 +1187,22 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float perce
}
}
- v2 = BM_edge_other_vert(e, v);
+ v_other = BM_edge_other_vert(e, v);
v_new = bmesh_semv(bm, v, e, r_e);
BLI_assert(v_new != NULL);
+ BLI_assert(BM_vert_in_edge(*r_e, v) && BM_vert_in_edge(*r_e, v_new));
+ BLI_assert(BM_vert_in_edge(e, v_new) && BM_vert_in_edge(e, v_other));
- sub_v3_v3v3(v_new->co, v2->co, v->co);
- madd_v3_v3v3fl(v_new->co, v->co, v_new->co, percent);
+ sub_v3_v3v3(v_new->co, v_other->co, v->co);
+ madd_v3_v3v3fl(v_new->co, v->co, v_new->co, fac);
- if (r_e) {
- (*r_e)->head.hflag = e->head.hflag;
- BM_elem_attrs_copy(bm, bm, e, *r_e);
- }
+ (*r_e)->head.hflag = e->head.hflag;
+ BM_elem_attrs_copy(bm, bm, e, *r_e);
/* v->v_new->v2 */
- BM_data_interp_face_vert_edge(bm, v2, v, v_new, e, percent);
- BM_data_interp_from_verts(bm, v, v2, v_new, percent);
+ BM_data_interp_face_vert_edge(bm, v_other, v, v_new, e, fac);
+ BM_data_interp_from_verts(bm, v, v_other, v_new, fac);
if (do_mdisp) {
int i, j;
diff --git a/source/blender/bmesh/intern/bmesh_mods.h b/source/blender/bmesh/intern/bmesh_mods.h
index 7c81e6b750e..59aee323bba 100644
--- a/source/blender/bmesh/intern/bmesh_mods.h
+++ b/source/blender/bmesh/intern/bmesh_mods.h
@@ -45,6 +45,10 @@ BMFace *BM_face_split_n(BMesh *bm, BMFace *f,
float cos[][3], int n,
BMLoop **r_l, BMEdge *example);
+bool BM_face_split_edgenet(BMesh *bm, BMFace *f,
+ BMEdge **edge_net, const int edge_net_len,
+ BMFace ***r_face_arr, int *r_face_arr_len);
+
BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac,
const bool do_del, const bool join_faces, const bool kill_degenerate_faces);
BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index 7c77302c942..74bd9110d8c 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -115,7 +115,7 @@ static BMOpDefine bmo_smooth_vert_def = {
},
{{{'\0'}}}, /* no output */
bmo_smooth_vert_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -138,7 +138,7 @@ static BMOpDefine bmo_smooth_laplacian_vert_def = {
},
{{{'\0'}}}, /* no output */
bmo_smooth_laplacian_vert_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -154,7 +154,8 @@ static BMOpDefine bmo_recalc_face_normals_def = {
},
{{{'\0'}}}, /* no output */
bmo_recalc_face_normals_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -180,7 +181,8 @@ static BMOpDefine bmo_region_extend_def = {
{{'\0'}},
},
bmo_region_extend_exec,
- BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -201,7 +203,10 @@ static BMOpDefine bmo_rotate_edges_def = {
{{'\0'}},
},
bmo_rotate_edges_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -218,7 +223,8 @@ static BMOpDefine bmo_reverse_faces_def = {
},
{{{'\0'}}}, /* no output */
bmo_reverse_faces_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -240,7 +246,10 @@ static BMOpDefine bmo_bisect_edges_def = {
{{'\0'}},
},
bmo_bisect_edges_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -266,7 +275,9 @@ static BMOpDefine bmo_mirror_def = {
{{'\0'}},
},
bmo_mirror_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -291,7 +302,7 @@ static BMOpDefine bmo_find_doubles_def = {
{{'\0'}},
},
bmo_find_doubles_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -309,7 +320,10 @@ static BMOpDefine bmo_remove_doubles_def = {
},
{{{'\0'}}}, /* no output */
bmo_remove_doubles_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -328,7 +342,10 @@ static BMOpDefine bmo_automerge_def = {
},
{{{'\0'}}}, /* no output */
bmo_automerge_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -344,7 +361,10 @@ static BMOpDefine bmo_collapse_def = {
},
{{{'\0'}}}, /* no output */
bmo_collapse_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -361,7 +381,7 @@ static BMOpDefine bmo_pointmerge_facedata_def = {
},
{{{'\0'}}}, /* no output */
bmo_pointmerge_facedata_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -379,7 +399,7 @@ static BMOpDefine bmo_average_vert_facedata_def = {
},
{{{'\0'}}}, /* no output */
bmo_average_vert_facedata_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -396,7 +416,10 @@ static BMOpDefine bmo_pointmerge_def = {
},
{{{'\0'}}}, /* no output */
bmo_pointmerge_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -412,7 +435,7 @@ static BMOpDefine bmo_collapse_uvs_def = {
},
{{{'\0'}}}, /* no output */
bmo_collapse_uvs_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -431,7 +454,10 @@ static BMOpDefine bmo_weld_verts_def = {
},
{{{'\0'}}}, /* no output */
bmo_weld_verts_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -451,7 +477,7 @@ static BMOpDefine bmo_create_vert_def = {
{{'\0'}},
},
bmo_create_vert_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -476,7 +502,10 @@ static BMOpDefine bmo_join_triangles_def = {
{{'\0'}},
},
bmo_join_triangles_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -504,7 +533,10 @@ static BMOpDefine bmo_contextual_create_def = {
{{'\0'}},
},
bmo_contextual_create_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -527,7 +559,9 @@ static BMOpDefine bmo_bridge_loops_def = {
{{'\0'}},
},
bmo_bridge_loops_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -551,7 +585,8 @@ static BMOpDefine bmo_grid_fill_def = {
{{'\0'}},
},
bmo_grid_fill_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
@@ -573,7 +608,8 @@ static BMOpDefine bmo_holes_fill_def = {
{{'\0'}},
},
bmo_holes_fill_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
@@ -596,7 +632,7 @@ static BMOpDefine bmo_face_attribute_fill_def = {
{{'\0'}},
},
bmo_face_attribute_fill_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -619,7 +655,8 @@ static BMOpDefine bmo_edgeloop_fill_def = {
{{'\0'}},
},
bmo_edgeloop_fill_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
@@ -643,7 +680,8 @@ static BMOpDefine bmo_edgenet_fill_def = {
{{'\0'}},
},
bmo_edgenet_fill_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -667,7 +705,7 @@ static BMOpDefine bmo_edgenet_prepare_def = {
{{'\0'}},
},
bmo_edgenet_prepare_exec,
- BMO_OPTYPE_FLAG_NOP,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -686,7 +724,7 @@ static BMOpDefine bmo_rotate_def = {
},
{{{'\0'}}}, /* no output */
bmo_rotate_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -704,7 +742,7 @@ static BMOpDefine bmo_translate_def = {
},
{{{'\0'}}}, /* no output */
bmo_translate_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -722,7 +760,7 @@ static BMOpDefine bmo_scale_def = {
},
{{{'\0'}}}, /* no output */
bmo_scale_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
@@ -742,7 +780,7 @@ static BMOpDefine bmo_transform_def = {
},
{{{'\0'}}}, /* no output */
bmo_transform_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -760,7 +798,7 @@ static BMOpDefine bmo_object_load_bmesh_def = {
},
{{{'\0'}}}, /* no output */
bmo_object_load_bmesh_exec,
- BMO_OPTYPE_FLAG_NOP,
+ (BMO_OPTYPE_FLAG_NOP),
};
@@ -782,7 +820,7 @@ static BMOpDefine bmo_bmesh_to_mesh_def = {
},
{{{'\0'}}}, /* no output */
bmo_bmesh_to_mesh_exec,
- BMO_OPTYPE_FLAG_NOP,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -804,7 +842,7 @@ static BMOpDefine bmo_mesh_to_bmesh_def = {
},
{{{'\0'}}}, /* no output */
bmo_mesh_to_bmesh_exec,
- BMO_OPTYPE_FLAG_NOP,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -816,6 +854,7 @@ static BMOpDefine bmo_extrude_discrete_faces_def = {
"extrude_discrete_faces",
/* slots_in */
{{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
+ {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */
{{'\0'}},
},
/* slots_out */
@@ -823,7 +862,7 @@ static BMOpDefine bmo_extrude_discrete_faces_def = {
{{'\0'}},
},
bmo_extrude_discrete_faces_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -836,6 +875,7 @@ static BMOpDefine bmo_extrude_edge_only_def = {
"extrude_edge_only",
/* slots_in */
{{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input vertices */
+ {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */
{{'\0'}},
},
/* slots_out */
@@ -843,7 +883,7 @@ static BMOpDefine bmo_extrude_edge_only_def = {
{{'\0'}},
},
bmo_extrude_edge_only_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -855,6 +895,7 @@ static BMOpDefine bmo_extrude_vert_indiv_def = {
"extrude_vert_indiv",
/* slots_in */
{{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
+ {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */
{{'\0'}},
},
/* slots_out */
@@ -863,7 +904,7 @@ static BMOpDefine bmo_extrude_vert_indiv_def = {
{{'\0'}},
},
bmo_extrude_vert_indiv_exec,
- BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -875,6 +916,7 @@ static BMOpDefine bmo_connect_verts_def = {
"connect_verts",
/* slots_in */
{{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
+ {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
{"check_degenerate", BMO_OP_SLOT_BOOL}, /* prevent splits with overlaps & intersections */
{{'\0'}},
},
@@ -883,7 +925,9 @@ static BMOpDefine bmo_connect_verts_def = {
{{'\0'}},
},
bmo_connect_verts_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -904,7 +948,9 @@ static BMOpDefine bmo_connect_verts_nonplanar_def = {
{{'\0'}},
},
bmo_connect_verts_nonplanar_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -916,6 +962,8 @@ static BMOpDefine bmo_connect_vert_pair_def = {
"connect_vert_pair",
/* slots_in */
{{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
+ {"verts_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
+ {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
{{'\0'}},
},
/* slots_out */
@@ -923,7 +971,9 @@ static BMOpDefine bmo_connect_vert_pair_def = {
{{'\0'}},
},
bmo_connect_vert_pair_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
@@ -938,6 +988,7 @@ static BMOpDefine bmo_extrude_face_region_def = {
{{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* edges and faces */
{"edges_exclude", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_EMPTY}},
{"use_keep_orig", BMO_OP_SLOT_BOOL}, /* keep original geometry */
+ {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */
{{'\0'}},
},
/* slots_out */
@@ -945,7 +996,7 @@ static BMOpDefine bmo_extrude_face_region_def = {
{{'\0'}},
},
bmo_extrude_face_region_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -956,11 +1007,15 @@ static BMOpDefine bmo_dissolve_verts_def = {
/* slots_in */
{{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
{"use_face_split", BMO_OP_SLOT_BOOL},
+ {"use_boundary_tear", BMO_OP_SLOT_BOOL},
{{'\0'}},
},
{{{'\0'}}}, /* no output */
bmo_dissolve_verts_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -979,7 +1034,10 @@ static BMOpDefine bmo_dissolve_edges_def = {
{{'\0'}},
},
bmo_dissolve_edges_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -997,7 +1055,10 @@ static BMOpDefine bmo_dissolve_faces_def = {
{{'\0'}},
},
bmo_dissolve_faces_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1019,7 +1080,10 @@ static BMOpDefine bmo_dissolve_limit_def = {
{{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
{{'\0'}}},
bmo_dissolve_limit_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1037,7 +1101,10 @@ static BMOpDefine bmo_dissolve_degenerate_def = {
/* slots_out */
{{{'\0'}}},
bmo_dissolve_degenerate_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1058,7 +1125,9 @@ static BMOpDefine bmo_triangulate_def = {
{{'\0'}},
},
bmo_triangulate_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1075,7 +1144,10 @@ static BMOpDefine bmo_unsubdivide_def = {
},
{{{'\0'}}}, /* no output */
bmo_unsubdivide_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1113,7 +1185,10 @@ static BMOpDefine bmo_subdivide_edges_def = {
{{'\0'}},
},
bmo_subdivide_edges_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1135,7 +1210,10 @@ static BMOpDefine bmo_subdivide_edgering_def = {
{{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
{{'\0'}}},
bmo_subdivide_edgering_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1159,7 +1237,10 @@ static BMOpDefine bmo_bisect_plane_def = {
{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input and output geometry (result of cut) */
{{'\0'}}},
bmo_bisect_plane_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1176,7 +1257,9 @@ static BMOpDefine bmo_delete_def = {
},
{{{'\0'}}}, /* no output */
bmo_delete_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1191,6 +1274,7 @@ static BMOpDefine bmo_duplicate_def = {
{{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
/* destination bmesh, if NULL will use current on */
{"dest", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_BMESH}},
+ {"use_select_history", BMO_OP_SLOT_BOOL},
{{'\0'}},
},
/* slots_out */
@@ -1206,7 +1290,8 @@ static BMOpDefine bmo_duplicate_def = {
{{'\0'}},
},
bmo_duplicate_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1231,7 +1316,8 @@ static BMOpDefine bmo_split_def = {
{{'\0'}},
},
bmo_split_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1258,7 +1344,8 @@ static BMOpDefine bmo_spin_def = {
{{'\0'}},
},
bmo_spin_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
@@ -1281,7 +1368,7 @@ static BMOpDefine bmo_similar_faces_def = {
{{'\0'}},
},
bmo_similar_faces_exec,
- BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1303,7 +1390,7 @@ static BMOpDefine bmo_similar_edges_def = {
{{'\0'}},
},
bmo_similar_edges_exec,
- BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1325,7 +1412,7 @@ static BMOpDefine bmo_similar_verts_def = {
{{'\0'}},
},
bmo_similar_verts_exec,
- BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1342,7 +1429,7 @@ static BMOpDefine bmo_rotate_uvs_def = {
},
{{{'\0'}}}, /* no output */
bmo_rotate_uvs_exec,
- BMO_OPTYPE_FLAG_NOP,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -1358,7 +1445,7 @@ static BMOpDefine bmo_reverse_uvs_def = {
},
{{{'\0'}}}, /* no output */
bmo_reverse_uvs_exec,
- BMO_OPTYPE_FLAG_NOP,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -1375,7 +1462,7 @@ static BMOpDefine bmo_rotate_colors_def = {
},
{{{'\0'}}}, /* no output */
bmo_rotate_colors_exec,
- BMO_OPTYPE_FLAG_NOP,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -1391,7 +1478,7 @@ static BMOpDefine bmo_reverse_colors_def = {
},
{{{'\0'}}}, /* no output */
bmo_reverse_colors_exec,
- BMO_OPTYPE_FLAG_NOP,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -1413,7 +1500,9 @@ static BMOpDefine bmo_split_edges_def = {
{{'\0'}},
},
bmo_split_edges_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1435,7 +1524,8 @@ static BMOpDefine bmo_create_grid_def = {
{{'\0'}},
},
bmo_create_grid_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1457,7 +1547,8 @@ static BMOpDefine bmo_create_uvsphere_def = {
{{'\0'}},
},
bmo_create_uvsphere_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1478,7 +1569,8 @@ static BMOpDefine bmo_create_icosphere_def = {
{{'\0'}},
},
bmo_create_icosphere_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1497,7 +1589,8 @@ static BMOpDefine bmo_create_monkey_def = {
{{'\0'}},
},
bmo_create_monkey_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1522,7 +1615,8 @@ static BMOpDefine bmo_create_cone_def = {
{{'\0'}},
},
bmo_create_cone_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1543,7 +1637,8 @@ static BMOpDefine bmo_create_circle_def = {
{{'\0'}},
},
bmo_create_circle_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1563,7 +1658,8 @@ static BMOpDefine bmo_create_cube_def = {
{{'\0'}},
},
bmo_create_cube_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1580,6 +1676,7 @@ static BMOpDefine bmo_bevel_def = {
{"segments", BMO_OP_SLOT_INT}, /* number of segments in bevel */
{"profile", BMO_OP_SLOT_FLT}, /* profile shape, 0->1 (.5=>round) */
{"vertex_only", BMO_OP_SLOT_BOOL}, /* only bevel vertices, not edges */
+ {"material", BMO_OP_SLOT_INT}, /* material for bevel faces, -1 means get from adjacent faces */
{{'\0'}},
},
/* slots_out */
@@ -1588,7 +1685,10 @@ static BMOpDefine bmo_bevel_def = {
},
bmo_bevel_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1610,7 +1710,10 @@ static BMOpDefine bmo_beautify_fill_def = {
{{'\0'}},
},
bmo_beautify_fill_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1632,7 +1735,9 @@ static BMOpDefine bmo_triangle_fill_def = {
{{'\0'}},
},
bmo_triangle_fill_exec,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1652,7 +1757,8 @@ static BMOpDefine bmo_solidify_def = {
{{'\0'}},
},
bmo_solidify_face_region_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1676,7 +1782,8 @@ static BMOpDefine bmo_inset_individual_def = {
{{'\0'}},
},
bmo_inset_individual_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC, /* caller needs to handle BMO_OPTYPE_FLAG_SELECT_FLUSH */
+ /* caller needs to handle BMO_OPTYPE_FLAG_SELECT_FLUSH */
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -1703,7 +1810,8 @@ static BMOpDefine bmo_inset_region_def = {
{{'\0'}},
},
bmo_inset_region_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1732,7 +1840,9 @@ static BMOpDefine bmo_wireframe_def = {
{{'\0'}},
},
bmo_wireframe_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1755,7 +1865,9 @@ static BMOpDefine bmo_poke_def = {
{{'\0'}},
},
bmo_poke_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
#ifdef WITH_BULLET
@@ -1789,7 +1901,9 @@ static BMOpDefine bmo_convex_hull_def = {
{{'\0'}},
},
bmo_convex_hull_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
#endif
@@ -1816,7 +1930,9 @@ static BMOpDefine bmo_symmetrize_def = {
{{'\0'}},
},
bmo_symmetrize_exec,
- BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
const BMOpDefine *bmo_opdefines[] = {
diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h
index 7fad3a8c20e..287aafc8f9f 100644
--- a/source/blender/bmesh/intern/bmesh_operator_api.h
+++ b/source/blender/bmesh/intern/bmesh_operator_api.h
@@ -182,8 +182,9 @@ typedef struct BMOpSlot {
typedef enum {
BMO_OPTYPE_FLAG_NOP = 0,
BMO_OPTYPE_FLAG_UNTAN_MULTIRES = (1 << 0), /* switch from multires tangent space to absolute coordinates */
- BMO_OPTYPE_FLAG_NORMALS_CALC = (1 << 1), /*switch from multires tangent space to absolute coordinates*/
- BMO_OPTYPE_FLAG_SELECT_FLUSH = (1 << 2) /*switch from multires tangent space to absolute coordinates*/
+ BMO_OPTYPE_FLAG_NORMALS_CALC = (1 << 1),
+ BMO_OPTYPE_FLAG_SELECT_FLUSH = (1 << 2),
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE = (1 << 3),
} BMOpTypeFlag;
typedef struct BMOperator {
@@ -337,7 +338,8 @@ void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *op, const char htype, cons
void BMO_mesh_selected_remap(BMesh *bm,
BMOpSlot *slot_vert_map,
BMOpSlot *slot_edge_map,
- BMOpSlot *slot_face_map);
+ BMOpSlot *slot_face_map,
+ const bool check_select);
/* copies the values from another slot to the end of the output slot */
#define BMO_slot_buffer_append(op_src, slots_src, slot_name_src, \
diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c
index 7f872613896..b041c010c22 100644
--- a/source/blender/bmesh/intern/bmesh_operators.c
+++ b/source/blender/bmesh/intern/bmesh_operators.c
@@ -605,7 +605,8 @@ void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char hty
void BMO_mesh_selected_remap(BMesh *bm,
BMOpSlot *slot_vert_map,
BMOpSlot *slot_edge_map,
- BMOpSlot *slot_face_map)
+ BMOpSlot *slot_face_map,
+ const bool check_select)
{
if (bm->selected.first) {
BMEditSelection *ese, *ese_next;
@@ -623,7 +624,7 @@ void BMO_mesh_selected_remap(BMesh *bm,
ese->ele = BMO_slot_map_elem_get(slot_elem_map, ese->ele);
if (UNLIKELY((ese->ele == NULL) ||
- (BM_elem_flag_test(ese->ele, BM_ELEM_SELECT) == false)))
+ (check_select && (BM_elem_flag_test(ese->ele, BM_ELEM_SELECT) == false))))
{
BLI_remlink(&bm->selected, ese);
MEM_freeN(ese);
@@ -764,6 +765,9 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_
BMOpSlot *output = BMO_slot_get(slot_args, slot_name);
int totelement = 0, i = 0;
+ BLI_assert(output->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
+ BLI_assert(((output->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
+
if (htype & BM_VERT) totelement += bm->totvert;
if (htype & BM_EDGE) totelement += bm->totedge;
if (htype & BM_FACE) totelement += bm->totface;
@@ -811,7 +815,11 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, BMOpSlot slot_
{
BMOpSlot *output = BMO_slot_get(slot_args, slot_name);
int totelement = 0, i = 0;
- const int respecthide = (op->flag & BMO_FLAG_RESPECT_HIDE) != 0;
+ const bool respecthide = ((op->flag & BMO_FLAG_RESPECT_HIDE) != 0) && ((hflag & BM_ELEM_HIDDEN) == 0);
+
+ BLI_assert(output->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
+ BLI_assert(((output->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
+ BLI_assert((output->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) == 0);
if (test_for_enabled)
totelement = BM_mesh_elem_hflag_count_enabled(bm, htype, hflag, respecthide);
@@ -951,14 +959,15 @@ static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op,
BLI_assert(op->slots_in == slot_args || op->slots_out == slot_args);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
+ BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
+ BLI_assert((slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) == 0);
+
if (test_for_enabled)
totelement = BMO_mesh_enabled_flag_count(bm, htype, oflag);
else
totelement = BMO_mesh_disabled_flag_count(bm, htype, oflag);
- BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
- BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
-
if (totelement) {
BMIter iter;
BMHeader *ele;
@@ -1034,6 +1043,7 @@ void BMO_slot_buffer_hflag_enable(BMesh *bm,
BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
+ BLI_assert((slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) == 0);
for (i = 0; i < slot->len; i++, data++) {
if (!(htype & (*data)->head.htype))
@@ -1654,7 +1664,6 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
char slot_name[64] = {0};
int i, type;
bool noslot, state;
- char htype;
/* basic useful info to help find where bmop formatting strings fail */
@@ -1729,9 +1738,8 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
break;
case 'm':
{
- int size, c;
-
- c = NEXT_CHAR(fmt);
+ int size;
+ const char c = NEXT_CHAR(fmt);
fmt++;
if (c == '3') size = 3;
@@ -1800,22 +1808,23 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt,
BMO_slot_float_set(op->slots_in, slot_name, va_arg(vlist, double));
}
else {
- bool stop = false;
+ char htype = 0;
- htype = 0;
while (1) {
- switch (NEXT_CHAR(fmt)) {
- case 'f': htype |= BM_FACE; break;
- case 'e': htype |= BM_EDGE; break;
- case 'v': htype |= BM_VERT; break;
- default:
- stop = true;
- break;
- }
- if (stop) {
+ char htype_set;
+ const char c = NEXT_CHAR(fmt);
+ if (c == 'f') htype_set = BM_FACE;
+ else if (c == 'e') htype_set = BM_EDGE;
+ else if (c == 'v') htype_set = BM_VERT;
+ else {
break;
}
+ if (UNLIKELY(htype & htype_set)) {
+ GOTO_ERROR("htype duplicated");
+ }
+
+ htype |= htype_set;
fmt++;
}
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index 307c391a406..9a0fce9dba0 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -854,7 +854,7 @@ void BM_face_triangulate(BMesh *bm, BMFace *f,
l_tri[1]->v,
l_tri[2]->v};
- f_new = BM_face_create_verts(bm, v_tri, 3, f, false, true);
+ f_new = BM_face_create_verts(bm, v_tri, 3, f, BM_CREATE_NOP, true);
l_new = BM_FACE_FIRST_LOOP(f_new);
BLI_assert(v_tri[0] == l_new->v);
diff --git a/source/blender/bmesh/intern/bmesh_private.h b/source/blender/bmesh/intern/bmesh_private.h
index 731c36437d5..102a677943b 100644
--- a/source/blender/bmesh/intern/bmesh_private.h
+++ b/source/blender/bmesh/intern/bmesh_private.h
@@ -64,7 +64,8 @@ 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 */
+ _FLAG_OVERLAP = (1 << 2), /* general overlap flag */
+ _FLAG_WALK = (1 << 3), /* general walk flag (keep clean) */
};
#define BM_ELEM_API_FLAG_ENABLE(element, f) { ((element)->head.api_flag |= (f)); } (void)0
diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
index 606e93d4a85..685e5443583 100644
--- a/source/blender/bmesh/intern/bmesh_queries.c
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -183,6 +183,26 @@ BMLoop *BM_loop_other_vert_loop(BMLoop *l, BMVert *v)
}
/**
+ * Check if verts share a face.
+ */
+bool BM_vert_pair_share_face_check(
+ BMVert *v_a, BMVert *v_b)
+{
+ if (v_a->e && v_b->e) {
+ BMIter iter;
+ BMFace *f;
+
+ BM_ITER_ELEM (f, &iter, v_a, BM_FACES_OF_VERT) {
+ if (BM_vert_in_face(f, v_b)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+/**
* Given 2 verts, find the smallest face they share and give back both loops.
*/
BMFace *BM_vert_pair_share_face_by_len(
diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h
index 21d20976901..0d47633dc73 100644
--- a/source/blender/bmesh/intern/bmesh_queries.h
+++ b/source/blender/bmesh/intern/bmesh_queries.h
@@ -27,29 +27,31 @@
* \ingroup bmesh
*/
-bool BM_vert_in_face(BMFace *f, BMVert *v);
-int BM_verts_in_face_count(BMFace *f, BMVert **varr, int len);
-bool BM_verts_in_face(BMFace *f, BMVert **varr, int len);
-
-bool BM_edge_in_face(BMEdge *e, BMFace *f);
-BLI_INLINE bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l);
-
-BLI_INLINE bool BM_vert_in_edge(const BMEdge *e, const BMVert *v);
-BLI_INLINE bool BM_verts_in_edge(const BMVert *v1, const BMVert *v2, const BMEdge *e);
-
-float BM_edge_calc_length(BMEdge *e);
-float BM_edge_calc_length_squared(BMEdge *e);
-bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb);
-bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb);
-BLI_INLINE BMVert *BM_edge_other_vert(BMEdge *e, const BMVert *v);
-BMLoop *BM_edge_other_loop(BMEdge *e, BMLoop *l);
-BMLoop *BM_face_other_edge_loop(BMFace *f, BMEdge *e, BMVert *v);
-BMLoop *BM_loop_other_edge_loop(BMLoop *l, BMVert *v);
-BMLoop *BM_face_other_vert_loop(BMFace *f, BMVert *v_prev, BMVert *v);
-BMLoop *BM_loop_other_vert_loop(BMLoop *l, BMVert *v);
-BMLoop *BM_vert_step_fan_loop(BMLoop *l, BMEdge **e_step);
-BMLoop *BM_vert_find_first_loop(BMVert *v);
-
+bool BM_vert_in_face(BMFace *f, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_verts_in_face_count(BMFace *f, BMVert **varr, int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_verts_in_face(BMFace *f, BMVert **varr, int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+
+bool BM_edge_in_face(BMEdge *e, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+
+BLI_INLINE bool BM_vert_in_edge(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE bool BM_verts_in_edge(const BMVert *v1, const BMVert *v2, const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+
+float BM_edge_calc_length(BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_edge_calc_length_squared(BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb) ATTR_NONNULL();
+bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb) ATTR_NONNULL();
+BLI_INLINE BMVert *BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *BM_edge_other_loop(BMEdge *e, BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *BM_face_other_edge_loop(BMFace *f, BMEdge *e, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *BM_loop_other_edge_loop(BMLoop *l, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *BM_face_other_vert_loop(BMFace *f, BMVert *v_prev, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *BM_loop_other_vert_loop(BMLoop *l, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *BM_vert_step_fan_loop(BMLoop *l, BMEdge **e_step) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *BM_vert_find_first_loop(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+
+bool BM_vert_pair_share_face_check(
+ BMVert *v_a, BMVert *v_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMFace *BM_vert_pair_share_face_by_len(
BMVert *v_a, BMVert *v_b,
BMLoop **r_l_a, BMLoop **r_l_b,
@@ -59,95 +61,95 @@ BMFace *BM_vert_pair_share_face_by_angle(
BMLoop **r_l_a, BMLoop **r_l_b,
const bool allow_adjacent) ATTR_NONNULL();
-int BM_vert_edge_count_nonwire(BMVert *v);
-int BM_vert_edge_count(BMVert *v);
-int BM_edge_face_count(BMEdge *e);
-int BM_vert_face_count(BMVert *v);
-BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e);
+int BM_vert_edge_count_nonwire(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_vert_edge_count(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_edge_face_count(BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_vert_face_count(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_vert_is_edge_pair(BMVert *v);
-bool BM_vert_is_wire(const BMVert *v);
-BLI_INLINE bool BM_edge_is_wire(const BMEdge *e);
+bool BM_vert_is_edge_pair(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_vert_is_wire(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_vert_is_manifold(const BMVert *v);
-BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e);
-bool BM_vert_is_boundary(const BMVert *v);
-BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e);
-BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e);
-bool BM_edge_is_convex(const BMEdge *e);
+bool BM_vert_is_manifold(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_vert_is_boundary(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_edge_is_convex(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_loop_is_convex(const BMLoop *l);
-BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b);
+bool BM_loop_is_convex(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_loop_calc_face_angle(BMLoop *l);
-void BM_loop_calc_face_normal(BMLoop *l, float r_normal[3]);
+float BM_loop_calc_face_angle(BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void BM_loop_calc_face_normal(BMLoop *l, float r_normal[3]) ATTR_NONNULL();
void BM_loop_calc_face_direction(BMLoop *l, float r_normal[3]);
void BM_loop_calc_face_tangent(BMLoop *l, float r_tangent[3]);
-float BM_edge_calc_face_angle_ex(const BMEdge *e, const float fallback);
-float BM_edge_calc_face_angle(const BMEdge *e);
-float BM_edge_calc_face_angle_signed_ex(const BMEdge *e, const float fallback);
-float BM_edge_calc_face_angle_signed(const BMEdge *e);
-void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_tangent[3]);
+float BM_edge_calc_face_angle_ex(const BMEdge *e, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_edge_calc_face_angle(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_edge_calc_face_angle_signed_ex(const BMEdge *e, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_edge_calc_face_angle_signed(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_tangent[3]) ATTR_NONNULL();
-float BM_vert_calc_edge_angle(BMVert *v);
-float BM_vert_calc_shell_factor(BMVert *v);
-float BM_vert_calc_shell_factor_ex(BMVert *v, const char hflag);
-float BM_vert_calc_mean_tagged_edge_length(BMVert *v);
+float BM_vert_calc_edge_angle(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_vert_calc_shell_factor(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_vert_calc_shell_factor_ex(BMVert *v, const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_vert_calc_mean_tagged_edge_length(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BMLoop *BM_face_find_shortest_loop(BMFace *f);
-BMLoop *BM_face_find_longest_loop(BMFace *f);
+BMLoop *BM_face_find_shortest_loop(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *BM_face_find_longest_loop(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BMEdge *BM_edge_exists(BMVert *v1, BMVert *v2);
-BMEdge *BM_edge_find_double(BMEdge *e);
+BMEdge *BM_edge_exists(BMVert *v1, BMVert *v2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMEdge *BM_edge_find_double(BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_face_exists(BMVert **varr, int len, BMFace **r_existface);
+bool BM_face_exists(BMVert **varr, int len, BMFace **r_existface) ATTR_NONNULL(1);
-bool BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len);
-bool BM_face_exists_multi_edge(BMEdge **earr, int len);
+bool BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_face_exists_multi_edge(BMEdge **earr, int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_face_exists_overlap(BMVert **varr, const int len, BMFace **r_f_overlap);
-bool BM_face_exists_overlap_subset(BMVert **varr, const int len);
+bool BM_face_exists_overlap(BMVert **varr, const int len, BMFace **r_f_overlap) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+bool BM_face_exists_overlap_subset(BMVert **varr, const int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-int BM_face_share_face_count(BMFace *f_a, BMFace *f_b);
-int BM_face_share_edge_count(BMFace *f1, BMFace *f2);
+int BM_face_share_face_count(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_face_share_edge_count(BMFace *f1, BMFace *f2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_face_share_face_check(BMFace *f1, BMFace *f2);
-bool BM_face_share_edge_check(BMFace *f1, BMFace *f2);
-bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2);
-bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2);
-bool BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2);
+bool BM_face_share_face_check(BMFace *f1, BMFace *f2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_face_share_edge_check(BMFace *f1, BMFace *f2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2);
-BMLoop *BM_edge_vert_share_loop(BMLoop *l, BMVert *v);
-BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v);
-BMLoop *BM_face_edge_share_loop(BMFace *f, BMEdge *e);
+BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *BM_edge_vert_share_loop(BMLoop *l, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *BM_face_edge_share_loop(BMFace *f, BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2);
+void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2) ATTR_NONNULL();
void BM_edge_ordered_verts_ex(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2,
- const BMLoop *edge_loop);
+ const BMLoop *edge_loop) ATTR_NONNULL();
-bool BM_vert_is_all_edge_flag_test(const BMVert *v, const char hflag, const bool respect_hide);
-bool BM_vert_is_all_face_flag_test(const BMVert *v, const char hflag, const bool respect_hide);
-bool BM_edge_is_all_face_flag_test(const BMEdge *e, const char hflag, const bool respect_hide);
+bool BM_vert_is_all_edge_flag_test(const BMVert *v, const char hflag, const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_vert_is_all_face_flag_test(const BMVert *v, const char hflag, const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_edge_is_all_face_flag_test(const BMEdge *e, const char hflag, const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_edge_is_any_vert_flag_test(const BMEdge *e, const char hflag);
-bool BM_face_is_any_vert_flag_test(const BMFace *f, const char hflag);
-bool BM_face_is_any_edge_flag_test(const BMFace *f, const char hflag);
+bool BM_edge_is_any_vert_flag_test(const BMEdge *e, const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_face_is_any_vert_flag_test(const BMFace *f, const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_face_is_any_edge_flag_test(const BMFace *f, const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_face_is_normal_valid(const BMFace *f);
+bool BM_face_is_normal_valid(const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_mesh_calc_volume(BMesh *bm, bool is_signed);
+float BM_mesh_calc_volume(BMesh *bm, bool is_signed) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
BMElemFilterFunc filter_fn, void *user_data,
- const char hflag_test, const char htype_step);
+ const char hflag_test, const char htype_step) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
int BM_mesh_calc_edge_groups(BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
BMElemFilterFunc filter_fn, void *user_data,
- const char hflag_test);
+ const char hflag_test) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
/* not really any good place to put this */
-float bmesh_subd_falloff_calc(const int falloff, float val);
+float bmesh_subd_falloff_calc(const int falloff, float val) ATTR_WARN_UNUSED_RESULT;
#include "bmesh_queries_inline.h"
diff --git a/source/blender/bmesh/intern/bmesh_structure.h b/source/blender/bmesh/intern/bmesh_structure.h
index 8e721ddd229..d2ad655ae75 100644
--- a/source/blender/bmesh/intern/bmesh_structure.h
+++ b/source/blender/bmesh/intern/bmesh_structure.h
@@ -39,39 +39,37 @@
* descriptive comments. but seriously, don't use this stuff.
*/
-struct ListBase;
-
/* LOOP CYCLE MANAGEMENT */
-bool bmesh_loop_validate(BMFace *f);
+bool bmesh_loop_validate(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/* DISK CYCLE MANAGMENT */
-void bmesh_disk_edge_append(BMEdge *e, BMVert *v);
-void bmesh_disk_edge_remove(BMEdge *e, BMVert *v);
-BLI_INLINE BMEdge *bmesh_disk_edge_next_safe(const BMEdge *e, const BMVert *v);
-BLI_INLINE BMEdge *bmesh_disk_edge_prev_safe(const BMEdge *e, const BMVert *v);
-BLI_INLINE BMEdge *bmesh_disk_edge_next(const BMEdge *e, const BMVert *v);
-BLI_INLINE BMEdge *bmesh_disk_edge_prev(const BMEdge *e, const BMVert *v);
-int bmesh_disk_facevert_count(const BMVert *v);
-BMEdge *bmesh_disk_faceedge_find_first(const BMEdge *e, const BMVert *v);
-BMEdge *bmesh_disk_faceedge_find_next(const BMEdge *e, const BMVert *v);
+void bmesh_disk_edge_append(BMEdge *e, BMVert *v) ATTR_NONNULL();
+void bmesh_disk_edge_remove(BMEdge *e, BMVert *v) ATTR_NONNULL();
+BLI_INLINE BMEdge *bmesh_disk_edge_next_safe(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE BMEdge *bmesh_disk_edge_prev_safe(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE BMEdge *bmesh_disk_edge_next(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE BMEdge *bmesh_disk_edge_prev(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int bmesh_disk_facevert_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMEdge *bmesh_disk_faceedge_find_first(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMEdge *bmesh_disk_faceedge_find_next(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/* RADIAL CYCLE MANAGMENT */
-void bmesh_radial_append(BMEdge *e, BMLoop *l);
-void bmesh_radial_loop_remove(BMLoop *l, BMEdge *e);
+void bmesh_radial_append(BMEdge *e, BMLoop *l) ATTR_NONNULL();
+void bmesh_radial_loop_remove(BMLoop *l, BMEdge *e) ATTR_NONNULL(1);
/* note:
* bmesh_radial_loop_next(BMLoop *l) / prev.
* just use member access l->radial_next, l->radial_prev now */
-int bmesh_radial_facevert_count(const BMLoop *l, const BMVert *v);
-BMLoop *bmesh_radial_faceloop_find_first(const BMLoop *l, const BMVert *v);
-BMLoop *bmesh_radial_faceloop_find_next(const BMLoop *l, const BMVert *v);
-BMLoop *bmesh_radial_faceloop_find_vert(const BMFace *f, const BMVert *v);
-bool bmesh_radial_validate(int radlen, BMLoop *l);
+int bmesh_radial_facevert_count(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *bmesh_radial_faceloop_find_first(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *bmesh_radial_faceloop_find_next(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *bmesh_radial_faceloop_find_vert(const BMFace *f, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool bmesh_radial_validate(int radlen, BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/* EDGE UTILITIES */
-bool bmesh_edge_swapverts(BMEdge *e, BMVert *orig, BMVert *newv); /* relink edge */
-BMEdge *bmesh_disk_edge_exists(const BMVert *v1, const BMVert *v2);
-bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v);
+bool bmesh_edge_swapverts(BMEdge *e, BMVert *v_orig, BMVert *v_new) ATTR_NONNULL();
+BMEdge *bmesh_disk_edge_exists(const BMVert *v1, const BMVert *v2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
#include "intern/bmesh_structure_inline.h"
diff --git a/source/blender/bmesh/intern/bmesh_walkers.c b/source/blender/bmesh/intern/bmesh_walkers.c
index 8f74e98e762..6a5efbe70ac 100644
--- a/source/blender/bmesh/intern/bmesh_walkers.c
+++ b/source/blender/bmesh/intern/bmesh_walkers.c
@@ -47,7 +47,7 @@
*
* basic design pattern: the walker step function goes through it's
* list of possible choices for recursion, and recurses (by pushing a new state)
- * using the first non-visited one. this choise is the flagged as visited using
+ * using the first non-visited one. This choice is the flagged as visited using
* the ghash. each step may push multiple new states onto the worklist at once.
*
* - Walkers use tool flags, not header flags.