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