/* * ***** 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. * * ***** END GPL LICENSE BLOCK ***** */ #ifndef __BMESH_OPERATOR_API_H__ #define __BMESH_OPERATOR_API_H__ /** \file blender/bmesh/bmesh_operator_api.h * \ingroup bmesh */ #ifdef __cplusplus extern "C" { #endif #include "BLI_ghash.h" #include /** * operators represent logical, executable mesh modules. all topological * operations involving a bmesh has to go through them. * * operators are nested, as are tool flags, which are private to an operator * when it's executed. tool flags are allocated in layers, one per operator * execution, and are used for all internal flagging a tool needs to do. * * each operator has a series of "slots" which can be of the following types: * - simple numerical types * - arrays of elements (e.g. arrays of faces). * - hash mappings. * * each slot is identified by a slot code, as are each operator. * operators, and their slots, are defined in bmesh_opdefines.c (with their * execution functions prototyped in bmesh_operators_private.h), with all their * operator code and slot codes defined in bmesh_operators.h. see * bmesh_opdefines.c and the BMOpDefine struct for how to define new operators. * * in general, operators are fed arrays of elements, created using either * #BMO_slot_buffer_from_hflag or #BMO_slot_buffer_from_flag * (or through one of the format specifiers in #BMO_op_callf or #BMO_op_initf). * * \note multiple element types (e.g. faces and edges) * can be fed to the same slot array. Operators act on this data, * and possibly spit out data into output slots. * * \note operators should never read from header flags (e.g. element->head.flag). * For example, if you want an operator to only operate on selected faces, you * should use #BMO_slot_buffer_from_hflag to put the selected elements into a slot. * * \note when you read from an element slot array or mapping, you can either tool-flag * all the elements in it, or read them using an iterator API (which is semantically * similar to the iterator api in bmesh_iterators.h). * * \note only #BMLoop items can't be put into slots as with verts, edges & faces. */ struct GHashIterator; #define BMO_elem_flag_test( bm, ele, oflag) _bmo_elem_flag_test (bm, (ele)->oflags, oflag) #define BMO_elem_flag_test_bool(bm, ele, oflag) _bmo_elem_flag_test_bool(bm, (ele)->oflags, oflag) #define BMO_elem_flag_enable( bm, ele, oflag) _bmo_elem_flag_enable (bm, (ele)->oflags, oflag) #define BMO_elem_flag_disable( bm, ele, oflag) _bmo_elem_flag_disable (bm, (ele)->oflags, oflag) #define BMO_elem_flag_set( bm, ele, oflag, val) _bmo_elem_flag_set (bm, (ele)->oflags, oflag, val) #define BMO_elem_flag_toggle( bm, ele, oflag) _bmo_elem_flag_toggle (bm, (ele)->oflags, oflag) BLI_INLINE short _bmo_elem_flag_test( BMesh *bm, BMFlagLayer *oflags, const short oflag); BLI_INLINE short _bmo_elem_flag_test_bool(BMesh *bm, BMFlagLayer *oflags, const short oflag); BLI_INLINE void _bmo_elem_flag_enable( BMesh *bm, BMFlagLayer *oflags, const short oflag); BLI_INLINE void _bmo_elem_flag_disable( BMesh *bm, BMFlagLayer *oflags, const short oflag); BLI_INLINE void _bmo_elem_flag_set( BMesh *bm, BMFlagLayer *oflags, const short oflag, int val); BLI_INLINE void _bmo_elem_flag_toggle( BMesh *bm, BMFlagLayer *oflags, const short oflag); /* slot type arrays are terminated by the last member * having a slot type of 0 */ enum { BMO_OP_SLOT_SENTINEL = 0, BMO_OP_SLOT_BOOL = 1, BMO_OP_SLOT_INT = 2, BMO_OP_SLOT_FLT = 3, /* normally store pointers to object, scene, * _never_ store arrays corresponding to mesh elements with this */ BMO_OP_SLOT_PTR = 4, BMO_OP_SLOT_MAT = 5, BMO_OP_SLOT_VEC = 8, /* after BMO_OP_SLOT_VEC, everything is dynamically allocated arrays. * We leave a space in the identifiers for future growth. * * it's very important this remain a power of two */ BMO_OP_SLOT_ELEMENT_BUF = 9, /* list of verts/edges/faces */ BMO_OP_SLOT_MAPPING = 10 /* simple hash map */ }; #define BMO_OP_SLOT_TOTAL_TYPES 11 /* please ignore all these structures, don't touch them in tool code, except * for when your defining an operator with BMOpDefine.*/ typedef struct BMOpSlot { int slot_type; int len; int flag; int index; /* index within slot array */ union { int i; float f; void *p; float vec[3]; void *buf; GHash *ghash; } data; } BMOpSlot; #define BMO_OP_MAX_SLOTS 16 /* way more than probably needed */ typedef struct BMOperator { int type; int slot_type; int type_flag; int flag; /* runtime options */ struct BMOpSlot slot_args[BMO_OP_MAX_SLOTS]; void (*exec)(BMesh *bm, struct BMOperator *op); struct MemArena *arena; } BMOperator; enum { BMO_FLAG_RESPECT_HIDE = 1, }; #define BMO_FLAG_DEFAULTS BMO_FLAG_RESPECT_HIDE #define MAX_SLOTNAME 32 typedef struct BMOSlotType { int type; char name[MAX_SLOTNAME]; } BMOSlotType; typedef struct BMOpDefine { const char *name; BMOSlotType slot_types[BMO_OP_MAX_SLOTS]; void (*exec)(BMesh *bm, BMOperator *op); int type_flag; } BMOpDefine; /* BMOpDefine->type_flag */ enum { BMO_OP_FLAG_UNTAN_MULTIRES = 1 /*switch from multires tangent space to absolute coordinates*/ }; /*------------- Operator API --------------*/ /* data types that use pointers (arrays, etc) should never * have it set directly. and never use BMO_slot_ptr_set to * pass in a list of edges or any arrays, really.*/ void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname); /* executes an operator, pushing and popping a new tool flag * layer as appropriate.*/ void BMO_op_exec(BMesh *bm, BMOperator *op); /* finishes an operator (though note the operator's tool flag is removed * after it finishes executing in BMO_op_exec).*/ void BMO_op_finish(BMesh *bm, BMOperator *op); /* count the number of elements with the specified flag enabled. * type can be a bitmask of BM_FACE, BM_EDGE, or BM_FACE. */ int BMO_mesh_enabled_flag_count(BMesh *bm, const char htype, const short oflag); /* count the number of elements with the specified flag disabled. * type can be a bitmask of BM_FACE, BM_EDGE, or BM_FACE. */ int BMO_mesh_disabled_flag_count(BMesh *bm, const char htype, const short oflag); /*---------formatted operator initialization/execution-----------*/ /* * this system is used to execute or initialize an operator, * using a formatted-string system. * * for example, BMO_op_callf(bm, BMO_FLAG_DEFAULTS, "delete geom=%hf context=%i", BM_ELEM_SELECT, DEL_FACES); * . . .will execute the delete operator, feeding in selected faces, deleting them. * * the basic format for the format string is: * [operatorname] [slot_name]=%[code] [slot_name]=%[code] * * as in printf, you pass in one additional argument to the function * for every code. * * the formatting codes are: * %d - put int in slot * %f - put float in slot * %p - put pointer in slot * %h[f/e/v] - put elements with a header flag in slot. * the letters after %h define which element types to use, * so e.g. %hf will do faces, %hfe will do faces and edges, * %hv will do verts, etc. must pass in at least one * element type letter. * %H[f/e/v] - same as %h, but tests if the flag is disabled * %f[f/e/v] - same as %h, except it deals with tool flags instead of * header flags. * %F[f/e/v] - same as %f, but tests if the flag is disabled * %a[f/e/v] - pass all elements (of types specified by f/e/v) to the * slot. * %e - pass in a single element. * %v - pointer to a float vector of length 3. * %m[3/4] - matrix, 3/4 refers to the matrix size, 3 or 4. the * corresponding argument must be a pointer to * a float matrix. * %s - copy a slot from another op, instead of mapping to one * argument, it maps to two, a pointer to an operator and * a slot name. */ void BMO_push(BMesh *bm, BMOperator *op); void BMO_pop(BMesh *bm); /*executes an operator*/ int BMO_op_callf(BMesh *bm, const int flag, const char *fmt, ...); /* initializes, but doesn't execute an operator. this is so you can * gain access to the outputs of the operator. note that you have * to execute/finish (BMO_op_exec and BMO_op_finish) yourself. */ int BMO_op_initf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, ...); /* va_list version, used to implement the above two functions, * plus EDBM_op_callf in editmesh_utils.c. */ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, va_list vlist); /* test whether a named slot exists */ int BMO_slot_exists(BMOperator *op, const char *slot_name); /* get a pointer to a slot. this may be removed layer on from the public API. */ BMOpSlot *BMO_slot_get(BMOperator *op, const char *slot_name); /* copies the data of a slot from one operator to another. src and dst are the * source/destination slot codes, respectively. */ void BMO_slot_copy(BMOperator *source_op, BMOperator *dest_op, const char *src, const char *dst); /* del "context" slot values, used for operator too */ enum { DEL_VERTS = 1, DEL_EDGES, DEL_ONLYFACES, DEL_EDGESFACES, DEL_FACES, DEL_ALL, DEL_ONLYTAGGED }; void BMO_op_flag_enable(BMesh *bm, BMOperator *op, const int op_flag); void BMO_op_flag_disable(BMesh *bm, BMOperator *op, const int op_flag); void BMO_slot_float_set(BMOperator *op, const char *slot_name, const float f); float BMO_slot_float_get(BMOperator *op, const char *slot_name); void BMO_slot_int_set(BMOperator *op, const char *slot_name, const int i); int BMO_slot_int_get(BMOperator *op, const char *slot_name); void BMO_slot_bool_set(BMOperator *op, const char *slot_name, const int i); int BMO_slot_bool_get(BMOperator *op, const char *slot_name); /* don't pass in arrays that are supposed to map to elements this way. * * so, e.g. passing in list of floats per element in another slot is bad. * passing in, e.g. pointer to an editmesh for the conversion operator is fine * though. */ void BMO_slot_ptr_set(BMOperator *op, const char *slot_name, void *p); void *BMO_slot_ptr_get(BMOperator *op, const char *slot_name); void BMO_slot_vec_set(BMOperator *op, const char *slot_name, const float vec[3]); void BMO_slot_vec_get(BMOperator *op, const char *slot_name, float r_vec[3]); /* only supports square mats */ /* size must be 3 or 4; this api is meant only for transformation matrices. * note that internally the matrix is stored in 4x4 form, and it's safe to * call whichever BMO_Get_Mat* function you want. */ void BMO_slot_mat_set(BMOperator *op, const char *slot_name, const float *mat, int size); void BMO_slot_mat4_get(BMOperator *op, const char *slot_name, float r_mat[4][4]); void BMO_slot_mat3_set(BMOperator *op, const char *slot_name, float r_mat[3][3]); void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *op, const char htype, const short oflag); /* copies the values from another slot to the end of the output slot */ void BMO_slot_buffer_append(BMOperator *output_op, const char *output_op_slot, BMOperator *other_op, const char *other_op_slot); /* puts every element of type 'type' (which is a bitmask) with tool * flag 'flag', into a slot. */ void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, const char *slot_name, const char htype, const short oflag); /* puts every element of type 'type' (which is a bitmask) without tool * flag 'flag', into a slot. */ void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, const char *slot_name, const char htype, const short oflag); /* tool-flags all elements inside an element slot array with flag flag. */ void BMO_slot_buffer_flag_enable(BMesh *bm, BMOperator *op, const char *slot_name, const char htype, const short oflag); /* clears tool-flag flag from all elements inside a slot array. */ void BMO_slot_buffer_flag_disable(BMesh *bm, BMOperator *op, const char *slot_name, const char htype, const short oflag); /* tool-flags all elements inside an element slot array with flag flag. */ void BMO_slot_buffer_hflag_enable(BMesh *bm, BMOperator *op, const char *slot_name, const char htype, const char hflag, const char do_flush); /* clears tool-flag flag from all elements inside a slot array. */ void BMO_slot_buffer_hflag_disable(BMesh *bm, BMOperator *op, const char *slot_name, const char htype, const char hflag, const char do_flush); /* puts every element of type 'type' (which is a bitmask) with header * flag 'flag', into a slot. note: ignores hidden elements * (e.g. elements with header flag BM_ELEM_HIDDEN set).*/ void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op, const char *slot_name, const char htype, const char hflag); /* puts every element of type 'type' (which is a bitmask) without * header flag 'flag', into a slot. note: ignores hidden elements * (e.g. elements with header flag BM_ELEM_HIDDEN set).*/ void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op, const char *slot_name, const char htype, const char hflag); /* counts number of elements inside a slot array. */ int BMO_slot_buffer_count(BMesh *bm, BMOperator *op, const char *slot_name); int BMO_slot_map_count(BMesh *bm, BMOperator *op, const char *slot_name); void BMO_slot_map_insert(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name, void *element, void *data, int len); /* Counts the number of edges with tool flag toolflag around */ int BMO_vert_edge_flags_count(BMesh *bm, BMVert *v, const short oflag); /* flags all elements in a mapping. note that the mapping must only have * bmesh elements in it.*/ void BMO_slot_map_to_flag(BMesh *bm, BMOperator *op, const char *slot_name, const char hflag, const short oflag); void *BMO_slot_buffer_alloc(BMOperator *op, const char *slot_name, const int len); void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, const char *slot_name, const char htype); /* this part of the API is used to iterate over element buffer or * mapping slots. * * for example, iterating over the faces in a slot is: * * BMOIter oiter; * BMFace *f; * * f = BMO_iter_new(&oiter, bm, some_operator, "slot_name", BM_FACE); * for (; f; f = BMO_iter_step(&oiter)) { * /do something with the face * } * * another example, iterating over a mapping: * BMOIter oiter; * void *key; * void *val; * * key = BMO_iter_new(&oiter, bm, some_operator, "slot_name", 0); * for (; key; key = BMO_iter_step(&oiter)) { * val = BMO_iter_map_value(&oiter); * //do something with the key/val pair * //note that val is a pointer to the val data, * //whether it's a float, pointer, whatever. * // * // so to get a pointer, for example, use: * // *((void**)BMO_iter_map_value(&oiter)); * //or something like that. * } */ /* contents of this structure are private, * don't directly access. */ typedef struct BMOIter { BMOpSlot *slot; int cur; //for arrays GHashIterator giter; void *val; char restrictmask; /* bitwise '&' with BMHeader.htype */ } BMOIter; void *BMO_slot_buffer_elem_first(BMOperator *op, const char *slot_name); void *BMO_iter_new(BMOIter *iter, BMesh *bm, BMOperator *op, const char *slot_name, const char restrictmask); void *BMO_iter_step(BMOIter *iter); /* returns a pointer to the key value when iterating over mappings. * remember for pointer maps this will be a pointer to a pointer.*/ void *BMO_iter_map_value(BMOIter *iter); /* use this for pointer mappings */ void *BMO_iter_map_value_p(BMOIter *iter); /* use this for float mappings */ float BMO_iter_map_value_f(BMOIter *iter); #define BMO_ITER(ele, iter, bm, op, slot_name, restrict) \ for (ele = BMO_iter_new(iter, bm, op, slot_name, restrict); ele; ele = BMO_iter_step(iter)) /******************* Inlined Functions********************/ typedef void (*opexec)(BMesh *bm, BMOperator *op); /* mappings map elements to data, which * follows the mapping struct in memory. */ typedef struct BMOElemMapping { BMHeader *element; int len; } BMOElemMapping; extern const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES]; #ifdef __cplusplus } #endif #endif /* __BMESH_OPERATOR_API_H__ */