diff options
Diffstat (limited to 'source/blender/bmesh/intern')
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. |