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