BMesh: add BMO_ITER_INDEX macro
[blender.git] / source / blender / bmesh / intern / bmesh_operator_api.h
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Joseph Eagar.
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 #ifndef __BMESH_OPERATOR_API_H__
24 #define __BMESH_OPERATOR_API_H__
25
26 /** \file blender/bmesh/intern/bmesh_operator_api.h
27  *  \ingroup bmesh
28  */
29
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33
34 #include "BLI_ghash.h"
35
36 #include <stdarg.h>
37
38 /**
39  * operators represent logical, executable mesh modules.  all topological
40  * operations involving a bmesh has to go through them.
41  *
42  * operators are nested, as are tool flags, which are private to an operator
43  * when it's executed.  tool flags are allocated in layers, one per operator
44  * execution, and are used for all internal flagging a tool needs to do.
45  *
46  * each operator has a series of "slots" which can be of the following types:
47  * - simple numerical types
48  * - arrays of elements (e.g. arrays of faces).
49  * - hash mappings.
50  *
51  * each slot is identified by a slot code, as are each operator.
52  * operators, and their slots, are defined in bmesh_opdefines.c (with their
53  * execution functions prototyped in bmesh_operators_private.h), with all their
54  * operator code and slot codes defined in bmesh_operators.h.  see
55  * bmesh_opdefines.c and the BMOpDefine struct for how to define new operators.
56  *
57  * in general, operators are fed arrays of elements, created using either
58  * #BMO_slot_buffer_from_hflag or #BMO_slot_buffer_from_flag
59  * (or through one of the format specifiers in #BMO_op_callf or #BMO_op_initf).
60  *
61  * \note multiple element types (e.g. faces and edges)
62  * can be fed to the same slot array.  Operators act on this data,
63  * and possibly spit out data into output slots.
64  *
65  * \note operators should never read from header flags (e.g. element->head.flag).
66  * For example, if you want an operator to only operate on selected faces, you
67  * should use #BMO_slot_buffer_from_hflag to put the selected elements into a slot.
68  *
69  * \note when you read from an element slot array or mapping, you can either tool-flag
70  * all the elements in it, or read them using an iterator API (which is semantically
71  * similar to the iterator api in bmesh_iterators.h).
72  *
73  * \note only #BMLoop items can't be put into slots as with verts, edges & faces.
74  */
75
76 struct GHashIterator;
77
78 #define BMO_elem_flag_test(     bm, ele, oflag)      _bmo_elem_flag_test     (bm, (ele)->oflags, oflag)
79 #define BMO_elem_flag_test_bool(bm, ele, oflag)      _bmo_elem_flag_test_bool(bm, (ele)->oflags, oflag)
80 #define BMO_elem_flag_enable(   bm, ele, oflag)      _bmo_elem_flag_enable   (bm, (ele)->oflags, oflag)
81 #define BMO_elem_flag_disable(  bm, ele, oflag)      _bmo_elem_flag_disable  (bm, (ele)->oflags, oflag)
82 #define BMO_elem_flag_set(      bm, ele, oflag, val) _bmo_elem_flag_set      (bm, (ele)->oflags, oflag, val)
83 #define BMO_elem_flag_toggle(   bm, ele, oflag)      _bmo_elem_flag_toggle   (bm, (ele)->oflags, oflag)
84
85 BLI_INLINE short _bmo_elem_flag_test(     BMesh *bm, BMFlagLayer *oflags, const short oflag);
86 BLI_INLINE bool  _bmo_elem_flag_test_bool(BMesh *bm, BMFlagLayer *oflags, const short oflag);
87 BLI_INLINE void  _bmo_elem_flag_enable(   BMesh *bm, BMFlagLayer *oflags, const short oflag);
88 BLI_INLINE void  _bmo_elem_flag_disable(  BMesh *bm, BMFlagLayer *oflags, const short oflag);
89 BLI_INLINE void  _bmo_elem_flag_set(      BMesh *bm, BMFlagLayer *oflags, const short oflag, int val);
90 BLI_INLINE void  _bmo_elem_flag_toggle(   BMesh *bm, BMFlagLayer *oflags, const short oflag);
91
92 /* slot type arrays are terminated by the last member
93  * having a slot type of 0 */
94 typedef enum eBMOpSlotType {
95         /* BMO_OP_SLOT_SENTINEL = 0, */
96         BMO_OP_SLOT_BOOL = 1,
97         BMO_OP_SLOT_INT = 2,
98         BMO_OP_SLOT_FLT = 3,
99
100         /* normally store pointers to object, scene,
101          * _never_ store arrays corresponding to mesh elements with this */
102         BMO_OP_SLOT_PTR = 4,  /* requres subtype BMO_OP_SLOT_SUBTYPE_PTR_xxx */
103         BMO_OP_SLOT_MAT = 5,
104         BMO_OP_SLOT_VEC = 8,
105
106         /* after BMO_OP_SLOT_VEC, everything is dynamically allocated arrays.
107          * We leave a space in the identifiers for future growth.
108          *
109          * it's very important this remain a power of two */
110         BMO_OP_SLOT_ELEMENT_BUF = 9, /* list of verts/edges/faces */
111         BMO_OP_SLOT_MAPPING = 10 /* simple hash map, requres subtype BMO_OP_SLOT_SUBTYPE_MAP_xxx */
112 } eBMOpSlotType;
113 #define BMO_OP_SLOT_TOTAL_TYPES 11
114
115 /* don't overlap values to avoid confusion */
116 typedef enum eBMOpSlotSubType_Elem {
117         /* use as flags */
118         BMO_OP_SLOT_SUBTYPE_ELEM_VERT = BM_VERT,
119         BMO_OP_SLOT_SUBTYPE_ELEM_EDGE = BM_EDGE,
120         BMO_OP_SLOT_SUBTYPE_ELEM_FACE = BM_FACE,
121         BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE = (BM_FACE << 1),
122 } eBMOpSlotSubType_Elem;
123 typedef enum eBMOpSlotSubType_Map {
124         BMO_OP_SLOT_SUBTYPE_MAP_EMPTY    = 64,  /* use as a set(), unused value */
125         BMO_OP_SLOT_SUBTYPE_MAP_ELEM     = 65,
126         BMO_OP_SLOT_SUBTYPE_MAP_FLT      = 66,
127         BMO_OP_SLOT_SUBTYPE_MAP_INT      = 67,
128         BMO_OP_SLOT_SUBTYPE_MAP_BOOL     = 68,
129         BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL = 69,  /* python can't convert these */
130 } eBMOpSlotSubType_Map;
131 typedef enum eBMOpSlotSubType_Ptr {
132         BMO_OP_SLOT_SUBTYPE_PTR_BMESH  = 100,
133         BMO_OP_SLOT_SUBTYPE_PTR_SCENE  = 101,
134         BMO_OP_SLOT_SUBTYPE_PTR_OBJECT = 102,
135         BMO_OP_SLOT_SUBTYPE_PTR_MESH   = 103,
136 } eBMOpSlotSubType_Ptr;
137
138 typedef union eBMOpSlotSubType_Union {
139         eBMOpSlotSubType_Elem elem;
140         eBMOpSlotSubType_Ptr ptr;
141         eBMOpSlotSubType_Map map;
142 } eBMOpSlotSubType_Union;
143
144 /* please ignore all these structures, don't touch them in tool code, except
145  * for when your defining an operator with BMOpDefine.*/
146
147 typedef struct BMOpSlot {
148         const char *slot_name;  /* pointer to BMOpDefine.slot_args */
149         eBMOpSlotType          slot_type;
150         eBMOpSlotSubType_Union slot_subtype;
151
152         int len;
153 //      int flag;  /* UNUSED */
154 //      int index; /* index within slot array */  /* UNUSED */
155         union {
156                 int i;
157                 float f;
158                 void *p;
159                 float vec[3];
160                 void **buf;
161                 GHash *ghash;
162         } data;
163 } BMOpSlot;
164
165 /* mainly for use outside bmesh internal code */
166 #define BMO_SLOT_AS_BOOL(slot)         ((slot)->data.i)
167 #define BMO_SLOT_AS_INT(slot)          ((slot)->data.i)
168 #define BMO_SLOT_AS_FLOAT(slot)        ((slot)->data.f)
169 #define BMO_SLOT_AS_VECTOR(slot)       ((slot)->data.vec)
170 #define BMO_SLOT_AS_MATRIX(slot )      ((float (*)[4])((slot)->data.p))
171 #define BMO_SLOT_AS_BUFFER(slot )      ((slot)->data.buf)
172 #define BMO_SLOT_AS_GHASH(slot )       ((slot)->data.ghash)
173
174 #define BMO_ASSERT_SLOT_IN_OP(slot, op) \
175         BLI_assert(((slot >= (op)->slots_in)  && (slot < &(op)->slots_in[BMO_OP_MAX_SLOTS])) || \
176                    ((slot >= (op)->slots_out) && (slot < &(op)->slots_out[BMO_OP_MAX_SLOTS])))
177
178 /* way more than probably needed, compiler complains if limit hit */
179 #define BMO_OP_MAX_SLOTS 16
180
181 /* BMOpDefine->type_flag */
182 typedef enum {
183         BMO_OPTYPE_FLAG_NOP                 = 0,
184         BMO_OPTYPE_FLAG_UNTAN_MULTIRES      = (1 << 0),  /* switch from multires tangent space to absolute coordinates */
185         BMO_OPTYPE_FLAG_NORMALS_CALC        = (1 << 1),
186         BMO_OPTYPE_FLAG_SELECT_FLUSH        = (1 << 2),
187         BMO_OPTYPE_FLAG_SELECT_VALIDATE     = (1 << 3),
188 } BMOpTypeFlag;
189
190 typedef struct BMOperator {
191         struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS];
192         struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS];
193         void (*exec)(BMesh *bm, struct BMOperator *op);
194         struct MemArena *arena;
195         int type;
196         BMOpTypeFlag type_flag;
197         int flag;  /* runtime options */
198 } BMOperator;
199
200 enum {
201         BMO_FLAG_RESPECT_HIDE = 1,
202 };
203
204 #define BMO_FLAG_DEFAULTS  BMO_FLAG_RESPECT_HIDE
205
206 #define MAX_SLOTNAME    32
207
208 typedef struct BMOSlotType {
209         char name[MAX_SLOTNAME];
210         eBMOpSlotType          type;
211         eBMOpSlotSubType_Union subtype;
212 } BMOSlotType;
213
214 typedef struct BMOpDefine {
215         const char *opname;
216         BMOSlotType slot_types_in[BMO_OP_MAX_SLOTS];
217         BMOSlotType slot_types_out[BMO_OP_MAX_SLOTS];
218         void (*exec)(BMesh *bm, BMOperator *op);
219         BMOpTypeFlag type_flag;
220 } BMOpDefine;
221
222 /*------------- Operator API --------------*/
223
224 /* data types that use pointers (arrays, etc) should never
225  * have it set directly.  and never use BMO_slot_ptr_set to
226  * pass in a list of edges or any arrays, really.*/
227
228 void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname);
229
230 /* executes an operator, pushing and popping a new tool flag
231  * layer as appropriate.*/
232 void BMO_op_exec(BMesh *bm, BMOperator *op);
233
234 /* finishes an operator (though note the operator's tool flag is removed
235  * after it finishes executing in BMO_op_exec).*/
236 void BMO_op_finish(BMesh *bm, BMOperator *op);
237
238 /* count the number of elements with the specified flag enabled.
239  * type can be a bitmask of BM_FACE, BM_EDGE, or BM_FACE. */
240 int BMO_mesh_enabled_flag_count(BMesh *bm, const char htype, const short oflag);
241
242 /* count the number of elements with the specified flag disabled.
243  * type can be a bitmask of BM_FACE, BM_EDGE, or BM_FACE. */
244 int BMO_mesh_disabled_flag_count(BMesh *bm, const char htype, const short oflag);
245
246 /*---------formatted operator initialization/execution-----------*/
247 void BMO_push(BMesh *bm, BMOperator *op);
248 void BMO_pop(BMesh *bm);
249
250 /*executes an operator*/
251 bool BMO_op_callf(BMesh *bm, const int flag, const char *fmt, ...);
252
253 /* initializes, but doesn't execute an operator.  this is so you can
254  * gain access to the outputs of the operator.  note that you have
255  * to execute/finish (BMO_op_exec and BMO_op_finish) yourself. */
256 bool BMO_op_initf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, ...);
257
258 /* va_list version, used to implement the above two functions,
259  * plus EDBM_op_callf in editmesh_utils.c. */
260 bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, va_list vlist);
261
262 /* test whether a named slot exists */
263 bool BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier);
264
265 /* get a pointer to a slot.  this may be removed layer on from the public API. */
266 BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier);
267
268 /* copies the data of a slot from one operator to another.  src and dst are the
269  * source/destination slot codes, respectively. */
270 #define BMO_slot_copy(op_src, slots_src, slot_name_src,                       \
271                       op_dst, slots_dst, slot_name_dst)                       \
272         _bmo_slot_copy((op_src)->slots_src, slot_name_src,                        \
273                        (op_dst)->slots_dst, slot_name_dst,                        \
274                        (op_dst)->arena)
275
276 void _bmo_slot_copy(
277         BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
278         BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
279         struct MemArena *arena_dst);
280
281 /* del "context" slot values, used for operator too */
282 enum {
283         DEL_VERTS = 1,
284         DEL_EDGES,
285         DEL_ONLYFACES,
286         DEL_EDGESFACES,
287         DEL_FACES,
288         DEL_ONLYTAGGED
289 };
290
291 typedef enum {
292         BMO_SYMMETRIZE_NEGATIVE_X,
293         BMO_SYMMETRIZE_NEGATIVE_Y,
294         BMO_SYMMETRIZE_NEGATIVE_Z,
295
296         BMO_SYMMETRIZE_POSITIVE_X,
297         BMO_SYMMETRIZE_POSITIVE_Y,
298         BMO_SYMMETRIZE_POSITIVE_Z,
299 } BMO_SymmDirection;
300
301 typedef enum {
302         BMO_DELIM_NORMAL = 1 << 0,
303         BMO_DELIM_MATERIAL = 1 << 1,
304         BMO_DELIM_SEAM = 1 << 2,
305         BMO_DELIM_SHARP = 1 << 3,
306         BMO_DELIM_UV = 1 << 4,
307 } BMO_Delimit;
308
309 void BMO_op_flag_enable(BMesh *bm, BMOperator *op, const int op_flag);
310 void BMO_op_flag_disable(BMesh *bm, BMOperator *op, const int op_flag);
311
312 void  BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float f);
313 float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
314 void  BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i);
315 int   BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
316 void  BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const bool i);
317 bool  BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
318 void *BMO_slot_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int *len);
319
320
321 /* don't pass in arrays that are supposed to map to elements this way.
322  *
323  * so, e.g. passing in list of floats per element in another slot is bad.
324  * passing in, e.g. pointer to an editmesh for the conversion operator is fine
325  * though. */
326 void  BMO_slot_ptr_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, void *p);
327 void *BMO_slot_ptr_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
328 void  BMO_slot_vec_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float vec[3]);
329 void  BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_vec[3]);
330
331 /* only supports square mats */
332 /* size must be 3 or 4; this api is meant only for transformation matrices.
333  * note that internally the matrix is stored in 4x4 form, and it's safe to
334  * call whichever BMO_Get_MatXXX function you want. */
335 void BMO_slot_mat_set(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],  const char *slot_name, const float *mat, int size);
336 void BMO_slot_mat4_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[4][4]);
337 void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[3][3]);
338
339 void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *op, const char htype, const short oflag);
340
341 void BMO_mesh_selected_remap(
342         BMesh *bm,
343         BMOpSlot *slot_vert_map,
344         BMOpSlot *slot_edge_map,
345         BMOpSlot *slot_face_map,
346         const bool check_select);
347
348 /* copies the values from another slot to the end of the output slot */
349 #define BMO_slot_buffer_append(op_src, slots_src, slot_name_src,              \
350                                op_dst, slots_dst, slot_name_dst)              \
351         _bmo_slot_buffer_append((op_src)->slots_src, slot_name_src,               \
352                                 (op_dst)->slots_dst, slot_name_dst,               \
353                                 (op_dst)->arena)
354 void _bmo_slot_buffer_append(
355         BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
356         BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
357         struct MemArena *arena_dst);
358
359 /* puts every element of type 'type' (which is a bitmask) with tool
360  * flag 'flag', into a slot. */
361 void BMO_slot_buffer_from_enabled_flag(
362         BMesh *bm, BMOperator *op,
363         BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
364         const char htype, const short oflag);
365
366 /* puts every element of type 'type' (which is a bitmask) without tool
367  * flag 'flag', into a slot. */
368 void BMO_slot_buffer_from_disabled_flag(
369         BMesh *bm, BMOperator *op,
370         BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
371         const char htype, const short oflag);
372
373 /* tool-flags all elements inside an element slot array with flag flag. */
374 void BMO_slot_buffer_flag_enable(
375         BMesh *bm,
376         BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
377         const char htype, const short oflag);
378 /* clears tool-flag flag from all elements inside a slot array. */
379 void BMO_slot_buffer_flag_disable(
380         BMesh *bm,
381         BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
382         const char htype, const short oflag);
383
384 /* tool-flags all elements inside an element slot array with flag flag. */
385 void BMO_slot_buffer_hflag_enable(
386         BMesh *bm,
387         BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
388         const char htype, const char hflag, const bool do_flush);
389 /* clears tool-flag flag from all elements inside a slot array. */
390 void BMO_slot_buffer_hflag_disable(
391         BMesh *bm,
392         BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
393         const char htype, const char hflag, const bool do_flush);
394
395 /* puts every element of type 'type' (which is a bitmask) with header
396  * flag 'flag', into a slot.  note: ignores hidden elements
397  * (e.g. elements with header flag BM_ELEM_HIDDEN set).*/
398 void BMO_slot_buffer_from_enabled_hflag(
399         BMesh *bm, BMOperator *op,
400         BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
401         const char htype, const char hflag);
402
403 /* puts every element of type 'type' (which is a bitmask) without
404  * header flag 'flag', into a slot.  note: ignores hidden elements
405  * (e.g. elements with header flag BM_ELEM_HIDDEN set).*/
406 void BMO_slot_buffer_from_disabled_hflag(
407         BMesh *bm, BMOperator *op,
408         BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
409         const char htype, const char hflag);
410
411 void  BMO_slot_buffer_from_array(BMOperator *op, BMOpSlot *slot, BMHeader **ele_buffer, int ele_buffer_len);
412
413 void  BMO_slot_buffer_from_single(BMOperator *op, BMOpSlot *slot, BMHeader *ele);
414 void *BMO_slot_buffer_get_single(BMOpSlot *slot);
415
416
417 /* counts number of elements inside a slot array. */
418 int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
419 int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
420
421 void BMO_slot_map_insert(
422         BMOperator *op, BMOpSlot *slot,
423         const void *element, const void *data);
424
425 /* flags all elements in a mapping.  note that the mapping must only have
426  * bmesh elements in it.*/
427 void BMO_slot_map_to_flag(
428         BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
429         const char *slot_name, const char hflag, const short oflag);
430
431 void *BMO_slot_buffer_alloc(
432         BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
433         const char *slot_name, const int len);
434
435 void BMO_slot_buffer_from_all(
436         BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
437         const char *slot_name, const char htype);
438
439 /**
440  * This part of the API is used to iterate over element buffer or
441  * mapping slots.
442  *
443  * for example, iterating over the faces in a slot is:
444  *
445  * \code{.c}
446  *
447  *    BMOIter oiter;
448  *    BMFace *f;
449  *
450  *    f = BMO_iter_new(&oiter, some_operator, "slot_name", BM_FACE);
451  *    for (; f; f = BMO_iter_step(&oiter)) {
452  *        /do something with the face
453  *    }
454  *
455  * another example, iterating over a mapping:
456  *    BMOIter oiter;
457  *    void *key;
458  *    void *val;
459  *
460  *    key = BMO_iter_new(&oiter, bm, some_operator, "slot_name", 0);
461  *    for (; key; key = BMO_iter_step(&oiter)) {
462  *        val = BMO_iter_map_value(&oiter);
463  *        //do something with the key/val pair
464  *        //note that val is a pointer to the val data,
465  *        //whether it's a float, pointer, whatever.
466  *        //
467  *        // so to get a pointer, for example, use:
468  *        //  *((void **)BMO_iter_map_value(&oiter));
469  *        //or something like that.
470  *    }
471  * \endcode
472  */
473
474 /* contents of this structure are private,
475  * don't directly access. */
476 typedef struct BMOIter {
477         BMOpSlot *slot;
478         int cur; //for arrays
479         GHashIterator giter;
480         void **val;
481         char restrictmask; /* bitwise '&' with BMHeader.htype */
482 } BMOIter;
483
484 void *BMO_slot_buffer_get_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
485
486 void *BMO_iter_new(
487         BMOIter *iter,
488         BMOpSlot slot_args[BMO_OP_MAX_SLOTS],  const char *slot_name,
489         const char restrictmask);
490 void *BMO_iter_step(BMOIter *iter);
491
492 void **BMO_iter_map_value_p(BMOIter *iter);
493 void  *BMO_iter_map_value_ptr(BMOIter *iter);
494
495 float BMO_iter_map_value_float(BMOIter *iter);
496 int   BMO_iter_map_value_int(BMOIter *iter);
497 bool  BMO_iter_map_value_bool(BMOIter *iter);
498
499 #define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag)   \
500         for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_new(iter, slot_args, slot_name, restrict_flag); \
501              ele; \
502              BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_step(iter))
503
504 #define BMO_ITER_INDEX(ele, iter, slot_args, slot_name, restrict_flag, i_)   \
505         for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_new(iter, slot_args, slot_name, restrict_flag), i_ = 0; \
506              ele; \
507              BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_step(iter), i_++)
508
509 extern const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES];
510
511 int BMO_opcode_from_opname(const char *opname);
512
513 #ifdef __cplusplus
514 }
515 #endif
516
517 #endif /* __BMESH_OPERATOR_API_H__ */