From b7174c9320c5e3446d8237059841d982279e32e9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 1 Nov 2014 23:31:01 +0100 Subject: Fix connect-vertices failing for concave ngons Also add: - generic callback for bmesh elements. - ability to pass an existing array to a bmesh operator. --- .../blender/bmesh/intern/bmesh_callback_generic.c | 55 ++++++++++++++++++++++ .../blender/bmesh/intern/bmesh_callback_generic.h | 44 +++++++++++++++++ source/blender/bmesh/intern/bmesh_operator_api.h | 2 + source/blender/bmesh/intern/bmesh_operators.c | 33 +++++++++++-- source/blender/bmesh/intern/bmesh_queries.c | 20 ++++++++ source/blender/bmesh/intern/bmesh_queries.h | 3 ++ 6 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 source/blender/bmesh/intern/bmesh_callback_generic.c create mode 100644 source/blender/bmesh/intern/bmesh_callback_generic.h (limited to 'source/blender/bmesh/intern') diff --git a/source/blender/bmesh/intern/bmesh_callback_generic.c b/source/blender/bmesh/intern/bmesh_callback_generic.c new file mode 100644 index 00000000000..91fec392552 --- /dev/null +++ b/source/blender/bmesh/intern/bmesh_callback_generic.c @@ -0,0 +1,55 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/bmesh/intern/bmesh_callback_generic.c + * \ingroup bmesh + * + * BM construction functions. + */ + +#include "BLI_utildefines.h" + +#include "bmesh.h" + +#include "intern/bmesh_callback_generic.h" + +bool BM_elem_cb_check_hflag_ex(BMElem *ele, void *user_data) +{ + const unsigned int hflag_pair = GET_INT_FROM_POINTER(user_data); + const char hflag_p = (hflag_pair & 0xff); + const char hflag_n = (hflag_pair >> 8); + + return ((BM_elem_flag_test(ele, hflag_p) != 0) && + (BM_elem_flag_test(ele, hflag_n) == 0)); +} + +bool BM_elem_cb_check_hflag_enabled(BMElem *ele, void *user_data) +{ + const char hflag = GET_INT_FROM_POINTER(user_data); + + return (BM_elem_flag_test(ele, hflag) != 0); +} + +bool BM_elem_cb_check_hflag_disabled(BMElem *ele, void *user_data) +{ + const char hflag = GET_INT_FROM_POINTER(user_data); + + return (BM_elem_flag_test(ele, hflag) == 0); +} diff --git a/source/blender/bmesh/intern/bmesh_callback_generic.h b/source/blender/bmesh/intern/bmesh_callback_generic.h new file mode 100644 index 00000000000..8c46128f3b0 --- /dev/null +++ b/source/blender/bmesh/intern/bmesh_callback_generic.h @@ -0,0 +1,44 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BMESH_CALLBACK_GENERIC_H__ +#define __BMESH_CALLBACK_GENERIC_H__ + +/** \file blender/bmesh/intern/bmesh_callback_generic.h + * \ingroup bmesh + */ + +bool BM_elem_cb_check_hflag_enabled(BMElem *, void *user_data); +bool BM_elem_cb_check_hflag_disabled(BMElem *, void *user_data); +bool BM_elem_cb_check_hflag_ex(BMElem *, void *user_data); + +#define BM_elem_cb_check_hflag_ex_simple(type, hflag_p, hflag_n) \ + (bool (*)(type, void *))BM_elem_cb_check_hflag_ex, \ + SET_UINT_IN_POINTER(((hflag_p) | (hflag_n << 8))) + +#define BM_elem_cb_check_hflag_enabled_simple(type, hflag_p) \ + (bool (*)(type, void *))BM_elem_cb_check_hflag_enabled, \ + SET_UINT_IN_POINTER((hflag_p)) + +#define BM_elem_cb_check_hflag_disabled_simple(type, hflag_n) \ + (bool (*)(type, void *))BM_elem_cb_check_hflag_disabled, \ + SET_UINT_IN_POINTER(hflag_n) + +#endif /* __BMESH_CALLBACK_GENERIC_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index 287aafc8f9f..825bbb136b1 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -395,6 +395,8 @@ void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag); +void BMO_slot_buffer_from_array(BMOperator *op, BMOpSlot *slot, BMHeader **ele_buffer, int ele_buffer_len); + void BMO_slot_buffer_from_single(BMOperator *op, BMOpSlot *slot, BMHeader *ele); void *BMO_slot_buffer_get_single(BMOpSlot *slot); diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index b041c010c22..ba154b04838 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -900,6 +900,21 @@ void BMO_slot_buffer_from_single(BMOperator *op, BMOpSlot *slot, BMHeader *ele) *slot->data.buf = ele; } +void BMO_slot_buffer_from_array(BMOperator *op, BMOpSlot *slot, BMHeader **ele_buffer, int ele_buffer_len) +{ + BMO_ASSERT_SLOT_IN_OP(slot, op); + BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(slot->len == 0 || slot->len == ele_buffer_len); + + if (slot->data.buf == NULL) { + slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(*slot->data.buf) * ele_buffer_len); + } + + slot->len = ele_buffer_len; + memcpy(slot->data.buf, ele_buffer, ele_buffer_len * sizeof(*slot->data.buf)); +} + + void *BMO_slot_buffer_get_single(BMOpSlot *slot) { BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); @@ -1636,6 +1651,7 @@ static int BMO_opcode_from_opname_check(const char *opname) * * **Element Buffer** (#BMO_OP_SLOT_ELEMENT_BUF) * - `e` - single element vert/edge/face (use with #BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE). + * - `eb` - elem buffer, take an array and a length. * - `av` - all verts * - `ae` - all edges * - `af` - all faces @@ -1756,12 +1772,23 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, state = true; break; } - case 'e': /* single vert/edge/face */ + case 'e': { - BMHeader *ele = va_arg(vlist, void *); BMOpSlot *slot = BMO_slot_get(op->slots_in, slot_name); - BMO_slot_buffer_from_single(op, slot, ele); + if (NEXT_CHAR(fmt) == 'b') { + BMHeader **ele_buffer = va_arg(vlist, void *); + int ele_buffer_len = va_arg(vlist, int); + + BMO_slot_buffer_from_array(op, slot, ele_buffer, ele_buffer_len); + fmt++; + } + else { + /* single vert/edge/face */ + BMHeader *ele = va_arg(vlist, void *); + + BMO_slot_buffer_from_single(op, slot, ele); + } state = true; break; diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index f301108a6ae..ca40cf9e6c8 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -202,6 +202,26 @@ bool BM_vert_pair_share_face_check( return false; } +bool BM_vert_pair_share_face_check_cb( + BMVert *v_a, BMVert *v_b, + bool (*test_fn)(BMFace *, void *user_data), void *user_data) +{ + if (v_a->e && v_b->e) { + BMIter iter; + BMFace *f; + + BM_ITER_ELEM (f, &iter, v_a, BM_FACES_OF_VERT) { + if (test_fn(f, user_data)) { + 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. */ diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index 0d47633dc73..c8578a8b093 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -52,6 +52,9 @@ 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(); +bool BM_vert_pair_share_face_check_cb( + BMVert *v_a, BMVert *v_b, + bool (*test_fn)(BMFace *f, void *user_data), void *user_data) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3); BMFace *BM_vert_pair_share_face_by_len( BMVert *v_a, BMVert *v_b, BMLoop **r_l_a, BMLoop **r_l_b, -- cgit v1.2.3