1 #ifndef _BMESH_OPERATOR_API_H
2 #define _BMESH_OPERATOR_API_H
8 #include "BLI_memarena.h"
11 #include "BKE_utildefines.h"
16 operators represent logical, executable mesh modules. all topological
17 operations involving a bmesh has to go through them.
19 operators are nested, as are tool flags, which are private to an operator
20 when it's executed. tool flags are allocated in layers, one per operator
21 execution, and are used for all internal flagging a tool needs to do.
23 each operator has a series of "slots," which can be of the following types:
24 * simple numerical types
25 * arrays of elements (e.g. arrays of faces).
28 each slot is identified by a slot code, as are each operator.
29 operators, and their slots, are defined in bmesh_opdefines.c (with their
30 execution functions prototyped in bmesh_operators_private.h), with all their
31 operator code and slot codes defined in bmesh_operators.h. see
32 bmesh_opdefines.c and the BMOpDefine struct for how to define new operators.
34 in general, operators are fed arrays of elements, created using either
35 BM_HeaderFlag_To_Slot or BM_Flag_To_Slot (or through one of the format
36 specifyers in BMO_CallOpf or BMO_InitOpf). Note that multiple element
37 types (e.g. faces and edges) can be fed to the same slot array. Operators
38 act on this data, and possibly spit out data into output slots.
41 * operators should never read from header flags (e.g. element->head.flag). for
42 example, if you want an operator to only operate on selected faces, you
43 should use BM_HeaderFlag_To_Slot to put the selected elements into a slot.
44 * when you read from an element slot array or mapping, you can either tool-flag
45 all the elements in it, or read them using an iterator APi (which is
46 semantically similar to the iterator api in bmesh_iterators.h).
51 /*slot type arrays are terminated by the last member
52 having a slot type of 0.*/
53 #define BMOP_OPSLOT_SENTINEL 0
54 #define BMOP_OPSLOT_INT 1
55 #define BMOP_OPSLOT_FLT 2
56 #define BMOP_OPSLOT_PNT 3
57 #define BMOP_OPSLOT_MAT 4
58 #define BMOP_OPSLOT_VEC 7
60 /*after BMOP_OPSLOT_VEC, everything is
62 dynamically allocated arrays. we
63 leave a space in the identifiers
67 //it's very important this remain a power of two
68 #define BMOP_OPSLOT_ELEMENT_BUF 8
69 #define BMOP_OPSLOT_MAPPING 9
70 #define BMOP_OPSLOT_TYPES 10
72 /*please ignore all these structures, don't touch them in tool code, except
73 for when your defining an operator with BMOpDefine.*/
75 typedef struct BMOpSlot{
79 int index; /*index within slot array*/
90 #define BMOP_MAX_SLOTS 16 /*way more than probably needed*/
96 typedef struct BMOperator {
101 struct BMOpSlot slots[BMOP_MAX_SLOTS];
102 void (*exec)(struct BMesh *bm, struct BMOperator *op);
106 #define MAX_SLOTNAME 32
108 typedef struct slottype {
110 char name[MAX_SLOTNAME];
113 typedef struct BMOpDefine {
115 slottype slottypes[BMOP_MAX_SLOTS];
116 void (*exec)(BMesh *bm, BMOperator *op);
121 #define BMOP_UNTAN_MULTIRES 1 /*switch from multires tangent space to absolute coordinates*/
124 /*ensures consistent normals before operator execution,
125 restoring the original ones windings/normals afterwards.
126 keep in mind, this won't work if the input mesh isn't
128 #define BMOP_RATIONALIZE_NORMALS 2
130 /*------------- Operator API --------------*/
132 /*data types that use pointers (arrays, etc) should never
133 have it set directly. and never use BMO_Set_Pnt to
134 pass in a list of edges or any arrays, really.*/
136 void BMO_Init_Op(struct BMOperator *op, const char *opname);
138 /*executes an operator, pushing and popping a new tool flag
139 layer as appropriate.*/
140 void BMO_Exec_Op(struct BMesh *bm, struct BMOperator *op);
142 /*finishes an operator (though note the operator's tool flag is removed
143 after it finishes executing in BMO_Exec_Op).*/
144 void BMO_Finish_Op(struct BMesh *bm, struct BMOperator *op);
147 /*tool flag API. never, ever ever should tool code put junk in
148 header flags (element->head.flag), nor should they use
149 element->head.eflag1/eflag2. instead, use this api to set
152 if you need to store a value per element, use a
153 ghash or a mapping slot to do it.*/
154 /*flags 15 and 16 (1<<14 and 1<<15) are reserved for bmesh api use*/
155 #define BMO_TestFlag(bm, element, flag) (((BMHeader*)(element))->flags[bm->stackdepth-1].f & (flag))
156 #define BMO_SetFlag(bm, element, flag) (((BMHeader*)(element))->flags[bm->stackdepth-1].f |= (flag))
157 #define BMO_ClearFlag(bm, element, flag) (((BMHeader*)(element))->flags[bm->stackdepth-1].f &= ~(flag))
158 #define BMO_ToggleFlag(bm, element, flag) (((BMHeader*)(element))->flags[bm->stackdepth-1].f ^= (flag))
160 /*profiling showed a significant amount of time spent in BMO_TestFlag
161 void BMO_SetFlag(struct BMesh *bm, void *element, int flag);
162 void BMO_ClearFlag(struct BMesh *bm, void *element, int flag);
163 int BMO_TestFlag(struct BMesh *bm, void *element, int flag);*/
165 /*count the number of elements with a specific flag. type
166 can be a bitmask of BM_FACE, BM_EDGE, or BM_FACE.*/
167 int BMO_CountFlag(struct BMesh *bm, int flag, int type);
169 /*---------formatted operator initialization/execution-----------*/
171 this system is used to execute or initialize an operator,
172 using a formatted-string system.
174 for example, BMO_CallOpf(bm, "del geom=%hf context=%d", BM_SELECT, DEL_FACES);
175 . . .will execute the delete operator, feeding in selected faces, deleting them.
177 the basic format for the format string is:
178 [operatorname] [slotname]=%[code] [slotname]=%[code]
180 as in printf, you pass in one additional argument to the function
183 the formatting codes are:
185 %f - put float in slot
186 %p - put pointer in slot
187 %h[f/e/v] - put elements with a header flag in slot.
188 the letters after %h define which element types to use,
189 so e.g. %hf will do faces, %hfe will do faces and edges,
190 %hv will do verts, etc. must pass in at least one
192 %f[f/e/v] - same as %h, except it deals with tool flags instead of
194 %a[f/e/v] - pass all elements (of types specified by f/e/v) to the
196 %e - pass in a single element.
197 %v - pointer to a float vector of length 3.
198 %m[3/4] - matrix, 3/4 refers to the matrix size, 3 or 4. the
199 corrusponding argument must be a pointer to
201 %s - copy a slot from another op, instead of mapping to one
202 argument, it maps to two, a pointer to an operator and
205 void BMO_push(BMesh *bm, BMOperator *op);
206 void BMO_pop(BMesh *bm);
208 /*executes an operator*/
209 int BMO_CallOpf(BMesh *bm, const char *fmt, ...);
211 /*initializes, but doesn't execute an operator. this is so you can
212 gain access to the outputs of the operator. note that you have
213 to execute/finitsh (BMO_Exec_Op and BMO_Finish_Op) yourself.*/
214 int BMO_InitOpf(BMesh *bm, BMOperator *op, const char *fmt, ...);
216 /*va_list version, used to implement the above two functions,
217 plus EDBM_CallOpf in bmeshutils.c.*/
218 int BMO_VInitOpf(BMesh *bm, BMOperator *op, const char *fmt, va_list vlist);
220 /*get a point to a slot. this may be removed layer on from the public API.*/
221 BMOpSlot *BMO_GetSlot(struct BMOperator *op, const char *slotname);
223 /*copies the data of a slot from one operator to another. src and dst are the
224 source/destination slot codes, respectively.*/
225 void BMO_CopySlot(struct BMOperator *source_op, struct BMOperator *dest_op,
226 const char *src, const char *dst);
228 /*remove tool flagged elements*/
229 void BM_remove_tagged_faces(struct BMesh *bm, int flag);
230 void BM_remove_tagged_edges(struct BMesh *bm, int flag);
231 void BM_remove_tagged_verts(struct BMesh *bm, int flag);
233 void BMO_Set_OpFlag(struct BMesh *bm, struct BMOperator *op, int flag);
234 void BMO_Clear_OpFlag(struct BMesh *bm, struct BMOperator *op, int flag);
236 void BMO_Set_Float(struct BMOperator *op, const char *slotname, float f);
237 float BMO_Get_Float(BMOperator *op, const char *slotname);
238 void BMO_Set_Int(struct BMOperator *op, const char *slotname, int i);
239 int BMO_Get_Int(BMOperator *op, const char *slotname);
241 /*don't pass in arrays that are supposed to map to elements this way.
243 so, e.g. passing in list of floats per element in another slot is bad.
244 passing in, e.g. pointer to an editmesh for the conversion operator is fine
246 void BMO_Set_Pnt(struct BMOperator *op, const char *slotname, void *p);
247 void *BMO_Get_Pnt(BMOperator *op, const char *slotname);
248 void BMO_Set_Vec(struct BMOperator *op, const char *slotname, float *vec);
249 void BMO_Get_Vec(BMOperator *op, const char *slotname, float *vec_out);
251 /*only supports square mats*/
252 /*size must be 3 or 4; this api is meant only for transformation matrices.
253 note that internally the matrix is stored in 4x4 form, and it's safe to
254 call whichever BMO_Get_Mat* function you want.*/
255 void BMO_Set_Mat(struct BMOperator *op, const char *slotname, float *mat, int size);
256 void BMO_Get_Mat4(struct BMOperator *op, const char *slotname, float mat[4][4]);
257 void BMO_Get_Mat3(struct BMOperator *op, const char *slotname, float mat[3][3]);
259 void BMO_Clear_Flag_All(BMesh *bm, BMOperator *op, int type, int flag);
261 /*puts every element of type type (which is a bitmask) with tool flag flag,
263 void BMO_Flag_To_Slot(struct BMesh *bm, struct BMOperator *op, const char *slotname, int flag, int type);
265 /*tool-flags all elements inside an element slot array with flag flag.*/
266 void BMO_Flag_Buffer(struct BMesh *bm, struct BMOperator *op, const char *slotname, int flag, int type);
267 /*clears tool-flag flag from all elements inside a slot array.*/
268 void BMO_Unflag_Buffer(struct BMesh *bm, struct BMOperator *op, const char *slotname, int flag, int type);
270 /*tool-flags all elements inside an element slot array with flag flag.*/
271 void BMO_HeaderFlag_Buffer(struct BMesh *bm, struct BMOperator *op, const char *slotname, int flag, int type);
272 /*clears tool-flag flag from all elements inside a slot array.*/
273 void BMO_UnHeaderFlag_Buffer(struct BMesh *bm, struct BMOperator *op, const char *slotname, int flag, int type);
275 /*puts every element of type type (which is a bitmask) with header flag
276 flag, into a slot. note: ignores hidden elements (e.g. elements with
277 header flag BM_HIDDEN set).*/
278 void BMO_HeaderFlag_To_Slot(struct BMesh *bm, struct BMOperator *op, const char *slotname, int flag, int type);
280 /*counts number of elements inside a slot array.*/
281 int BMO_CountSlotBuf(struct BMesh *bm, struct BMOperator *op, const char *slotname);
282 int BMO_CountSlotMap(struct BMesh *bm, struct BMOperator *op, const char *slotname);
284 /*Counts the number of edges with tool flag toolflag around
286 int BMO_Vert_CountEdgeFlags(BMesh *bm, BMVert *v, int toolflag);
288 /*inserts a key/value mapping into a mapping slot. note that it copies the
289 value, it doesn't store a reference to it.*/
290 //BM_INLINE void BMO_Insert_Mapping(BMesh *bm, BMOperator *op, const char *slotname,
291 //void *element, void *data, int len);
293 /*inserts a key/float mapping pair into a mapping slot.*/
294 //BM_INLINE void BMO_Insert_MapFloat(BMesh *bm, BMOperator *op, const char *slotname,
295 //void *element, float val);
297 //returns 1 if the specified pointer is in the map.
298 //BM_INLINE int BMO_InMap(BMesh *bm, BMOperator *op, const char *slotname, void *element);
300 /*returns a point to the value of a specific key.*/
301 //BM_INLINE void *BMO_Get_MapData(BMesh *bm, BMOperator *op, const char *slotname, void *element);
303 /*returns the float part of a key/float pair.*/
304 //BM_INLINE float BMO_Get_MapFloat(BMesh *bm, BMOperator *op, const char *slotname, void *element);
306 /*flags all elements in a mapping. note that the mapping must only have
307 bmesh elements in it.*/
308 void BMO_Mapping_To_Flag(struct BMesh *bm, struct BMOperator *op,
309 const char *slotname, int flag);
311 /*pointer versoins of BMO_Get_MapFloat and BMO_Insert_MapFloat.
313 do NOT use these for non-operator-api-allocated memory! instead
314 use BMO_Get_MapData and BMO_Insert_Mapping, which copies the data.*/
315 //BM_INLINE void BMO_Insert_MapPointer(BMesh *bm, BMOperator *op, const char *slotname,
316 //void *key, void *val);
317 //BM_INLINE void *BMO_Get_MapPointer(BMesh *bm, BMOperator *op, const char *slotname,
320 /*this part of the API is used to iterate over element buffer or
323 for example, iterating over the faces in a slot is:
328 f = BMO_IterNew(&oiter, bm, some_operator, "slotname", BM_FACE);
329 for (; f; f=BMO_IterStep(&oiter)) {
330 /do something with the face
333 another example, iterating over a mapping:
338 key = BMO_IterNew(&oiter, bm, some_operator, "slotname", 0);
339 for (; key; key=BMO_IterStep(&oiter)) {
340 val = BMO_IterMapVal(&oiter);
341 //do something with the key/val pair
342 //note that val is a pointer to the val data,
343 //whether it's a float, pointer, whatever.
345 // so to get a pointer, for example, use:
346 // *((void**)BMO_IterMapVal(&oiter));
347 //or something like that.
352 /*contents of this structure are private,
353 don't directly access.*/
354 typedef struct BMOIter {
356 int cur; //for arrays
357 struct GHashIterator giter;
362 void *BMO_FirstElem(BMOperator *op, const char *slotname);
364 /*restrictmask restricts the iteration to certain element types
365 (e.g. combination of BM_VERT, BM_EDGE, BM_FACE), if iterating
366 over an element buffer (not a mapping).*/
367 void *BMO_IterNew(BMOIter *iter, BMesh *bm, BMOperator *op,
368 const char *slotname, int restrictmask);
369 void *BMO_IterStep(BMOIter *iter);
371 /*returns a pointer to the key value when iterating over mappings.
372 remember for pointer maps this will be a pointer to a pointer.*/
373 void *BMO_IterMapVal(BMOIter *iter);
375 /*use this for pointer mappings*/
376 void *BMO_IterMapValp(BMOIter *iter);
378 /*use this for float mappings*/
379 float BMO_IterMapValf(BMOIter *iter);
381 #define BMO_ITER(ele, iter, bm, op, slotname, restrict) \
382 ele = BMO_IterNew(iter, bm, op, slotname, restrict); \
383 for ( ; ele; ele=BMO_IterStep(iter))
385 /******************* Inlined Functions********************/
386 typedef void (*opexec)(struct BMesh *bm, struct BMOperator *op);
388 /*mappings map elements to data, which
389 follows the mapping struct in memory.*/
390 typedef struct element_mapping {
395 extern const int BMOP_OPSLOT_TYPEINFO[];
397 BM_INLINE void BMO_Insert_Mapping(BMesh *UNUSED(bm), BMOperator *op, const char *slotname,
398 void *element, void *data, int len) {
399 element_mapping *mapping;
400 BMOpSlot *slot = BMO_GetSlot(op, slotname);
403 if (slot->slottype != BMOP_OPSLOT_MAPPING) return;
405 mapping = (element_mapping*) BLI_memarena_alloc(op->arena, sizeof(*mapping) + len);
407 mapping->element = (BMHeader*) element;
409 memcpy(mapping+1, data, len);
411 if (!slot->data.ghash) {
412 slot->data.ghash = BLI_ghash_new(BLI_ghashutil_ptrhash,
413 BLI_ghashutil_ptrcmp, "bmesh op");
416 BLI_ghash_insert(slot->data.ghash, element, mapping);
419 BM_INLINE void BMO_Insert_MapInt(BMesh *bm, BMOperator *op, const char *slotname,
420 void *element, int val)
422 BMO_Insert_Mapping(bm, op, slotname, element, &val, sizeof(int));
425 BM_INLINE void BMO_Insert_MapFloat(BMesh *bm, BMOperator *op, const char *slotname,
426 void *element, float val)
428 BMO_Insert_Mapping(bm, op, slotname, element, &val, sizeof(float));
431 BM_INLINE void BMO_Insert_MapPointer(BMesh *bm, BMOperator *op, const char *slotname,
432 void *element, void *val)
434 BMO_Insert_Mapping(bm, op, slotname, element, &val, sizeof(void*));
437 BM_INLINE int BMO_InMap(BMesh *UNUSED(bm), BMOperator *op, const char *slotname, void *element)
439 BMOpSlot *slot = BMO_GetSlot(op, slotname);
442 if (slot->slottype != BMOP_OPSLOT_MAPPING) return 0;
443 if (!slot->data.ghash) return 0;
445 return BLI_ghash_haskey(slot->data.ghash, element);
448 BM_INLINE void *BMO_Get_MapData(BMesh *UNUSED(bm), BMOperator *op, const char *slotname,
451 element_mapping *mapping;
452 BMOpSlot *slot = BMO_GetSlot(op, slotname);
455 if (slot->slottype != BMOP_OPSLOT_MAPPING) return NULL;
456 if (!slot->data.ghash) return NULL;
458 mapping = (element_mapping*) BLI_ghash_lookup(slot->data.ghash, element);
460 if (!mapping) return NULL;
465 BM_INLINE float BMO_Get_MapFloat(BMesh *bm, BMOperator *op, const char *slotname,
468 float *val = (float*) BMO_Get_MapData(bm, op, slotname, element);
469 if (val) return *val;
474 BM_INLINE int BMO_Get_MapInt(BMesh *bm, BMOperator *op, const char *slotname,
477 int *val = (int*) BMO_Get_MapData(bm, op, slotname, element);
478 if (val) return *val;
483 BM_INLINE void *BMO_Get_MapPointer(BMesh *bm, BMOperator *op, const char *slotname,
486 void **val = (void**) BMO_Get_MapData(bm, op, slotname, element);
487 if (val) return *val;
496 #endif /* _BMESH_OPERATOR_API_H */