2 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
18 * Contributor(s): Joseph Eagar.
20 * ***** END GPL LICENSE BLOCK *****
23 #ifndef _BMESH_OPERATOR_API_H
24 #define _BMESH_OPERATOR_API_H
30 #include "BLI_memarena.h"
31 #include "BLI_ghash.h"
33 #include "BKE_utildefines.h"
36 #include <string.h> /* for memcpy */
39 * operators represent logical, executable mesh modules. all topological
40 * operations involving a bmesh has to go through them.
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.
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).
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.
57 * in general, operators are fed arrays of elements, created using either
58 * BM_HeaderFlag_To_Slot or BM_Flag_To_Slot (or through one of the format
59 * specifyers in BMO_CallOpf or BMO_InitOpf). Note that multiple element
60 * types (e.g. faces and edges) can be fed to the same slot array. Operators
61 * act on this data, and possibly spit out data into output slots.
64 * - operators should never read from header flags (e.g. element->head.flag). for
65 * example, if you want an operator to only operate on selected faces, you
66 * should use BM_HeaderFlag_To_Slot to put the selected elements into a slot.
67 * - when you read from an element slot array or mapping, you can either tool-flag
68 * all the elements in it, or read them using an iterator APi (which is
69 * semantically similar to the iterator api in bmesh_iterators.h).
74 /* slot type arrays are terminated by the last member
75 * having a slot type of 0.*/
76 #define BMOP_OPSLOT_SENTINEL 0
77 #define BMOP_OPSLOT_INT 1
78 #define BMOP_OPSLOT_FLT 2
79 #define BMOP_OPSLOT_PNT 3
80 #define BMOP_OPSLOT_MAT 4
81 #define BMOP_OPSLOT_VEC 7
83 /* after BMOP_OPSLOT_VEC, everything is
85 * dynamically allocated arrays. we
86 * leave a space in the identifiers
89 //it's very important this remain a power of two
90 #define BMOP_OPSLOT_ELEMENT_BUF 8
91 #define BMOP_OPSLOT_MAPPING 9
92 #define BMOP_OPSLOT_TYPES 10
94 /* please ignore all these structures, don't touch them in tool code, except
95 * for when your defining an operator with BMOpDefine.*/
97 typedef struct BMOpSlot{
101 int index; /* index within slot array */
112 #define BMOP_MAX_SLOTS 16 /* way more than probably needed */
118 typedef struct BMOperator {
123 struct BMOpSlot slots[BMOP_MAX_SLOTS];
124 void (*exec)(struct BMesh *bm, struct BMOperator *op);
128 #define MAX_SLOTNAME 32
130 typedef struct BMOSlotType {
132 char name[MAX_SLOTNAME];
135 typedef struct BMOpDefine {
137 BMOSlotType slottypes[BMOP_MAX_SLOTS];
138 void (*exec)(BMesh *bm, BMOperator *op);
143 #define BMOP_UNTAN_MULTIRES 1 /*switch from multires tangent space to absolute coordinates*/
146 /* ensures consistent normals before operator execution,
147 * restoring the original ones windings/normals afterwards.
148 * keep in mind, this won't work if the input mesh isn't
150 #define BMOP_RATIONALIZE_NORMALS 2
152 /*------------- Operator API --------------*/
154 /* data types that use pointers (arrays, etc) should never
155 * have it set directly. and never use BMO_Set_Pnt to
156 * pass in a list of edges or any arrays, really.*/
158 void BMO_Init_Op(struct BMesh *bm, struct BMOperator *op, const char *opname);
160 /* executes an operator, pushing and popping a new tool flag
161 * layer as appropriate.*/
162 void BMO_Exec_Op(struct BMesh *bm, struct BMOperator *op);
164 /* finishes an operator (though note the operator's tool flag is removed
165 * after it finishes executing in BMO_Exec_Op).*/
166 void BMO_Finish_Op(struct BMesh *bm, struct BMOperator *op);
169 /* tool flag API. never, ever ever should tool code put junk in
170 * header flags (element->head.flag), nor should they use
171 * element->head.eflag1/eflag2. instead, use this api to set
174 * if you need to store a value per element, use a
175 * ghash or a mapping slot to do it. */
177 /* flags 15 and 16 (1<<14 and 1<<15) are reserved for bmesh api use */
178 #define BMO_TestFlag(bm, element, oflag) (((BMHeader*)(element))->flags[bm->stackdepth-1].f & (oflag))
179 #define BMO_SetFlag(bm, element, oflag) (((BMHeader*)(element))->flags[bm->stackdepth-1].f |= (oflag))
180 #define BMO_ClearFlag(bm, element, oflag) (((BMHeader*)(element))->flags[bm->stackdepth-1].f &= ~(oflag))
181 #define BMO_ToggleFlag(bm, element, oflag) (((BMHeader*)(element))->flags[bm->stackdepth-1].f ^= (oflag))
183 /*profiling showed a significant amount of time spent in BMO_TestFlag
184 void BMO_SetFlag(struct BMesh *bm, void *element, int oflag);
185 void BMO_ClearFlag(struct BMesh *bm, void *element, int oflag);
186 int BMO_TestFlag(struct BMesh *bm, void *element, int oflag);*/
188 /* count the number of elements with a specific flag.
189 * type can be a bitmask of BM_FACE, BM_EDGE, or BM_FACE. */
190 int BMO_CountFlag(struct BMesh *bm, const int oflag, const char htype);
192 /*---------formatted operator initialization/execution-----------*/
194 * this system is used to execute or initialize an operator,
195 * using a formatted-string system.
197 * for example, BMO_CallOpf(bm, "del geom=%hf context=%d", BM_SELECT, DEL_FACES);
198 * . . .will execute the delete operator, feeding in selected faces, deleting them.
200 * the basic format for the format string is:
201 * [operatorname] [slotname]=%[code] [slotname]=%[code]
203 * as in printf, you pass in one additional argument to the function
206 * the formatting codes are:
207 * %d - put int in slot
208 * %f - put float in slot
209 * %p - put pointer in slot
210 * %h[f/e/v] - put elements with a header flag in slot.
211 * the letters after %h define which element types to use,
212 * so e.g. %hf will do faces, %hfe will do faces and edges,
213 * %hv will do verts, etc. must pass in at least one
214 * element type letter.
215 * %f[f/e/v] - same as %h, except it deals with tool flags instead of
217 * %a[f/e/v] - pass all elements (of types specified by f/e/v) to the
219 * %e - pass in a single element.
220 * %v - pointer to a float vector of length 3.
221 * %m[3/4] - matrix, 3/4 refers to the matrix size, 3 or 4. the
222 * corrusponding argument must be a pointer to
224 * %s - copy a slot from another op, instead of mapping to one
225 * argument, it maps to two, a pointer to an operator and
228 void BMO_push(BMesh *bm, BMOperator *op);
229 void BMO_pop(BMesh *bm);
231 /*executes an operator*/
232 int BMO_CallOpf(BMesh *bm, const char *fmt, ...);
234 /* initializes, but doesn't execute an operator. this is so you can
235 * gain access to the outputs of the operator. note that you have
236 * to execute/finitsh (BMO_Exec_Op and BMO_Finish_Op) yourself. */
237 int BMO_InitOpf(BMesh *bm, BMOperator *op, const char *fmt, ...);
239 /* va_list version, used to implement the above two functions,
240 * plus EDBM_CallOpf in bmeshutils.c. */
241 int BMO_VInitOpf(BMesh *bm, BMOperator *op, const char *fmt, va_list vlist);
243 /* test whether a named slot exists */
244 int BMO_HasSlot(struct BMOperator *op, const char *slotname);
246 /* get a pointer to a slot. this may be removed layer on from the public API. */
247 BMOpSlot *BMO_GetSlot(struct BMOperator *op, const char *slotname);
249 /* copies the data of a slot from one operator to another. src and dst are the
250 * source/destination slot codes, respectively. */
251 void BMO_CopySlot(struct BMOperator *source_op, struct BMOperator *dest_op,
252 const char *src, const char *dst);
254 /*remove tool flagged elements*/
255 void BM_remove_tagged_faces(struct BMesh *bm, const int oflag);
256 void BM_remove_tagged_edges(struct BMesh *bm, const int oflag);
257 void BM_remove_tagged_verts(struct BMesh *bm, const int oflag);
259 void BMO_Set_OpFlag(struct BMesh *bm, struct BMOperator *op, const int oflag);
260 void BMO_Clear_OpFlag(struct BMesh *bm, struct BMOperator *op, const int oflag);
262 void BMO_Set_Float(struct BMOperator *op, const char *slotname, float f);
263 float BMO_Get_Float(BMOperator *op, const char *slotname);
264 void BMO_Set_Int(struct BMOperator *op, const char *slotname, int i);
265 int BMO_Get_Int(BMOperator *op, const char *slotname);
267 /* don't pass in arrays that are supposed to map to elements this way.
269 * so, e.g. passing in list of floats per element in another slot is bad.
270 * passing in, e.g. pointer to an editmesh for the conversion operator is fine
272 void BMO_Set_Pnt(struct BMOperator *op, const char *slotname, void *p);
273 void *BMO_Get_Pnt(BMOperator *op, const char *slotname);
274 void BMO_Set_Vec(struct BMOperator *op, const char *slotname, const float vec[3]);
275 void BMO_Get_Vec(BMOperator *op, const char *slotname, float r_vec[3]);
277 /* only supports square mats */
278 /* size must be 3 or 4; this api is meant only for transformation matrices.
279 * note that internally the matrix is stored in 4x4 form, and it's safe to
280 * call whichever BMO_Get_Mat* function you want. */
281 void BMO_Set_Mat(struct BMOperator *op, const char *slotname, float *mat, int size);
282 void BMO_Get_Mat4(struct BMOperator *op, const char *slotname, float mat[4][4]);
283 void BMO_Get_Mat3(struct BMOperator *op, const char *slotname, float mat[3][3]);
285 void BMO_Clear_Flag_All(BMesh *bm, BMOperator *op, const char htype, const int oflag);
287 /* puts every element of type type (which is a bitmask) with tool flag flag,
289 void BMO_Flag_To_Slot(struct BMesh *bm, struct BMOperator *op, const char *slotname,
290 const int oflag, const char htype);
292 /* tool-flags all elements inside an element slot array with flag flag. */
293 void BMO_Flag_Buffer(struct BMesh *bm, struct BMOperator *op, const char *slotname,
294 const int oflag, const char htype);
295 /* clears tool-flag flag from all elements inside a slot array. */
296 void BMO_Unflag_Buffer(struct BMesh *bm, struct BMOperator *op, const char *slotname,
297 const int oflag, const char htype);
299 /* tool-flags all elements inside an element slot array with flag flag. */
300 void BMO_HeaderFlag_Buffer(struct BMesh *bm, struct BMOperator *op, const char *slotname,
301 const char hflag, const char htype);
302 /* clears tool-flag flag from all elements inside a slot array. */
303 void BMO_UnHeaderFlag_Buffer(struct BMesh *bm, struct BMOperator *op, const char *slotname,
304 const char hflag, const char htype);
306 /* puts every element of type type (which is a bitmask) with header flag
307 * flag, into a slot. note: ignores hidden elements (e.g. elements with
308 * header flag BM_HIDDEN set).*/
309 void BMO_HeaderFlag_To_Slot(struct BMesh *bm, struct BMOperator *op, const char *slotname,
310 const char hflag, const char htype);
312 /* counts number of elements inside a slot array. */
313 int BMO_CountSlotBuf(struct BMesh *bm, struct BMOperator *op, const char *slotname);
314 int BMO_CountSlotMap(struct BMesh *bm, struct BMOperator *op, const char *slotname);
316 /* Counts the number of edges with tool flag toolflag around
318 int BMO_Vert_CountEdgeFlags(BMesh *bm, BMVert *v, const int oflag);
320 /* inserts a key/value mapping into a mapping slot. note that it copies the
321 * value, it doesn't store a reference to it. */
323 //BM_INLINE void BMO_Insert_Mapping(BMesh *bm, BMOperator *op, const char *slotname,
324 //void *element, void *data, int len);
326 /* inserts a key/float mapping pair into a mapping slot. */
327 //BM_INLINE void BMO_Insert_MapFloat(BMesh *bm, BMOperator *op, const char *slotname,
328 //void *element, float val);
330 //returns 1 if the specified pointer is in the map.
331 //BM_INLINE int BMO_InMap(BMesh *bm, BMOperator *op, const char *slotname, void *element);
333 /* returns a point to the value of a specific key. */
334 //BM_INLINE void *BMO_Get_MapData(BMesh *bm, BMOperator *op, const char *slotname, void *element);
336 /* returns the float part of a key/float pair. */
337 //BM_INLINE float BMO_Get_MapFloat(BMesh *bm, BMOperator *op, const char *slotname, void *element);
339 /* flags all elements in a mapping. note that the mapping must only have
340 * bmesh elements in it.*/
341 void BMO_Mapping_To_Flag(struct BMesh *bm, struct BMOperator *op,
342 const char *slotname, const int oflag);
344 /* pointer versoins of BMO_Get_MapFloat and BMO_Insert_MapFloat.
346 * do NOT use these for non-operator-api-allocated memory! instead
347 * use BMO_Get_MapData and BMO_Insert_Mapping, which copies the data. */
349 //BM_INLINE void BMO_Insert_MapPointer(BMesh *bm, BMOperator *op, const char *slotname,
350 //void *key, void *val);
351 //BM_INLINE void *BMO_Get_MapPointer(BMesh *bm, BMOperator *op, const char *slotname,
354 /* this part of the API is used to iterate over element buffer or
357 * for example, iterating over the faces in a slot is:
362 * f = BMO_IterNew(&oiter, bm, some_operator, "slotname", BM_FACE);
363 * for (; f; f=BMO_IterStep(&oiter)) {
364 * /do something with the face
367 * another example, iterating over a mapping:
372 * key = BMO_IterNew(&oiter, bm, some_operator, "slotname", 0);
373 * for (; key; key=BMO_IterStep(&oiter)) {
374 * val = BMO_IterMapVal(&oiter);
375 * //do something with the key/val pair
376 * //note that val is a pointer to the val data,
377 * //whether it's a float, pointer, whatever.
379 * // so to get a pointer, for example, use:
380 * // *((void**)BMO_IterMapVal(&oiter));
381 * //or something like that.
385 /* contents of this structure are private,
386 * don't directly access. */
387 typedef struct BMOIter {
389 int cur; //for arrays
390 struct GHashIterator giter;
392 char restrictmask; /* bitwise '&' with BMHeader.htype */
395 void *BMO_FirstElem(BMOperator *op, const char *slotname);
397 /* restrictmask restricts the iteration to certain element types
398 * (e.g. combination of BM_VERT, BM_EDGE, BM_FACE), if iterating
399 * over an element buffer (not a mapping).*/
400 void *BMO_IterNew(BMOIter *iter, BMesh *bm, BMOperator *op,
401 const char *slotname, const char restrictmask);
402 void *BMO_IterStep(BMOIter *iter);
404 /* returns a pointer to the key value when iterating over mappings.
405 * remember for pointer maps this will be a pointer to a pointer.*/
406 void *BMO_IterMapVal(BMOIter *iter);
408 /* use this for pointer mappings */
409 void *BMO_IterMapValp(BMOIter *iter);
411 /* use this for float mappings */
412 float BMO_IterMapValf(BMOIter *iter);
414 #define BMO_ITER(ele, iter, bm, op, slotname, restrict) \
415 ele = BMO_IterNew(iter, bm, op, slotname, restrict); \
416 for ( ; ele; ele=BMO_IterStep(iter))
418 /******************* Inlined Functions********************/
419 typedef void (*opexec)(struct BMesh *bm, struct BMOperator *op);
421 /* mappings map elements to data, which
422 * follows the mapping struct in memory. */
423 typedef struct BMOElemMapping {
428 extern const int BMOP_OPSLOT_TYPEINFO[];
430 BM_INLINE void BMO_Insert_Mapping(BMesh *UNUSED(bm), BMOperator *op, const char *slotname,
431 void *element, void *data, int len) {
432 BMOElemMapping *mapping;
433 BMOpSlot *slot = BMO_GetSlot(op, slotname);
436 if (slot->slottype != BMOP_OPSLOT_MAPPING) return;
438 mapping = (BMOElemMapping *) BLI_memarena_alloc(op->arena, sizeof(*mapping) + len);
440 mapping->element = (BMHeader*) element;
442 memcpy(mapping+1, data, len);
444 if (!slot->data.ghash) {
445 slot->data.ghash = BLI_ghash_new(BLI_ghashutil_ptrhash,
446 BLI_ghashutil_ptrcmp, "bmesh op");
449 BLI_ghash_insert(slot->data.ghash, element, mapping);
452 BM_INLINE void BMO_Insert_MapInt(BMesh *bm, BMOperator *op, const char *slotname,
453 void *element, int val)
455 BMO_Insert_Mapping(bm, op, slotname, element, &val, sizeof(int));
458 BM_INLINE void BMO_Insert_MapFloat(BMesh *bm, BMOperator *op, const char *slotname,
459 void *element, float val)
461 BMO_Insert_Mapping(bm, op, slotname, element, &val, sizeof(float));
464 BM_INLINE void BMO_Insert_MapPointer(BMesh *bm, BMOperator *op, const char *slotname,
465 void *element, void *val)
467 BMO_Insert_Mapping(bm, op, slotname, element, &val, sizeof(void*));
470 BM_INLINE int BMO_InMap(BMesh *UNUSED(bm), BMOperator *op, const char *slotname, void *element)
472 BMOpSlot *slot = BMO_GetSlot(op, slotname);
475 if (slot->slottype != BMOP_OPSLOT_MAPPING) return 0;
476 if (!slot->data.ghash) return 0;
478 return BLI_ghash_haskey(slot->data.ghash, element);
481 BM_INLINE void *BMO_Get_MapData(BMesh *UNUSED(bm), BMOperator *op, const char *slotname,
484 BMOElemMapping *mapping;
485 BMOpSlot *slot = BMO_GetSlot(op, slotname);
488 if (slot->slottype != BMOP_OPSLOT_MAPPING) return NULL;
489 if (!slot->data.ghash) return NULL;
491 mapping = (BMOElemMapping *) BLI_ghash_lookup(slot->data.ghash, element);
493 if (!mapping) return NULL;
498 BM_INLINE float BMO_Get_MapFloat(BMesh *bm, BMOperator *op, const char *slotname,
501 float *val = (float*) BMO_Get_MapData(bm, op, slotname, element);
502 if (val) return *val;
507 BM_INLINE int BMO_Get_MapInt(BMesh *bm, BMOperator *op, const char *slotname,
510 int *val = (int*) BMO_Get_MapData(bm, op, slotname, element);
511 if (val) return *val;
516 BM_INLINE void *BMO_Get_MapPointer(BMesh *bm, BMOperator *op, const char *slotname,
519 void **val = (void**) BMO_Get_MapData(bm, op, slotname, element);
520 if (val) return *val;
525 BM_INLINE void BMO_SetIndex(BMesh *bm, const void *element, int index)
527 BMHeader *header = (BMHeader *)element;
528 header->flags[bm->stackdepth-1].index = index;
531 BM_INLINE int BMO_GetIndex(BMesh *bm, void *element)
533 BMHeader *header = (BMHeader *)element;
534 return header->flags[bm->stackdepth-1].index;
541 #endif /* _BMESH_OPERATOR_API_H */