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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2014-11-02 01:31:01 +0300
committerCampbell Barton <ideasman42@gmail.com>2014-11-02 02:09:14 +0300
commitb7174c9320c5e3446d8237059841d982279e32e9 (patch)
treedff0041b0846622804bd44fbd5137ddbd5996ff9
parente8b8ee7d280b99f6b3d253a30822c98a3c38c2c5 (diff)
Fix connect-vertices failing for concave ngons
Also add: - generic callback for bmesh elements. - ability to pass an existing array to a bmesh operator.
-rw-r--r--source/blender/bmesh/CMakeLists.txt2
-rw-r--r--source/blender/bmesh/bmesh.h1
-rw-r--r--source/blender/bmesh/intern/bmesh_callback_generic.c55
-rw-r--r--source/blender/bmesh/intern/bmesh_callback_generic.h44
-rw-r--r--source/blender/bmesh/intern/bmesh_operator_api.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c33
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c20
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.h3
-rw-r--r--source/blender/bmesh/operators/bmo_connect_pair.c147
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c52
10 files changed, 275 insertions, 84 deletions
diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
index 50d3ac30ddc..23737866bf2 100644
--- a/source/blender/bmesh/CMakeLists.txt
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -74,6 +74,8 @@ set(SRC
operators/bmo_utils.c
operators/bmo_wireframe.c
+ intern/bmesh_callback_generic.c
+ intern/bmesh_callback_generic.h
intern/bmesh_construct.c
intern/bmesh_construct.h
intern/bmesh_core.c
diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h
index 4efc6aa16f8..87b1818fa5d 100644
--- a/source/blender/bmesh/bmesh.h
+++ b/source/blender/bmesh/bmesh.h
@@ -243,6 +243,7 @@ extern "C" {
#include "intern/bmesh_error.h"
#include "intern/bmesh_core.h"
+#include "intern/bmesh_callback_generic.h"
#include "intern/bmesh_construct.h"
#include "intern/bmesh_delete.h"
#include "intern/bmesh_edgeloop.h"
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,
diff --git a/source/blender/bmesh/operators/bmo_connect_pair.c b/source/blender/bmesh/operators/bmo_connect_pair.c
index cfffb6021cf..916ea3ebcd9 100644
--- a/source/blender/bmesh/operators/bmo_connect_pair.c
+++ b/source/blender/bmesh/operators/bmo_connect_pair.c
@@ -230,23 +230,45 @@ static PathLinkState *state_dupe_add(
static PathLinkState *state_step__face_edges(
PathContext *pc,
PathLinkState *state, const PathLinkState *state_orig,
- BMLoop *l_iter, BMLoop *l_last)
+ BMLoop *l_iter, BMLoop *l_last,
+ float *r_dist_best)
{
+ BMLoop *l_iter_best = NULL;
+ float dist_best = *r_dist_best;
+
do {
if (state_isect_co_pair(pc, l_iter->v->co, l_iter->next->v->co)) {
- BMElem *ele_next = (BMElem *)l_iter->e;
- BMElem *ele_next_from = (BMElem *)l_iter->f;
+ float dist_test;
+ float co_isect[3];
- if (FACE_WALK_TEST((BMFace *)ele_next_from) &&
- (state_link_find(state, ele_next) == false))
- {
- if (state_orig->link_last != state->link_last) {
- state = state_dupe_add(pc, state, state_orig);
+ state_calc_co_pair(pc, l_iter->v->co, l_iter->next->v->co, co_isect);
+ dist_test = len_squared_v3v3(state->co_prev, co_isect);
+ if (dist_test < dist_best) {
+ BMElem *ele_next = (BMElem *)l_iter->e;
+ BMElem *ele_next_from = (BMElem *)l_iter->f;
+
+ if (FACE_WALK_TEST((BMFace *)ele_next_from) &&
+ (state_link_find(state, ele_next) == false))
+ {
+ dist_best = dist_test;
+ l_iter_best = l_iter;
}
- state_link_add(pc, state, ele_next, ele_next_from);
}
}
} while ((l_iter = l_iter->next) != l_last);
+
+ if ((l_iter = l_iter_best)) {
+ BMElem *ele_next = (BMElem *)l_iter->e;
+ BMElem *ele_next_from = (BMElem *)l_iter->f;
+
+ if (state_orig->link_last != state->link_last) {
+ state = state_dupe_add(pc, state, state_orig);
+ }
+ state_link_add(pc, state, ele_next, ele_next_from);
+ }
+
+ *r_dist_best = dist_best;
+
return state;
}
@@ -254,23 +276,40 @@ static PathLinkState *state_step__face_edges(
static PathLinkState *state_step__face_verts(
PathContext *pc,
PathLinkState *state, const PathLinkState *state_orig,
- BMLoop *l_iter, BMLoop *l_last)
+ BMLoop *l_iter, BMLoop *l_last, float *r_dist_best)
{
+ BMLoop *l_iter_best = NULL;
+ float dist_best = *r_dist_best;
+
do {
if (state_isect_co_exact(pc, l_iter->v->co)) {
- BMElem *ele_next = (BMElem *)l_iter->v;
- BMElem *ele_next_from = (BMElem *)l_iter->f;
+ const float dist_test = len_squared_v3v3(state->co_prev, l_iter->v->co);
+ if (dist_test < dist_best) {
+ BMElem *ele_next = (BMElem *)l_iter->v;
+ BMElem *ele_next_from = (BMElem *)l_iter->f;
- if (FACE_WALK_TEST((BMFace *)ele_next_from) &&
- state_link_find(state, ele_next) == false)
- {
- if (state_orig->link_last != state->link_last) {
- state = state_dupe_add(pc, state, state_orig);
+ if (FACE_WALK_TEST((BMFace *)ele_next_from) &&
+ state_link_find(state, ele_next) == false)
+ {
+ dist_best = dist_test;
+ l_iter_best = l_iter;
}
- state_link_add(pc, state, ele_next, ele_next_from);
}
}
} while ((l_iter = l_iter->next) != l_last);
+
+ if ((l_iter = l_iter_best)) {
+ BMElem *ele_next = (BMElem *)l_iter->v;
+ BMElem *ele_next_from = (BMElem *)l_iter->f;
+
+ if (state_orig->link_last != state->link_last) {
+ state = state_dupe_add(pc, state, state_orig);
+ }
+ state_link_add(pc, state, ele_next, ele_next_from);
+ }
+
+ *r_dist_best = dist_best;
+
return state;
}
@@ -290,20 +329,12 @@ static bool state_step(PathContext *pc, PathLinkState *state)
if ((l_start->f != ele_from) &&
FACE_WALK_TEST(l_start->f))
{
+ float dist_best = FLT_MAX;
/* very similar to block below */
- if (BM_vert_in_face(l_start->f, pc->v_b)) {
- if (state_orig.link_last != state->link_last) {
- state = state_dupe_add(pc, state, &state_orig);
- }
-
- state_link_add(pc, state, (BMElem *)pc->v_b, (BMElem *)l_start->f);
- }
- else {
- state = state_step__face_edges(pc, state, &state_orig,
- l_start->next, l_start);
- state = state_step__face_verts(pc, state, &state_orig,
- l_start->next->next, l_start);
- }
+ state = state_step__face_edges(pc, state, &state_orig,
+ l_start->next, l_start, &dist_best);
+ state = state_step__face_verts(pc, state, &state_orig,
+ l_start->next->next, l_start, &dist_best);
}
}
}
@@ -319,24 +350,14 @@ static bool state_step(PathContext *pc, PathLinkState *state)
if ((l_start->f != ele_from) &&
FACE_WALK_TEST(l_start->f))
{
+ float dist_best = FLT_MAX;
/* very similar to block above */
- if (BM_vert_in_face(l_start->f, pc->v_b)) {
- BMElem *ele_next = (BMElem *)pc->v_b;
- BMElem *ele_next_from = (BMElem *)l_start->f;
-
- if (state_orig.link_last != state->link_last) {
- state = state_dupe_add(pc, state, &state_orig);
- }
- state_link_add(pc, state, ele_next, ele_next_from);
- }
- else {
- state = state_step__face_edges(pc, state, &state_orig,
- l_start->next, l_start->prev);
- if (l_start->f->len > 3) {
- /* adjacent verts are handled in state_step__vert_edges */
- state = state_step__face_verts(pc, state, &state_orig,
- l_start->next->next, l_start->prev);
- }
+ state = state_step__face_edges(pc, state, &state_orig,
+ l_start->next, l_start->prev, &dist_best);
+ if (l_start->f->len > 3) {
+ /* adjacent verts are handled in state_step__vert_edges */
+ state = state_step__face_verts(pc, state, &state_orig,
+ l_start->next->next, l_start->prev, &dist_best);
}
}
}
@@ -351,31 +372,19 @@ static bool state_step(PathContext *pc, PathLinkState *state)
if (((BMElem *)e != ele_from) &&
VERT_WALK_TEST(v_other))
{
- if (v_other == pc->v_b) {
- BMElem *ele_next = (BMElem *)pc->v_b;
+ if (state_isect_co_exact(pc, v_other->co)) {
+ BMElem *ele_next = (BMElem *)v_other;
BMElem *ele_next_from = (BMElem *)e;
-
- if (state_orig.link_last != state->link_last) {
- state = state_dupe_add(pc, state, &state_orig);
- }
- state_link_add(pc, state, ele_next, ele_next_from);
- }
- else {
- if (state_isect_co_exact(pc, v_other->co)) {
- BMElem *ele_next = (BMElem *)v_other;
- BMElem *ele_next_from = (BMElem *)e;
- if (state_link_find(state, ele_next) == false) {
- if (state_orig.link_last != state->link_last) {
- state = state_dupe_add(pc, state, &state_orig);
- }
- state_link_add(pc, state, ele_next, ele_next_from);
+ if (state_link_find(state, ele_next) == false) {
+ if (state_orig.link_last != state->link_last) {
+ state = state_dupe_add(pc, state, &state_orig);
}
+ state_link_add(pc, state, ele_next, ele_next_from);
}
}
}
}
}
-
}
else {
BLI_assert(0);
@@ -562,12 +571,10 @@ void bmo_connect_vert_pair_exec(BMesh *bm, BMOperator *op)
#if 1
if (found_all) {
- /* leave 'check_degenerate' off, if a user tries to cut with 2 verts,
- * always connect even when resulting faces are degenerate [#39418] */
BMOperator op_sub;
BMO_op_initf(bm, &op_sub, 0,
- "connect_verts verts=%fv faces_exclude=%s",
- VERT_OUT, op, "faces_exclude");
+ "connect_verts verts=%fv faces_exclude=%s check_degenerate=%b",
+ VERT_OUT, op, "faces_exclude", true);
BMO_op_exec(bm, &op_sub);
BMO_slot_copy(&op_sub, slots_out, "edges.out",
op, slots_out, "edges.out");
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 20c7f4eb521..4f4a7998a87 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -877,23 +877,50 @@ static int edbm_vert_connect_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
BMOperator bmop;
- const bool is_pair = (bm->totvertsel == 2);
+ bool is_pair = (bm->totvertsel == 2);
int len;
-
+ bool check_degenerate = true;
+ const int verts_len = bm->totvertsel;
+ BMVert **verts;
+
+
+ verts = MEM_mallocN(sizeof(*verts) * verts_len, __func__);
+ {
+ BMIter iter;
+ BMVert *v;
+ int i = 0;
+
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ verts[i++] = v;
+ }
+ }
+
+ if (is_pair) {
+ if (BM_vert_pair_share_face_check_cb(
+ verts[0], verts[1],
+ BM_elem_cb_check_hflag_disabled_simple(BMFace *, BM_ELEM_HIDDEN)))
+ {
+ check_degenerate = false;
+ is_pair = false;
+ }
+ }
+ }
+
if (is_pair) {
if (!EDBM_op_init(em, &bmop, op,
- "connect_vert_pair verts=%hv verts_exclude=%hv faces_exclude=%hf",
- BM_ELEM_SELECT, BM_ELEM_HIDDEN, BM_ELEM_HIDDEN))
+ "connect_vert_pair verts=%eb verts_exclude=%hv faces_exclude=%hf",
+ verts, verts_len, BM_ELEM_HIDDEN, BM_ELEM_HIDDEN))
{
- return OPERATOR_CANCELLED;
+ goto finally;
}
}
else {
if (!EDBM_op_init(em, &bmop, op,
- "connect_verts verts=%hv faces_exclude=%hf check_degenerate=%b",
- BM_ELEM_SELECT, BM_ELEM_HIDDEN, true))
+ "connect_verts verts=%eb faces_exclude=%hf check_degenerate=%b",
+ verts, verts_len, BM_ELEM_HIDDEN, check_degenerate))
{
- return OPERATOR_CANCELLED;
+ goto finally;
}
}
@@ -908,15 +935,18 @@ static int edbm_vert_connect_exec(bContext *C, wmOperator *op)
}
if (!EDBM_op_finish(em, &bmop, op, true)) {
- return OPERATOR_CANCELLED;
+ len = 0;
}
else {
EDBM_selectmode_flush(em); /* so newly created edges get the selection state from the vertex */
EDBM_update_generic(em, true, true);
-
- return len ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
+
+
+finally:
+ MEM_freeN(verts);
+ return len ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void MESH_OT_vert_connect(wmOperatorType *ot)