/blender-2.63a/source/blender/bmesh/intern/bmesh_operators.c
C | 1588 lines | 1092 code | 290 blank | 206 comment | 231 complexity | 58180ba8edeb357d18dc81668b1bdcb3 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0, BSD-3-Clause, LGPL-3.0, BSD-2-Clause, Apache-2.0, AGPL-1.0
- /*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributor(s): Joseph Eagar, Geoffrey Bantle, Campbell Barton
- *
- * ***** END GPL LICENSE BLOCK *****
- */
- /** \file blender/bmesh/intern/bmesh_operators.c
- * \ingroup bmesh
- *
- * BMesh operator access.
- */
- #include "MEM_guardedalloc.h"
- #include "BLI_utildefines.h"
- #include "BLI_string.h"
- #include "BLI_math.h"
- #include "BLI_memarena.h"
- #include "BLI_mempool.h"
- #include "BLI_listbase.h"
- #include "BLI_array.h"
- #include "bmesh.h"
- #include "intern/bmesh_private.h"
- /* forward declarations */
- static void bmo_flag_layer_alloc(BMesh *bm);
- static void bmo_flag_layer_free(BMesh *bm);
- static void bmo_flag_layer_clear(BMesh *bm);
- static int bmo_name_to_slotcode(BMOpDefine *def, const char *name);
- static int bmo_name_to_slotcode_check(BMOpDefine *def, const char *name);
- static int bmo_opname_to_opcode(const char *opname);
- static const char *bmo_error_messages[] = {
- NULL,
- "Self intersection error",
- "Could not dissolve vert",
- "Could not connect vertices",
- "Could not traverse mesh",
- "Could not dissolve faces",
- "Could not dissolve vertices",
- "Tessellation error",
- "Can not deal with non-manifold geometry",
- "Invalid selection",
- "Internal mesh error",
- };
- /* operator slot type information - size of one element of the type given. */
- const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES] = {
- 0, /* 0: BMO_OP_SLOT_SENTINEL */
- sizeof(int), /* 1: BMO_OP_SLOT_BOOL */
- sizeof(int), /* 2: BMO_OP_SLOT_INT */
- sizeof(float), /* 3: BMO_OP_SLOT_FLT */
- sizeof(void *), /* 4: BMO_OP_SLOT_PNT */
- sizeof(void *), /* 5: BMO_OP_SLOT_PNT */
- 0, /* 6: unused */
- 0, /* 7: unused */
- sizeof(float) * 3, /* 8: BMO_OP_SLOT_VEC */
- sizeof(void *), /* 9: BMO_OP_SLOT_ELEMENT_BUF */
- sizeof(BMOElemMapping) /* 10: BMO_OP_SLOT_MAPPING */
- };
- /* Dummy slot so there is something to return when slot name lookup fails */
- static BMOpSlot BMOpEmptySlot = {0};
- void BMO_op_flag_enable(BMesh *UNUSED(bm), BMOperator *op, const int op_flag)
- {
- op->flag |= op_flag;
- }
- void BMO_op_flag_disable(BMesh *UNUSED(bm), BMOperator *op, const int op_flag)
- {
- op->flag &= ~op_flag;
- }
- /**
- * \brief BMESH OPSTACK PUSH
- *
- * Pushes the opstack down one level and allocates a new flag layer if appropriate.
- */
- void BMO_push(BMesh *bm, BMOperator *UNUSED(op))
- {
- bm->stackdepth++;
- /* add flag layer, if appropriate */
- if (bm->stackdepth > 1)
- bmo_flag_layer_alloc(bm);
- else
- bmo_flag_layer_clear(bm);
- }
- /**
- * \brief BMESH OPSTACK POP
- *
- * Pops the opstack one level and frees a flag layer if appropriate
- *
- * BMESH_TODO: investigate NOT freeing flag layers.
- */
- void BMO_pop(BMesh *bm)
- {
- if (bm->stackdepth > 1)
- bmo_flag_layer_free(bm);
- bm->stackdepth--;
- }
- /**
- * \brief BMESH OPSTACK INIT OP
- *
- * Initializes an operator structure to a certain type
- */
- void BMO_op_init(BMesh *bm, BMOperator *op, const char *opname)
- {
- int i, opcode = bmo_opname_to_opcode(opname);
- #ifdef DEBUG
- BM_ELEM_INDEX_VALIDATE(bm, "pre bmo", opname);
- #else
- (void)bm;
- #endif
- if (opcode == -1) {
- opcode = 0; /* error!, already printed, have a better way to handle this? */
- }
- memset(op, 0, sizeof(BMOperator));
- op->type = opcode;
- op->flag = opdefines[opcode]->flag;
-
- /* initialize the operator slot types */
- for (i = 0; opdefines[opcode]->slottypes[i].type; i++) {
- op->slots[i].slottype = opdefines[opcode]->slottypes[i].type;
- op->slots[i].index = i;
- }
- /* callback */
- op->exec = opdefines[opcode]->exec;
- /* memarena, used for operator's slot buffers */
- op->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
- BLI_memarena_use_calloc(op->arena);
- }
- /**
- * \brief BMESH OPSTACK EXEC OP
- *
- * Executes a passed in operator.
- *
- * This handles the allocation and freeing of temporary flag
- * layers and starting/stopping the modeling loop.
- * Can be called from other operators exec callbacks as well.
- */
- void BMO_op_exec(BMesh *bm, BMOperator *op)
- {
-
- BMO_push(bm, op);
- if (bm->stackdepth == 2)
- bmesh_edit_begin(bm, op->flag);
- op->exec(bm, op);
-
- if (bm->stackdepth == 2)
- bmesh_edit_end(bm, op->flag);
-
- BMO_pop(bm);
- }
- /**
- * \brief BMESH OPSTACK FINISH OP
- *
- * Does housekeeping chores related to finishing up an operator.
- */
- void BMO_op_finish(BMesh *bm, BMOperator *op)
- {
- BMOpSlot *slot;
- int i;
- for (i = 0; opdefines[op->type]->slottypes[i].type; i++) {
- slot = &op->slots[i];
- if (slot->slottype == BMO_OP_SLOT_MAPPING) {
- if (slot->data.ghash)
- BLI_ghash_free(slot->data.ghash, NULL, NULL);
- }
- }
- BLI_memarena_free(op->arena);
- #ifdef DEBUG
- BM_ELEM_INDEX_VALIDATE(bm, "post bmo", opdefines[op->type]->name);
- #else
- (void)bm;
- #endif
- }
- /**
- * \brief BMESH OPSTACK HAS SLOT
- *
- * \return Success if the slot if found.
- */
- int BMO_slot_exists(BMOperator *op, const char *slotname)
- {
- int slotcode = bmo_name_to_slotcode(opdefines[op->type], slotname);
- return (slotcode >= 0);
- }
- /**
- * \brief BMESH OPSTACK GET SLOT
- *
- * Returns a pointer to the slot of type 'slotcode'
- */
- BMOpSlot *BMO_slot_get(BMOperator *op, const char *slotname)
- {
- int slotcode = bmo_name_to_slotcode_check(opdefines[op->type], slotname);
- if (slotcode < 0) {
- return &BMOpEmptySlot;
- }
- return &(op->slots[slotcode]);
- }
- /**
- * \brief BMESH OPSTACK COPY SLOT
- *
- * Copies data from one slot to another.
- */
- void BMO_slot_copy(BMOperator *source_op, BMOperator *dest_op, const char *src, const char *dst)
- {
- BMOpSlot *source_slot = BMO_slot_get(source_op, src);
- BMOpSlot *dest_slot = BMO_slot_get(dest_op, dst);
- if (source_slot == dest_slot)
- return;
- if (source_slot->slottype != dest_slot->slottype) {
- /* possibly assert here? */
- return;
- }
- if (dest_slot->slottype == BMO_OP_SLOT_ELEMENT_BUF) {
- /* do buffer copy */
- dest_slot->data.buf = NULL;
- dest_slot->len = source_slot->len;
- if (dest_slot->len) {
- const int slot_alloc_size = BMO_OPSLOT_TYPEINFO[dest_slot->slottype] * dest_slot->len;
- dest_slot->data.buf = BLI_memarena_alloc(dest_op->arena, slot_alloc_size);
- memcpy(dest_slot->data.buf, source_slot->data.buf, slot_alloc_size);
- }
- }
- else if (dest_slot->slottype == BMO_OP_SLOT_MAPPING) {
- GHashIterator it;
- BMOElemMapping *srcmap, *dstmap;
- /* sanity check */
- if (!source_slot->data.ghash) {
- return;
- }
- if (!dest_slot->data.ghash) {
- dest_slot->data.ghash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh operator 2");
- }
- BLI_ghashIterator_init(&it, source_slot->data.ghash);
- for ( ; (srcmap = BLI_ghashIterator_getValue(&it));
- BLI_ghashIterator_step(&it))
- {
- dstmap = BLI_memarena_alloc(dest_op->arena, sizeof(*dstmap) + srcmap->len);
- dstmap->element = srcmap->element;
- dstmap->len = srcmap->len;
- memcpy(dstmap + 1, srcmap + 1, srcmap->len);
- BLI_ghash_insert(dest_slot->data.ghash, dstmap->element, dstmap);
- }
- }
- else {
- dest_slot->data = source_slot->data;
- }
- }
- /*
- * BMESH OPSTACK SET XXX
- *
- * Sets the value of a slot depending on it's type
- */
- void BMO_slot_float_set(BMOperator *op, const char *slotname, const float f)
- {
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- BLI_assert(slot->slottype == BMO_OP_SLOT_FLT);
- if (!(slot->slottype == BMO_OP_SLOT_FLT))
- return;
- slot->data.f = f;
- }
- void BMO_slot_int_set(BMOperator *op, const char *slotname, const int i)
- {
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- BLI_assert(slot->slottype == BMO_OP_SLOT_INT);
- if (!(slot->slottype == BMO_OP_SLOT_INT))
- return;
- slot->data.i = i;
- }
- void BMO_slot_bool_set(BMOperator *op, const char *slotname, const int i)
- {
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- BLI_assert(slot->slottype == BMO_OP_SLOT_BOOL);
- if (!(slot->slottype == BMO_OP_SLOT_BOOL))
- return;
- slot->data.i = i;
- }
- /* only supports square mats */
- void BMO_slot_mat_set(BMOperator *op, const char *slotname, const float *mat, int size)
- {
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- BLI_assert(slot->slottype == BMO_OP_SLOT_MAT);
- if (!(slot->slottype == BMO_OP_SLOT_MAT))
- return;
- slot->len = 4;
- slot->data.p = BLI_memarena_alloc(op->arena, sizeof(float) * 4 * 4);
-
- if (size == 4) {
- memcpy(slot->data.p, mat, sizeof(float) * 4 * 4);
- }
- else if (size == 3) {
- copy_m4_m3(slot->data.p, (float (*)[3])mat);
- }
- else {
- fprintf(stderr, "%s: invalid size argument %d (bmesh internal error)\n", __func__, size);
- memset(slot->data.p, 0, sizeof(float) * 4 * 4);
- }
- }
- void BMO_slot_mat4_get(BMOperator *op, const char *slotname, float r_mat[4][4])
- {
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- BLI_assert(slot->slottype == BMO_OP_SLOT_MAT);
- if (!(slot->slottype == BMO_OP_SLOT_MAT))
- return;
- copy_m4_m4(r_mat, (float (*)[4])slot->data.p);
- }
- void BMO_slot_mat3_set(BMOperator *op, const char *slotname, float r_mat[3][3])
- {
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- BLI_assert(slot->slottype == BMO_OP_SLOT_MAT);
- if (!(slot->slottype == BMO_OP_SLOT_MAT))
- return;
- copy_m3_m4(r_mat, slot->data.p);
- }
- void BMO_slot_ptr_set(BMOperator *op, const char *slotname, void *p)
- {
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- BLI_assert(slot->slottype == BMO_OP_SLOT_PNT);
- if (!(slot->slottype == BMO_OP_SLOT_PNT))
- return;
- slot->data.p = p;
- }
- void BMO_slot_vec_set(BMOperator *op, const char *slotname, const float vec[3])
- {
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- BLI_assert(slot->slottype == BMO_OP_SLOT_VEC);
- if (!(slot->slottype == BMO_OP_SLOT_VEC))
- return;
- copy_v3_v3(slot->data.vec, vec);
- }
- float BMO_slot_float_get(BMOperator *op, const char *slotname)
- {
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- BLI_assert(slot->slottype == BMO_OP_SLOT_FLT);
- if (!(slot->slottype == BMO_OP_SLOT_FLT))
- return 0.0f;
- return slot->data.f;
- }
- int BMO_slot_int_get(BMOperator *op, const char *slotname)
- {
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- BLI_assert(slot->slottype == BMO_OP_SLOT_INT);
- if (!(slot->slottype == BMO_OP_SLOT_INT))
- return 0;
- return slot->data.i;
- }
- int BMO_slot_bool_get(BMOperator *op, const char *slotname)
- {
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- BLI_assert(slot->slottype == BMO_OP_SLOT_BOOL);
- if (!(slot->slottype == BMO_OP_SLOT_BOOL))
- return 0;
- return slot->data.i;
- }
- void *BMO_slot_ptr_get(BMOperator *op, const char *slotname)
- {
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- BLI_assert(slot->slottype == BMO_OP_SLOT_PNT);
- if (!(slot->slottype == BMO_OP_SLOT_PNT))
- return NULL;
- return slot->data.p;
- }
- void BMO_slot_vec_get(BMOperator *op, const char *slotname, float r_vec[3])
- {
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- BLI_assert(slot->slottype == BMO_OP_SLOT_VEC);
- if (!(slot->slottype == BMO_OP_SLOT_VEC))
- return;
- copy_v3_v3(r_vec, slot->data.vec);
- }
- /*
- * BMO_COUNTFLAG
- *
- * Counts the number of elements of a certain type that have a
- * specific flag enabled (or disabled if test_for_enabled is false).
- *
- */
- static int bmo_mesh_flag_count(BMesh *bm, const char htype, const short oflag,
- const short test_for_enabled)
- {
- const char iter_types[3] = {BM_VERTS_OF_MESH,
- BM_EDGES_OF_MESH,
- BM_FACES_OF_MESH};
- const char flag_types[3] = {BM_VERT, BM_EDGE, BM_FACE};
- BMIter iter;
- int count = 0;
- BMElemF *ele_f;
- int i;
- BLI_assert(ELEM(TRUE, FALSE, test_for_enabled));
- for (i = 0; i < 3; i++) {
- if (htype & flag_types[i]) {
- BM_ITER_MESH (ele_f, &iter, bm, iter_types[i]) {
- if (BMO_elem_flag_test_bool(bm, ele_f, oflag) == test_for_enabled)
- count++;
- }
- }
- }
- return count;
- }
- int BMO_mesh_enabled_flag_count(BMesh *bm, const char htype, const short oflag)
- {
- return bmo_mesh_flag_count(bm, htype, oflag, TRUE);
- }
- int BMO_mesh_disabled_flag_count(BMesh *bm, const char htype, const short oflag)
- {
- return bmo_mesh_flag_count(bm, htype, oflag, FALSE);
- }
- void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char htype, const short oflag)
- {
- const char iter_types[3] = {BM_VERTS_OF_MESH,
- BM_EDGES_OF_MESH,
- BM_FACES_OF_MESH};
- const char flag_types[3] = {BM_VERT, BM_EDGE, BM_FACE};
- BMIter iter;
- BMElemF *ele;
- int i;
- for (i = 0; i < 3; i++) {
- if (htype & flag_types[i]) {
- BM_ITER_MESH (ele, &iter, bm, iter_types[i]) {
- BMO_elem_flag_disable(bm, ele, oflag);
- }
- }
- }
- }
- int BMO_slot_buffer_count(BMesh *UNUSED(bm), BMOperator *op, const char *slotname)
- {
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- BLI_assert(slot->slottype == BMO_OP_SLOT_ELEMENT_BUF);
-
- /* check if its actually a buffer */
- if (slot->slottype != BMO_OP_SLOT_ELEMENT_BUF)
- return 0;
- return slot->len;
- }
- int BMO_slot_map_count(BMesh *UNUSED(bm), BMOperator *op, const char *slotname)
- {
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- BLI_assert(slot->slottype == BMO_OP_SLOT_MAPPING);
-
- /* check if its actually a buffer */
- if (!(slot->slottype == BMO_OP_SLOT_MAPPING))
- return 0;
- return slot->data.ghash ? BLI_ghash_size(slot->data.ghash) : 0;
- }
- /* inserts a key/value mapping into a mapping slot. note that it copies the
- * value, it doesn't store a reference to it. */
- void BMO_slot_map_insert(BMesh *UNUSED(bm), BMOperator *op, const char *slotname,
- void *element, void *data, int len)
- {
- BMOElemMapping *mapping;
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- BLI_assert(slot->slottype == BMO_OP_SLOT_MAPPING);
- mapping = (BMOElemMapping *) BLI_memarena_alloc(op->arena, sizeof(*mapping) + len);
- mapping->element = (BMHeader *) element;
- mapping->len = len;
- memcpy(mapping + 1, data, len);
- if (!slot->data.ghash) {
- slot->data.ghash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh slot map hash");
- }
- BLI_ghash_insert(slot->data.ghash, element, mapping);
- }
- #if 0
- void *bmo_slot_buffer_grow(BMesh *bm, BMOperator *op, int slotcode, int totadd)
- {
- BMOpSlot *slot = &op->slots[slotcode];
- void *tmp;
- ssize_t allocsize;
-
- BLI_assert(slot->slottype == BMO_OP_SLOT_ELEMENT_BUF);
- /* check if its actually a buffer */
- if (slot->slottype != BMO_OP_SLOT_ELEMENT_BUF)
- return NULL;
- if (slot->flag & BMOS_DYNAMIC_ARRAY) {
- if (slot->len >= slot->size) {
- slot->size = (slot->size + 1 + totadd) * 2;
- allocsize = BMO_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode].type] * slot->size;
- tmp = slot->data.buf;
- slot->data.buf = MEM_callocN(allocsize, "opslot dynamic array");
- memcpy(slot->data.buf, tmp, allocsize);
- MEM_freeN(tmp);
- }
- slot->len += totadd;
- }
- else {
- slot->flag |= BMOS_DYNAMIC_ARRAY;
- slot->len += totadd;
- slot->size = slot->len + 2;
- allocsize = BMO_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode].type] * slot->len;
- tmp = slot->data.buf;
- slot->data.buf = MEM_callocN(allocsize, "opslot dynamic array");
- memcpy(slot->data.buf, tmp, allocsize);
- }
- return slot->data.buf;
- }
- #endif
- void BMO_slot_map_to_flag(BMesh *bm, BMOperator *op, const char *slotname,
- const char htype, const short oflag)
- {
- GHashIterator it;
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- BMElemF *ele_f;
- BLI_assert(slot->slottype == BMO_OP_SLOT_MAPPING);
- /* sanity check */
- if (!slot->data.ghash) return;
- BLI_ghashIterator_init(&it, slot->data.ghash);
- for ( ; (ele_f = BLI_ghashIterator_getKey(&it)); BLI_ghashIterator_step(&it)) {
- if (ele_f->head.htype & htype) {
- BMO_elem_flag_enable(bm, ele_f, oflag);
- }
- }
- }
- static void *bmo_slot_buffer_alloc(BMOperator *op, const char *slotname, int len)
- {
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- BLI_assert(slot->slottype == BMO_OP_SLOT_ELEMENT_BUF);
- /* check if its actually a buffer */
- if (slot->slottype != BMO_OP_SLOT_ELEMENT_BUF)
- return NULL;
-
- slot->len = len;
- if (len)
- slot->data.buf = BLI_memarena_alloc(op->arena, BMO_OPSLOT_TYPEINFO[slot->slottype] * len);
- return slot->data.buf;
- }
- /**
- * \brief BMO_ALL_TO_SLOT
- *
- * Copies all elements of a certain type into an operator slot.
- */
- static void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, const char *slotname, const char htype)
- {
- BMOpSlot *output = BMO_slot_get(op, slotname);
- int totelement = 0, i = 0;
-
- if (htype & BM_VERT) totelement += bm->totvert;
- if (htype & BM_EDGE) totelement += bm->totedge;
- if (htype & BM_FACE) totelement += bm->totface;
- if (totelement) {
- BMIter iter;
- BMHeader *ele;
- bmo_slot_buffer_alloc(op, slotname, totelement);
- /* TODO - collapse these loops into one */
- if (htype & BM_VERT) {
- BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
- ((BMHeader **)output->data.p)[i] = ele;
- i++;
- }
- }
- if (htype & BM_EDGE) {
- BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
- ((BMHeader **)output->data.p)[i] = ele;
- i++;
- }
- }
- if (htype & BM_FACE) {
- BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
- ((BMHeader **)output->data.p)[i] = ele;
- i++;
- }
- }
- }
- }
- /**
- * \brief BMO_HEADERFLAG_TO_SLOT
- *
- * Copies elements of a certain type, which have a certain header flag
- * enabled/disabled into a slot for an operator.
- */
- static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *slotname,
- const char htype, const char hflag,
- const short test_for_enabled)
- {
- BMOpSlot *output = BMO_slot_get(op, slotname);
- int totelement = 0, i = 0;
- BLI_assert(ELEM(TRUE, FALSE, test_for_enabled));
- if (test_for_enabled)
- totelement = BM_mesh_elem_hflag_count_enabled(bm, htype, hflag, TRUE);
- else
- totelement = BM_mesh_elem_hflag_count_disabled(bm, htype, hflag, TRUE);
- if (totelement) {
- BMIter iter;
- BMElem *ele;
- bmo_slot_buffer_alloc(op, slotname, totelement);
- /* TODO - collapse these loops into one */
- if (htype & BM_VERT) {
- BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(ele, BM_ELEM_HIDDEN) &&
- BM_elem_flag_test_bool(ele, hflag) == test_for_enabled)
- {
- ((BMElem **)output->data.p)[i] = ele;
- i++;
- }
- }
- }
- if (htype & BM_EDGE) {
- BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(ele, BM_ELEM_HIDDEN) &&
- BM_elem_flag_test_bool(ele, hflag) == test_for_enabled)
- {
- ((BMElem **)output->data.p)[i] = ele;
- i++;
- }
- }
- }
- if (htype & BM_FACE) {
- BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(ele, BM_ELEM_HIDDEN) &&
- BM_elem_flag_test_bool(ele, hflag) == test_for_enabled)
- {
- ((BMElem **)output->data.p)[i] = ele;
- i++;
- }
- }
- }
- }
- else {
- output->len = 0;
- }
- }
- void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op, const char *slotname,
- const char htype, const char hflag)
- {
- bmo_slot_buffer_from_hflag(bm, op, slotname, htype, hflag, TRUE);
- }
- void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op, const char *slotname,
- const char htype, const char hflag)
- {
- bmo_slot_buffer_from_hflag(bm, op, slotname, htype, hflag, FALSE);
- }
- /**
- * Copies the values from another slot to the end of the output slot.
- */
- void BMO_slot_buffer_append(BMOperator *output_op, const char *output_slot_name,
- BMOperator *other_op, const char *other_slot_name)
- {
- BMOpSlot *output_slot = BMO_slot_get(output_op, output_slot_name);
- BMOpSlot *other_slot = BMO_slot_get(other_op, other_slot_name);
- BLI_assert(output_slot->slottype == BMO_OP_SLOT_ELEMENT_BUF &&
- other_slot->slottype == BMO_OP_SLOT_ELEMENT_BUF);
- if (output_slot->len == 0) {
- /* output slot is empty, copy rather than append */
- BMO_slot_copy(other_op, output_op, other_slot_name, output_slot_name);
- }
- else if (other_slot->len != 0) {
- int elem_size = BMO_OPSLOT_TYPEINFO[output_slot->slottype];
- int alloc_size = elem_size * (output_slot->len + other_slot->len);
- /* allocate new buffer */
- void *buf = BLI_memarena_alloc(output_op->arena, alloc_size);
- /* copy slot data */
- memcpy(buf, output_slot->data.buf, elem_size * output_slot->len);
- memcpy(((char *)buf) + elem_size * output_slot->len, other_slot->data.buf, elem_size * other_slot->len);
- output_slot->data.buf = buf;
- output_slot->len += other_slot->len;
- }
- }
- /**
- * \brief BMO_FLAG_TO_SLOT
- *
- * Copies elements of a certain type, which have a certain flag set
- * into an output slot for an operator.
- */
- static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, const char *slotname,
- const char htype, const short oflag,
- const short test_for_enabled)
- {
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- int totelement, i = 0;
- BLI_assert(ELEM(TRUE, FALSE, test_for_enabled));
- 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->slottype == BMO_OP_SLOT_ELEMENT_BUF);
- if (totelement) {
- BMIter iter;
- BMHeader *ele;
- BMHeader **ele_array;
- bmo_slot_buffer_alloc(op, slotname, totelement);
- ele_array = (BMHeader **)slot->data.p;
- /* TODO - collapse these loops into one */
- if (htype & BM_VERT) {
- BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
- if (BMO_elem_flag_test_bool(bm, (BMElemF *)ele, oflag) == test_for_enabled) {
- ele_array[i] = ele;
- i++;
- }
- }
- }
- if (htype & BM_EDGE) {
- BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
- if (BMO_elem_flag_test_bool(bm, (BMElemF *)ele, oflag) == test_for_enabled) {
- ele_array[i] = ele;
- i++;
- }
- }
- }
- if (htype & BM_FACE) {
- BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
- if (BMO_elem_flag_test_bool(bm, (BMElemF *)ele, oflag) == test_for_enabled) {
- ele_array[i] = ele;
- i++;
- }
- }
- }
- }
- else {
- slot->len = 0;
- }
- }
- void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, const char *slotname,
- const char htype, const short oflag)
- {
- bmo_slot_buffer_from_flag(bm, op, slotname, htype, oflag, TRUE);
- }
- void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, const char *slotname,
- const char htype, const short oflag)
- {
- bmo_slot_buffer_from_flag(bm, op, slotname, htype, oflag, FALSE);
- }
- /**
- * \brief BMO_FLAG_BUFFER
- *
- * Header Flags elements in a slots buffer, automatically
- * using the selection API where appropriate.
- */
- void BMO_slot_buffer_hflag_enable(BMesh *bm, BMOperator *op, const char *slotname,
- const char htype, const char hflag, const char do_flush)
- {
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- BMElem **data = slot->data.p;
- int i;
- const char do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT));
- const char do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN));
- BLI_assert(slot->slottype == BMO_OP_SLOT_ELEMENT_BUF);
- for (i = 0; i < slot->len; i++, data++) {
- if (!(htype & (*data)->head.htype))
- continue;
- if (do_flush_select) {
- BM_elem_select_set(bm, *data, TRUE);
- }
- if (do_flush_hide) {
- BM_elem_hide_set(bm, *data, FALSE);
- }
- BM_elem_flag_enable(*data, hflag);
- }
- }
- /**
- * \brief BMO_FLAG_BUFFER
- *
- * Removes flags from elements in a slots buffer, automatically
- * using the selection API where appropriate.
- */
- void BMO_slot_buffer_hflag_disable(BMesh *bm, BMOperator *op, const char *slotname,
- const char htype, const char hflag, const char do_flush)
- {
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- BMElem **data = slot->data.p;
- int i;
- const char do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT));
- const char do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN));
- BLI_assert(slot->slottype == BMO_OP_SLOT_ELEMENT_BUF);
- for (i = 0; i < slot->len; i++, data++) {
- if (!(htype & (*data)->head.htype))
- continue;
- if (do_flush_select) {
- BM_elem_select_set(bm, *data, FALSE);
- }
- if (do_flush_hide) {
- BM_elem_hide_set(bm, *data, FALSE);
- }
- BM_elem_flag_disable(*data, hflag);
- }
- }
- int BMO_vert_edge_flags_count(BMesh *bm, BMVert *v, const short oflag)
- {
- int count = 0;
- if (v->e) {
- BMEdge *curedge;
- const int len = bmesh_disk_count(v);
- int i;
-
- for (i = 0, curedge = v->e; i < len; i++) {
- if (BMO_elem_flag_test(bm, curedge, oflag))
- count++;
- curedge = bmesh_disk_edge_next(curedge, v);
- }
- }
- return count;
- }
- /**
- * \brief BMO_FLAG_BUFFER
- *
- * Flags elements in a slots buffer
- */
- void BMO_slot_buffer_flag_enable(BMesh *bm, BMOperator *op, const char *slotname,
- const char htype, const short oflag)
- {
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- BMHeader **data = slot->data.p;
- int i;
- BLI_assert(slot->slottype == BMO_OP_SLOT_ELEMENT_BUF);
- for (i = 0; i < slot->len; i++) {
- if (!(htype & data[i]->htype))
- continue;
- BMO_elem_flag_enable(bm, (BMElemF *)data[i], oflag);
- }
- }
- /**
- * \brief BMO_FLAG_BUFFER
- *
- * Removes flags from elements in a slots buffer
- */
- void BMO_slot_buffer_flag_disable(BMesh *bm, BMOperator *op, const char *slotname,
- const char htype, const short oflag)
- {
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- BMHeader **data = slot->data.p;
- int i;
- BLI_assert(slot->slottype == BMO_OP_SLOT_ELEMENT_BUF);
- for (i = 0; i < slot->len; i++) {
- if (!(htype & data[i]->htype))
- continue;
- BMO_elem_flag_disable(bm, (BMElemF *)data[i], oflag);
- }
- }
- /**
- * \brief ALLOC/FREE FLAG LAYER
- *
- * Used by operator stack to free/allocate
- * private flag data. This is allocated
- * using a mempool so the allocation/frees
- * should be quite fast.
- *
- * BMESH_TODO:
- * Investigate not freeing flag layers until
- * all operators have been executed. This would
- * save a lot of realloc potentially.
- */
- static void bmo_flag_layer_alloc(BMesh *bm)
- {
- BMElemF *ele;
- /* set the index values since we are looping over all data anyway,
- * may save time later on */
- int i;
- BMIter iter;
- BLI_mempool *oldpool = bm->toolflagpool; /* old flag pool */
- BLI_mempool *newpool;
- void *oldflags;
- /* store memcpy size for reuse */
- const size_t old_totflags_size = (bm->totflags * sizeof(BMFlagLayer));
-
- bm->totflags++;
- /* allocate new flag poo */
- bm->toolflagpool = newpool = BLI_mempool_create(sizeof(BMFlagLayer) * bm->totflags, 512, 512, 0);
-
- /* now go through and memcpy all the flags. Loops don't get a flag layer at this time.. */
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) {
- oldflags = ele->oflags;
- ele->oflags = BLI_mempool_calloc(newpool);
- memcpy(ele->oflags, oldflags, old_totflags_size);
- BM_elem_index_set(ele, i); /* set_inline */
- }
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) {
- oldflags = ele->oflags;
- ele->oflags = BLI_mempool_calloc(newpool);
- memcpy(ele->oflags, oldflags, old_totflags_size);
- BM_elem_index_set(ele, i); /* set_inline */
- }
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) {
- oldflags = ele->oflags;
- ele->oflags = BLI_mempool_calloc(newpool);
- memcpy(ele->oflags, oldflags, old_totflags_size);
- BM_elem_index_set(ele, i); /* set_inline */
- }
- bm->elem_index_dirty &= ~(BM_VERT|BM_EDGE|BM_FACE);
- BLI_mempool_destroy(oldpool);
- }
- static void bmo_flag_layer_free(BMesh *bm)
- {
- BMElemF *ele;
- /* set the index values since we are looping over all data anyway,
- * may save time later on */
- int i;
- BMIter iter;
- BLI_mempool *oldpool = bm->toolflagpool;
- BLI_mempool *newpool;
- void *oldflags;
-
- /* store memcpy size for reuse */
- const size_t new_totflags_size = ((bm->totflags - 1) * sizeof(BMFlagLayer));
- /* de-increment the totflags first.. */
- bm->totflags--;
- /* allocate new flag poo */
- bm->toolflagpool = newpool = BLI_mempool_create(new_totflags_size, 512, 512, BLI_MEMPOOL_SYSMALLOC);
-
- /* now go through and memcpy all the flag */
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) {
- oldflags = ele->oflags;
- ele->oflags = BLI_mempool_calloc(newpool);
- memcpy(ele->oflags, oldflags, new_totflags_size);
- BM_elem_index_set(ele, i); /* set_inline */
- }
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) {
- oldflags = ele->oflags;
- ele->oflags = BLI_mempool_calloc(newpool);
- memcpy(ele->oflags, oldflags, new_totflags_size);
- BM_elem_index_set(ele, i); /* set_inline */
- }
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) {
- oldflags = ele->oflags;
- ele->oflags = BLI_mempool_calloc(newpool);
- memcpy(ele->oflags, oldflags, new_totflags_size);
- BM_elem_index_set(ele, i); /* set_inline */
- }
- bm->elem_index_dirty &= ~(BM_VERT|BM_EDGE|BM_FACE);
- BLI_mempool_destroy(oldpool);
- }
- static void bmo_flag_layer_clear(BMesh *bm)
- {
- BMElemF *ele;
- /* set the index values since we are looping over all data anyway,
- * may save time later on */
- int i;
- BMIter iter;
- const int totflags_offset = bm->totflags - 1;
- /* now go through and memcpy all the flag */
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) {
- memset(ele->oflags + totflags_offset, 0, sizeof(BMFlagLayer));
- BM_elem_index_set(ele, i); /* set_inline */
- }
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) {
- memset(ele->oflags + totflags_offset, 0, sizeof(BMFlagLayer));
- BM_elem_index_set(ele, i); /* set_inline */
- }
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) {
- memset(ele->oflags + totflags_offset, 0, sizeof(BMFlagLayer));
- BM_elem_index_set(ele, i); /* set_inline */
- }
- bm->elem_index_dirty &= ~(BM_VERT|BM_EDGE|BM_FACE);
- }
- void *BMO_slot_buffer_elem_first(BMOperator *op, const char *slotname)
- {
- BMOpSlot *slot = BMO_slot_get(op, slotname);
-
- if (slot->slottype != BMO_OP_SLOT_ELEMENT_BUF)
- return NULL;
- return slot->data.buf ? *(void **)slot->data.buf : NULL;
- }
- /**
- * \brief New Iterator
- *
- * \param restrictmask restricts the iteration to certain element types
- * (e.g. combination of BM_VERT, BM_EDGE, BM_FACE), if iterating
- * over an element buffer (not a mapping). */
- void *BMO_iter_new(BMOIter *iter, BMesh *UNUSED(bm), BMOperator *op,
- const char *slotname, const char restrictmask)
- {
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- memset(iter, 0, sizeof(BMOIter));
- iter->slot = slot;
- iter->cur = 0;
- iter->restrictmask = restrictmask;
- if (iter->slot->slottype == BMO_OP_SLOT_MAPPING) {
- if (iter->slot->data.ghash) {
- BLI_ghashIterator_init(&iter->giter, slot->data.ghash);
- }
- else {
- return NULL;
- }
- }
- return BMO_iter_step(iter);
- }
- void *BMO_iter_step(BMOIter *iter)
- {
- if (iter->slot->slottype == BMO_OP_SLOT_ELEMENT_BUF) {
- BMHeader *h;
- if (iter->cur >= iter->slot->len) {
- return NULL;
- }
- h = ((void **)iter->slot->data.buf)[iter->cur++];
- while (!(iter->restrictmask & h->htype)) {
- if (iter->cur >= iter->slot->len) {
- return NULL;
- }
- h = ((void **)iter->slot->data.buf)[iter->cur++];
- }
- return h;
- }
- else if (iter->slot->slottype == BMO_OP_SLOT_MAPPING) {
- BMOElemMapping *map;
- void *ret = BLI_ghashIterator_getKey(&iter->giter);
- map = BLI_ghashIterator_getValue(&iter->giter);
-
- iter->val = map + 1;
- BLI_ghashIterator_step(&iter->giter);
- return ret;
- }
- return NULL;
- }
- /* used for iterating over mapping */
- void *BMO_iter_map_value(BMOIter *iter)
- {
- return iter->val;
- }
- void *BMO_iter_map_value_p(BMOIter *iter)
- {
- return *((void **)iter->val);
- }
- float BMO_iter_map_value_f(BMOIter *iter)
- {
- return *((float *)iter->val);
- }
- /* error syste */
- typedef struct BMOpError {
- struct BMOpError *next, *prev;
- int errorcode;
- BMOperator *op;
- const char *msg;
- } BMOpError;
- void BMO_error_clear(BMesh *bm)
- {
- while (BMO_error_pop(bm, NULL, NULL));
- }
- void BMO_error_raise(BMesh *bm, BMOperator *owner, int errcode, const char *msg)
- {
- BMOpError *err = MEM_callocN(sizeof(BMOpError), "bmop_error");
-
- err->errorcode = errcode;
- if (!msg) msg = bmo_error_messages[errcode];
- err->msg = msg;
- err->op = owner;
-
- BLI_addhead(&bm->errorstack, err);
- }
- int BMO_error_occurred(BMesh *bm)
- {
- return bm->errorstack.first != NULL;
- }
- /* returns error code or 0 if no erro */
- int BMO_error_get(BMesh *bm, const char **msg, BMOperator **op)
- {
- BMOpError *err = bm->errorstack.first;
- if (!err) {
- return 0;
- }
- if (msg) *msg = err->msg;
- if (op) *op = err->op;
-
- return err->errorcode;
- }
- int BMO_error_pop(BMesh *bm, const char **msg, BMOperator **op)
- {
- int errorcode = BMO_error_get(bm, msg, op);
-
- if (errorcode) {
- BMOpError *err = bm->errorstack.first;
-
- BLI_remlink(&bm->errorstack, bm->errorstack.first);
- MEM_freeN(err);
- }
- return errorcode;
- }
- #define NEXT_CHAR(fmt) ((fmt)[0] != 0 ? (fmt)[1] : 0)
- static int bmo_name_to_slotcode(BMOpDefine *def, const char *name)
- {
- int i;
- for (i = 0; def->slottypes[i].type; i++) {
- if (!strncmp(name, def->slottypes[i].name, MAX_SLOTNAME)) {
- return i;
- }
- }
- return -1;
- }
- static int bmo_name_to_slotcode_check(BMOpDefine *def, const char *name)
- {
- int i = bmo_name_to_slotcode(def, name);
- if (i < 0) {
- fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, name);
- }
- return i;
- }
- static int bmo_opname_to_opcode(const char *opname)
- {
- int i;
- for (i = 0; i < bmesh_total_ops; i++) {
- if (!strcmp(opname, opdefines[i]->name)) {
- return i;
- }
- }
- fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, opname);
- return -1;
- }
- /* Example:
- * BMO_op_callf(bm, "del %i %hv", DEL_ONLYFACES, BM_ELEM_SELECT);
- *
- * i - int
- * b - boolean (same as int but 1/0 only)
- * f - float
- * hv - header flagged verts (hflag)
- * he - header flagged edges (hflag)
- * hf - header flagged faces (hflag)
- * fv - flagged verts (oflag)
- * fe - flagged edges (oflag)
- * ff - flagged faces (oflag)
- */
- int BMO_op_vinitf(BMesh *bm, BMOperator *op, const char *_fmt, va_list vlist)
- {
- BMOpDefine *def;
- char *opname, *ofmt, *fmt;
- char slotname[64] = {0};
- int i /*, n = strlen(fmt) */, stop /*, slotcode = -1 */, type, state;
- char htype;
- int noslot = 0;
- /* basic useful info to help find where bmop formatting strings fail */
- const char *err_reason = "Unknown";
- int lineno = -1;
- #define GOTO_ERROR(reason) \
- { \
- err_reason = reason; \
- lineno = __LINE__; \
- goto error; \
- } (void)0
- /* we muck around in here, so dup i */
- fmt = ofmt = BLI_strdup(_fmt);
-
- /* find operator name */
- i = strcspn(fmt, " ");
- opname = fmt;
- if (!opname[i]) noslot = 1;
- opname[i] = '\0';
- fmt += i + (noslot ? 0 : 1);
-
- i = bmo_opname_to_opcode(opname);
- if (i == -1) {
- MEM_freeN(ofmt);
- return FALSE;
- }
- BMO_op_init(bm, op, opname);
- def = opdefines[i];
-
- i = 0;
- state = 1; /* 0: not inside slotcode name, 1: inside slotcode name */
- while (*fmt) {
- if (state) {
- /* jump past leading whitespac */
- i = strspn(fmt, " ");
- fmt += i;
-
- /* ignore trailing whitespac */
- if (!fmt[i])
- break;
- /* find end of slot name, only "slot=%f", can be used */
- i = strcspn(fmt, "=");
- if (!fmt[i]) {
- GOTO_ERROR("could not match end of slot name");
- }
- fmt[i] = 0;
- if (bmo_name_to_slotcode_check(def, fmt) < 0) {
- GOTO_ERROR("name to slot code check failed");
- }
-
- BLI_strncpy(slotname, fmt, sizeof(slotname));
-
- state = 0;
- fmt += i;
- }
- else {
- switch (*fmt) {
- case ' ':
- case '=':
- case '%':
- break;
- case 'm': {
- int size, c;
- c = NEXT_CHAR(fmt);
- fmt++;
- if (c == '3') size = 3;
- else if (c == '4') size = 4;
- else GOTO_ERROR("matrix size was not 3 or 4");
- BMO_slot_mat_set(op, slotname, va_arg(vlist, void *), size);
- state = 1;
- break;
- }
- case 'v': {
- BMO_slot_vec_set(op, slotname, va_arg(vlist, float *));
- state = 1;
- break;
- }
- case 'e': {
- BMHeader *ele = va_arg(vlist, void *);
- BMOpSlot *slot = BMO_slot_get(op, slotname);
- slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(void *) * 4);
- slot->len = 1;
- *((void **)slot->data.buf) = ele;
- state = 1;
- break;
- }
- case 's': {
- BMOperator *op2 = va_arg(vlist, void *);
- const char *slotname2 = va_arg(vlist, char *);
- BMO_slot_copy(op2, op, slotname2, slotname);
- state = 1;
- break;
- }
- case 'i':
- BMO_slot_int_set(op, slotname, va_arg(vlist, int));
- state = 1;
- break;
- case 'b':
- BMO_slot_bool_set(op, slotname, va_arg(vlist, int));
- state = 1;
- break;
- case 'p':
- BMO_slot_ptr_set(op, slotname, va_arg(vlist, void *));
- state = 1;
- break;
- case 'f':
- case 'F':
- case 'h':
- case 'H':
- case 'a':
- type = *fmt;
- if (NEXT_CHAR(fmt) == ' ' || NEXT_CHAR(fmt) == '\0') {
- BMO_slot_float_set(op, slotname, va_arg(vlist, double));
- }
- else {
- htype = 0;
- stop = 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 = 1;
- break;
- }
- if (stop) {
- break;
- }
- fmt++;
- }
- if (type == 'h') {
- BMO_slot_buffer_from_enabled_hflag(bm, op, slotname, htype, va_arg(vlist, int));
- }
- else if (type == 'H') {
- BMO_slot_buffer_from_disabled_hflag(bm, op, slotname, htype, va_arg(vlist, int));
- }
- else if (type == 'a') {
- BMO_slot_buffer_from_all(bm, op, slotname, htype);
- }
- else if (type == 'f') {
- BMO_slot_buffer_from_enabled_flag(bm, op, slotname, htype, va_arg(vlist, int));
- }
- else if (type == 'F') {
- BMO_slot_buffer_from_disabled_flag(bm, op, slotname, htype, va_arg(vlist, int));
- }
- }
- state = 1;
- break;
- default:
- fprintf(stderr,
- "%s: unrecognized bmop format char: %c, %d in '%s'\n",
- __func__, *fmt, (int)(fmt - ofmt), ofmt);
- break;
- }
- }
- fmt++;
- }
- MEM_freeN(ofmt);
- return TRUE;
- error:
- /* non urgent todo - explain exactly what is failing */
- fprintf(stderr, "%s: error parsing formatting string\n", __func__);
- fprintf(stderr, "string: '%s', position %d\n", _fmt, (int)(fmt - ofmt));
- fprintf(stderr, " ");
- {
- int pos = (int)(fmt - ofmt);
- int i;
- for (i = 0; i < pos; i++) {
- fprintf(stderr, " ");
- }
- fprintf(stderr, "^\n");
- }
- fprintf(stderr, "source code: %s:%d\n", __FILE__, lineno);
- fprintf(stderr, "reason: %s\n", err_reason);
- MEM_freeN(ofmt);
- BMO_op_finish(bm, op);
- return FALSE;
- #undef GOTO_ERROR
- }
- int BMO_op_initf(BMesh *bm, BMOperator *op, const char *fmt, ...)
- {
- va_list list;
- va_start(list, fmt);
- if (!BMO_op_vinitf(bm, op, fmt, list)) {
- printf("%s: failed\n", __func__);
- va_end(list);
- return FALSE;
- }
- va_end(list);
- return TRUE;
- }
- int BMO_op_callf(BMesh *bm, const char *fmt, ...)
- {
- va_list list;
- BMOperator op;
- va_start(list, fmt);
- if (!BMO_op_vinitf(bm, &op, fmt, list)) {
- printf("%s: failed, format is:\n \"%s\"\n", __func__, fmt);
- va_end(list);
- return FALSE;
- }
- BMO_op_exec(bm, &op);
- BMO_op_finish(bm, &op);
- va_end(list);
- return TRUE;
- }