67daa3231294ffd2689b2198040e9d05357aa185
[blender.git] / source / blender / bmesh / bmesh_operator_api.h
1 #ifndef _BMESH_OPERATOR_H
2 #define _BMESH_OPERATOR_H
3
4 #include "BLI_memarena.h"
5 #include "BLI_ghash.h"
6
7 #include "BKE_utildefines.h"
8
9 #include <stdarg.h>
10
11 /*
12 operators represent logical, executable mesh modules.  all topological 
13 operations involving a bmesh has to go through them.
14
15 operators are nested, as are tool flags, which are private to an operator 
16 when it's executed.  tool flags are allocated in layers, one per operator
17 execution, and are used for all internal flagging a tool needs to do.
18
19 each operator has a series of "slots," which can be of the following types:
20 * simple numerical types
21 * arrays of elements (e.g. arrays of faces).
22 * hash mappings.
23
24 each slot is identified by a slot code, as are each operator. 
25 operators, and their slots, are defined in bmesh_opdefines.c (with their 
26 execution functions prototyped in bmesh_operators_private.h), with all their
27 operator code and slot codes defined in bmesh_operators.h.  see
28 bmesh_opdefines.c and the BMOpDefine struct for how to define new operators.
29
30 in general, operators are fed arrays of elements, created using either
31 BM_HeaderFlag_To_Slot or BM_Flag_To_Slot (or through one of the format
32 specifyers in BMO_CallOpf or BMO_InitOpf).  Note that multiple element
33 types (e.g. faces and edges) can be fed to the same slot array.  Operators
34 act on this data, and possibly spit out data into output slots.
35
36 some notes:
37 * operators should never read from header flags (e.g. element->head.flag). for
38   example, if you want an operator to only operate on selected faces, you
39   should use BM_HeaderFlag_To_Slot to put the selected elements into a slot.
40 * when you read from an element slot array or mapping, you can either tool-flag 
41   all the elements in it, or read them using an iterator APi (which is 
42   semantically similar to the iterator api in bmesh_iterators.h).
43 */
44
45 struct GHashIterator;
46
47 /*slot type arrays are terminated by the last member
48   having a slot type of 0.*/
49 #define BMOP_OPSLOT_SENTINEL            0
50 #define BMOP_OPSLOT_INT                 1
51 #define BMOP_OPSLOT_FLT                 2
52 #define BMOP_OPSLOT_PNT                 3
53 #define BMOP_OPSLOT_MAT                 4
54 #define BMOP_OPSLOT_VEC                 7
55
56 /*after BMOP_OPSLOT_VEC, everything is 
57
58   dynamically allocated arrays.  we
59   leave a space in the identifiers
60   for future growth.
61
62   */
63 //it's very important this remain a power of two
64 #define BMOP_OPSLOT_ELEMENT_BUF         8
65 #define BMOP_OPSLOT_MAPPING             9
66 #define BMOP_OPSLOT_TYPES               10
67
68 /*please ignore all these structures, don't touch them in tool code, except
69   for when your defining an operator with BMOpDefine.*/
70
71 typedef struct BMOpSlot{
72         int slottype;
73         int len;
74         int flag;
75         int index; /*index within slot array*/
76         union {
77                 int i;
78                 float f;                                        
79                 void *p;                                        
80                 float vec[3];
81                 void *buf;
82                 GHash *ghash;
83         } data;
84 } BMOpSlot;
85
86 #define BMOP_MAX_SLOTS                  16 /*way more than probably needed*/
87
88 typedef struct BMOperator {
89         int type;
90         int slottype;
91         int needflag;
92         struct BMOpSlot slots[BMOP_MAX_SLOTS];
93         void (*exec)(struct BMesh *bm, struct BMOperator *op);
94         MemArena *arena;
95 } BMOperator;
96
97 #define MAX_SLOTNAME    32
98
99 typedef struct slottype {
100         int type;
101         char name[MAX_SLOTNAME];
102 } slottype;
103
104 typedef struct BMOpDefine {
105         char *name;
106         slottype slottypes[BMOP_MAX_SLOTS];
107         void (*exec)(BMesh *bm, BMOperator *op);
108         int flag; /*doesn't do anything right now*/
109 } BMOpDefine;
110
111 /*------------- Operator API --------------*/
112
113 /*data types that use pointers (arrays, etc) should never
114   have it set directly.  and never use BMO_Set_Pnt to
115   pass in a list of edges or any arrays, really.*/
116
117 void BMO_Init_Op(struct BMOperator *op, char *opname);
118
119 /*executes an operator, pushing and popping a new tool flag 
120   layer as appropriate.*/
121 void BMO_Exec_Op(struct BMesh *bm, struct BMOperator *op);
122
123 /*finishes an operator (though note the operator's tool flag is removed 
124   after it finishes executing in BMO_Exec_Op).*/
125 void BMO_Finish_Op(struct BMesh *bm, struct BMOperator *op);
126
127
128 /*tool flag API. never, ever ever should tool code put junk in 
129   header flags (element->head.flag), nor should they use 
130   element->head.eflag1/eflag2.  instead, use this api to set
131   flags.  
132   
133   if you need to store a value per element, use a 
134   ghash or a mapping slot to do it.*/
135 /*flags 15 and 16 (1<<14 and 1<<15) are reserved for bmesh api use*/
136 #define BMO_TestFlag(bm, element, flag) (((BMHeader*)element)->flags[bm->stackdepth-1].mask & (flag))
137 #define BMO_SetFlag(bm, element, flag) (((BMHeader*)element)->flags[bm->stackdepth-1].mask |= (flag))
138 #define BMO_ClearFlag(bm, element, flag) (((BMHeader*)element)->flags[bm->stackdepth-1].mask &= ~(flag))
139
140 /*profiling showed a significant amount of time spent in BMO_TestFlag
141 void BMO_SetFlag(struct BMesh *bm, void *element, int flag);
142 void BMO_ClearFlag(struct BMesh *bm, void *element, int flag);
143 int BMO_TestFlag(struct BMesh *bm, void *element, int flag);*/
144
145 /*count the number of elements with a specific flag.  type
146   can be a bitmask of BM_FACE, BM_EDGE, or BM_FACE.*/
147 int BMO_CountFlag(struct BMesh *bm, int flag, int type);
148
149 /*---------formatted operator initialization/execution-----------*/
150 /*
151   this system is used to execute or initialize an operator,
152   using a formatted-string system.
153
154   for example, BMO_CallOpf(bm, "del geom=%hf context=%d", BM_SELECT, DEL_FACES);
155   . . .will execute the delete operator, feeding in selected faces, deleting them.
156
157   the basic format for the format string is:
158     [operatorname] [slotname]=%[code] [slotname]=%[code]
159   
160   as in printf, you pass in one additional argument to the function
161   for every code.
162
163   the formatting codes are:
164      %d - put int in slot
165      %f - put float in slot
166      %p - put pointer in slot
167      %h[f/e/v] - put elements with a header flag in slot.
168                   the letters after %h define which element types to use,
169                   so e.g. %hf will do faces, %hfe will do faces and edges,
170                   %hv will do verts, etc.  must pass in at least one
171                   element type letter.
172      %f[f/e/v] - same as %h, except it deals with tool flags instead of
173                   header flags.
174      %a[f/e/v] - pass all elements (of types specified by f/e/v) to the
175                   slot.
176      %e        - pass in a single element.
177      %v - pointer to a float vector of length 3.
178      %m[3/4] - matrix, 3/4 refers to the matrix size, 3 or 4.  the
179                corrusponding argument must be a pointer to
180                a float matrix.
181      %s - copy a slot from another op, instead of mapping to one
182           argument, it maps to two, a pointer to an operator and
183           a slot name.
184 */
185 /*executes an operator*/
186 int BMO_CallOpf(BMesh *bm, char *fmt, ...);
187
188 /*initializes, but doesn't execute an operator.  this is so you can
189   gain access to the outputs of the operator.  note that you have
190   to execute/finitsh (BMO_Exec_Op and BMO_Finish_Op) yourself.*/
191 int BMO_InitOpf(BMesh *bm, BMOperator *op, char *fmt, ...);
192
193 /*va_list version, used to implement the above two functions,
194    plus EDBM_CallOpf in bmeshutils.c.*/
195 int BMO_VInitOpf(BMesh *bm, BMOperator *op, char *fmt, va_list vlist);
196
197 /*get a point to a slot.  this may be removed layer on from the public API.*/
198 BMOpSlot *BMO_GetSlot(struct BMOperator *op, char *slotname);
199
200 /*copies the data of a slot from one operator to another.  src and dst are the
201   source/destination slot codes, respectively.*/
202 void BMO_CopySlot(struct BMOperator *source_op, struct BMOperator *dest_op, 
203                   char *src, char *dst);
204
205 /*remove tool flagged elements*/
206 void BM_remove_tagged_faces(struct BMesh *bm, int flag);
207 void BM_remove_tagged_edges(struct BMesh *bm, int flag);
208 void BM_remove_tagged_verts(struct BMesh *bm, int flag);
209
210 void BMO_Set_Float(struct BMOperator *op, char *slotname, float f);
211 float BMO_Get_Float(BMOperator *op, char *slotname);
212 void BMO_Set_Int(struct BMOperator *op, char *slotname, int i);
213 int BMO_Get_Int(BMOperator *op, char *slotname);
214
215 /*don't pass in arrays that are supposed to map to elements this way.
216   
217   so, e.g. passing in list of floats per element in another slot is bad.
218   passing in, e.g. pointer to an editmesh for the conversion operator is fine
219   though.*/
220 void BMO_Set_Pnt(struct BMOperator *op, char *slotname, void *p);
221 void *BMO_Get_Pnt(BMOperator *op, char *slotname);
222 void BMO_Set_Vec(struct BMOperator *op, char *slotname, float *vec);
223 void BMO_Get_Vec(BMOperator *op, char *slotname, float *vec_out);
224
225 /*only supports square mats*/
226 /*size must be 3 or 4; this api is meant only for transformation matrices.
227   note that internally the matrix is stored in 4x4 form, and it's safe to
228   call whichever BMO_Get_Mat* function you want.*/
229 void BMO_Set_Mat(struct BMOperator *op, char *slotname, float *mat, int size);
230 void BMO_Get_Mat4(struct BMOperator *op, char *slotname, float mat[4][4]);
231 void BMO_Get_Mat3(struct BMOperator *op, char *slotname, float mat[3][3]);
232
233 void BMO_Clear_Flag_All(BMesh *bm, BMOperator *op, int type, int flag);
234
235 /*puts every element of type type (which is a bitmask) with tool flag flag,
236   into a slot.*/
237 void BMO_Flag_To_Slot(struct BMesh *bm, struct BMOperator *op, char *slotname, int flag, int type);
238
239 /*tool-flags all elements inside an element slot array with flag flag.*/
240 void BMO_Flag_Buffer(struct BMesh *bm, struct BMOperator *op, char *slotname, int flag, int type);
241 /*clears tool-flag flag from all elements inside a slot array.*/
242 void BMO_Unflag_Buffer(struct BMesh *bm, struct BMOperator *op, char *slotname, int flag, int type);
243
244 /*tool-flags all elements inside an element slot array with flag flag.*/
245 void BMO_HeaderFlag_Buffer(struct BMesh *bm, struct BMOperator *op, char *slotname, int flag, int type);
246 /*clears tool-flag flag from all elements inside a slot array.*/
247 void BMO_UnHeaderFlag_Buffer(struct BMesh *bm, struct BMOperator *op, char *slotname, int flag, int type);
248
249 /*puts every element of type type (which is a bitmask) with header flag 
250   flag, into a slot.  note: ignores hidden elements (e.g. elements with
251   header flag BM_HIDDEN set).*/
252 void BMO_HeaderFlag_To_Slot(struct BMesh *bm, struct BMOperator *op, char *slotname, int flag, int type);
253
254 /*counts number of elements inside a slot array.*/
255 int BMO_CountSlotBuf(struct BMesh *bm, struct BMOperator *op, char *slotname);
256 int BMO_CountSlotMap(struct BMesh *bm, struct BMOperator *op, char *slotname);
257
258 /*Counts the number of edges with tool flag toolflag around
259   v*/
260 int BMO_Vert_CountEdgeFlags(BMesh *bm, BMVert *v, int toolflag);
261
262 /*inserts a key/value mapping into a mapping slot.  note that it copies the
263   value, it doesn't store a reference to it.*/
264 //BM_INLINE void BMO_Insert_Mapping(BMesh *bm, BMOperator *op, char *slotname, 
265                         //void *element, void *data, int len);
266
267 /*inserts a key/float mapping pair into a mapping slot.*/
268 //BM_INLINE void BMO_Insert_MapFloat(BMesh *bm, BMOperator *op, char *slotname, 
269                         //void *element, float val);
270
271 //returns 1 if the specified pointer is in the map.
272 //BM_INLINE int BMO_InMap(BMesh *bm, BMOperator *op, char *slotname, void *element);
273
274 /*returns a point to the value of a specific key.*/
275 //BM_INLINE void *BMO_Get_MapData(BMesh *bm, BMOperator *op, char *slotname, void *element);
276
277 /*returns the float part of a key/float pair.*/
278 //BM_INLINE float BMO_Get_MapFloat(BMesh *bm, BMOperator *op, char *slotname, void *element);
279
280 /*flags all elements in a mapping.  note that the mapping must only have
281   bmesh elements in it.*/
282 void BMO_Mapping_To_Flag(struct BMesh *bm, struct BMOperator *op, 
283                          char *slotname, int flag);
284
285 /*pointer versoins of BMO_Get_MapFloat and BMO_Insert_MapFloat.
286
287   do NOT use these for non-operator-api-allocated memory! instead
288   use BMO_Get_MapData and BMO_Insert_Mapping, which copies the data.*/
289 //BM_INLINE void BMO_Insert_MapPointer(BMesh *bm, BMOperator *op, char *slotname, 
290                         //void *key, void *val);
291 //BM_INLINE void *BMO_Get_MapPointer(BMesh *bm, BMOperator *op, char *slotname,
292                        //void *key);
293
294 /*this part of the API is used to iterate over element buffer or
295   mapping slots.
296   
297   for example, iterating over the faces in a slot is:
298
299           BMOIter oiter;
300           BMFace *f;
301
302           f = BMO_IterNew(&oiter, bm, some_operator, "slotname", BM_FACE);
303           for (; f; f=BMO_IterStep(&oiter)) {
304                 /do something with the face
305           }
306
307   another example, iterating over a mapping:
308           BMOIter oiter;
309           void *key;
310           void *val;
311
312           key = BMO_IterNew(&oiter, bm, some_operator, "slotname", 0);
313           for (; key; key=BMO_IterStep(&oiter)) {
314                 val = BMO_IterMapVal(&oiter);
315                 //do something with the key/val pair
316                 //note that val is a pointer to the val data,
317                 //whether it's a float, pointer, whatever.
318                 //
319                 // so to get a pointer, for example, use:
320                 //  *((void**)BMO_IterMapVal(&oiter));
321                 //or something like that.
322           }
323
324   */
325
326 /*contents of this structure are private,
327   don't directly access.*/
328 typedef struct BMOIter {
329         BMOpSlot *slot;
330         int cur; //for arrays
331         struct GHashIterator giter;
332         void *val;
333         int restrict;
334 } BMOIter;
335
336 /*restrictmask restricts the iteration to certain element types
337   (e.g. combination of BM_VERT, BM_EDGE, BM_FACE), if iterating
338   over an element buffer (not a mapping).*/
339 void *BMO_IterNew(BMOIter *iter, BMesh *bm, BMOperator *op, 
340                   char *slotname, int restrictmask);
341 void *BMO_IterStep(BMOIter *iter);
342
343 /*returns a pointer to the key value when iterating over mappings.
344   remember for pointer maps this will be a pointer to a pointer.*/
345 void *BMO_IterMapVal(BMOIter *iter);
346
347 /*use this for pointer mappings*/
348 void *BMO_IterMapValp(BMOIter *iter);
349
350 /*use this for float mappings*/
351 float BMO_IterMapValf(BMOIter *iter);
352
353 #define BMO_ITER(ele, iter, bm, op, slotname, restrict) \
354         ele = BMO_IterNew(iter, bm, op, slotname, restrict); \
355         for ( ; ele; ele=BMO_IterStep(iter))
356
357 /******************* Inlined Functions********************/
358 typedef void (*opexec)(struct BMesh *bm, struct BMOperator *op);
359
360 /*mappings map elements to data, which
361   follows the mapping struct in memory.*/
362 typedef struct element_mapping {
363         BMHeader *element;
364         int len;
365 } element_mapping;
366
367 extern const int BMOP_OPSLOT_TYPEINFO[];
368
369 BM_INLINE void BMO_Insert_Mapping(BMesh *bm, BMOperator *op, char *slotname, 
370                         void *element, void *data, int len) {
371         element_mapping *mapping;
372         BMOpSlot *slot = BMO_GetSlot(op, slotname);
373
374         /*sanity check*/
375         if (slot->slottype != BMOP_OPSLOT_MAPPING) return;
376         
377         mapping = BLI_memarena_alloc(op->arena, sizeof(*mapping) + len);
378
379         mapping->element = element;
380         mapping->len = len;
381         memcpy(mapping+1, data, len);
382
383         if (!slot->data.ghash) {
384                 slot->data.ghash = BLI_ghash_new(BLI_ghashutil_ptrhash, 
385                                                      BLI_ghashutil_ptrcmp);
386         }
387         
388         BLI_ghash_insert(slot->data.ghash, element, mapping);
389 }
390
391
392 BM_INLINE void BMO_Insert_MapFloat(BMesh *bm, BMOperator *op, char *slotname, 
393                         void *element, float val)
394 {
395         BMO_Insert_Mapping(bm, op, slotname, element, &val, sizeof(float));
396 }
397
398 BM_INLINE void BMO_Insert_MapPointer(BMesh *bm, BMOperator *op, char *slotname, 
399                         void *element, void *val)
400 {
401         BMO_Insert_Mapping(bm, op, slotname, element, &val, sizeof(void*));
402 }
403
404 BM_INLINE int BMO_InMap(BMesh *bm, BMOperator *op, char *slotname, void *element)
405 {
406         BMOpSlot *slot = BMO_GetSlot(op, slotname);
407
408         /*sanity check*/
409         if (slot->slottype != BMOP_OPSLOT_MAPPING) return 0;
410         if (!slot->data.ghash) return 0;
411
412         return BLI_ghash_haskey(slot->data.ghash, element);
413 }
414
415 BM_INLINE void *BMO_Get_MapData(BMesh *bm, BMOperator *op, char *slotname,
416                       void *element)
417 {
418         element_mapping *mapping;
419         BMOpSlot *slot = BMO_GetSlot(op, slotname);
420
421         /*sanity check*/
422         if (slot->slottype != BMOP_OPSLOT_MAPPING) return NULL;
423         if (!slot->data.ghash) return NULL;
424
425         mapping = BLI_ghash_lookup(slot->data.ghash, element);
426         
427         if (!mapping) return NULL;
428
429         return mapping + 1;
430 }
431
432 BM_INLINE float BMO_Get_MapFloat(BMesh *bm, BMOperator *op, char *slotname,
433                        void *element)
434 {
435         float *val = BMO_Get_MapData(bm, op, slotname, element);
436         if (val) return *val;
437
438         return 0.0f;
439 }
440
441 BM_INLINE void *BMO_Get_MapPointer(BMesh *bm, BMOperator *op, char *slotname,
442                        void *element)
443 {
444         void **val = BMO_Get_MapData(bm, op, slotname, element);
445         if (val) return *val;
446
447         return NULL;
448 }
449
450 #endif /* _BMESH_OPERATOR_H */