svn merge -r39890:39889 source/blender/editors/object/object_relations.c source...
[blender.git] / source / blender / bmesh / bmesh_operator_api.h
1 #ifndef _BMESH_OPERATOR_API_H
2 #define _BMESH_OPERATOR_API_H
3
4 #ifdef __cplusplus
5 extern "C" {
6 #endif
7
8 #include "BLI_memarena.h"
9 #include "BLI_ghash.h"
10
11 #include "BKE_utildefines.h"
12
13 #include <stdarg.h>
14
15 /*
16 operators represent logical, executable mesh modules.  all topological 
17 operations involving a bmesh has to go through them.
18
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.
22
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).
26 * hash mappings.
27
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.
33
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.
39
40 some notes:
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).
47 */
48
49 struct GHashIterator;
50
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
59
60 /*after BMOP_OPSLOT_VEC, everything is 
61
62   dynamically allocated arrays.  we
63   leave a space in the identifiers
64   for future growth.
65
66   */
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
71
72 /*please ignore all these structures, don't touch them in tool code, except
73   for when your defining an operator with BMOpDefine.*/
74
75 typedef struct BMOpSlot{
76         int slottype;
77         int len;
78         int flag;
79         int index; /*index within slot array*/
80         union {
81                 int i;
82                 float f;                                        
83                 void *p;                                        
84                 float vec[3];
85                 void *buf;
86                 GHash *ghash;
87         } data;
88 } BMOpSlot;
89
90 #define BMOP_MAX_SLOTS                  16 /*way more than probably needed*/
91
92 #ifdef slots
93 #undef slots
94 #endif
95
96 typedef struct BMOperator {
97         int type;
98         int slottype;
99         int needflag;
100         int flag;
101         struct BMOpSlot slots[BMOP_MAX_SLOTS];
102         void (*exec)(struct BMesh *bm, struct BMOperator *op);
103         MemArena *arena;
104 } BMOperator;
105
106 #define MAX_SLOTNAME    32
107
108 typedef struct slottype {
109         int type;
110         char name[MAX_SLOTNAME];
111 } slottype;
112
113 typedef struct BMOpDefine {
114         const char *name;
115         slottype slottypes[BMOP_MAX_SLOTS];
116         void (*exec)(BMesh *bm, BMOperator *op);
117         int flag; 
118 } BMOpDefine;
119
120 /*BMOpDefine->flag*/
121 #define BMOP_UNTAN_MULTIRES             1 /*switch from multires tangent space to absolute coordinates*/
122
123
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
127   manifold.*/
128 #define BMOP_RATIONALIZE_NORMALS 2
129
130 /*------------- Operator API --------------*/
131
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.*/
135
136 void BMO_Init_Op(struct BMOperator *op, const char *opname);
137
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);
141
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);
145
146
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
150   flags.  
151   
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))
159
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);*/
164
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);
168
169 /*---------formatted operator initialization/execution-----------*/
170 /*
171   this system is used to execute or initialize an operator,
172   using a formatted-string system.
173
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.
176
177   the basic format for the format string is:
178     [operatorname] [slotname]=%[code] [slotname]=%[code]
179   
180   as in printf, you pass in one additional argument to the function
181   for every code.
182
183   the formatting codes are:
184      %d - put int in slot
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
191                   element type letter.
192      %f[f/e/v] - same as %h, except it deals with tool flags instead of
193                   header flags.
194      %a[f/e/v] - pass all elements (of types specified by f/e/v) to the
195                   slot.
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
200                a float matrix.
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
203           a slot name.
204 */
205 void BMO_push(BMesh *bm, BMOperator *op);
206 void BMO_pop(BMesh *bm);
207
208 /*executes an operator*/
209 int BMO_CallOpf(BMesh *bm, const char *fmt, ...);
210
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, ...);
215
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);
219
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);
222
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);
227
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);
232
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);
235
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);
240
241 /*don't pass in arrays that are supposed to map to elements this way.
242   
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
245   though.*/
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);
250
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]);
258
259 void BMO_Clear_Flag_All(BMesh *bm, BMOperator *op, int type, int flag);
260
261 /*puts every element of type type (which is a bitmask) with tool flag flag,
262   into a slot.*/
263 void BMO_Flag_To_Slot(struct BMesh *bm, struct BMOperator *op, const char *slotname, int flag, int type);
264
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);
269
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);
274
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);
279
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);
283
284 /*Counts the number of edges with tool flag toolflag around
285   v*/
286 int BMO_Vert_CountEdgeFlags(BMesh *bm, BMVert *v, int toolflag);
287
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);
292
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);
296
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);
299
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);
302
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);
305
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);
310
311 /*pointer versoins of BMO_Get_MapFloat and BMO_Insert_MapFloat.
312
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,
318                        //void *key);
319
320 /*this part of the API is used to iterate over element buffer or
321   mapping slots.
322   
323   for example, iterating over the faces in a slot is:
324
325           BMOIter oiter;
326           BMFace *f;
327
328           f = BMO_IterNew(&oiter, bm, some_operator, "slotname", BM_FACE);
329           for (; f; f=BMO_IterStep(&oiter)) {
330                 /do something with the face
331           }
332
333   another example, iterating over a mapping:
334           BMOIter oiter;
335           void *key;
336           void *val;
337
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.
344                 //
345                 // so to get a pointer, for example, use:
346                 //  *((void**)BMO_IterMapVal(&oiter));
347                 //or something like that.
348           }
349
350   */
351
352 /*contents of this structure are private,
353   don't directly access.*/
354 typedef struct BMOIter {
355         BMOpSlot *slot;
356         int cur; //for arrays
357         struct GHashIterator giter;
358         void *val;
359         int restrictmask;
360 } BMOIter;
361
362 void *BMO_FirstElem(BMOperator *op, const char *slotname);
363
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);
370
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);
374
375 /*use this for pointer mappings*/
376 void *BMO_IterMapValp(BMOIter *iter);
377
378 /*use this for float mappings*/
379 float BMO_IterMapValf(BMOIter *iter);
380
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))
384
385 /******************* Inlined Functions********************/
386 typedef void (*opexec)(struct BMesh *bm, struct BMOperator *op);
387
388 /*mappings map elements to data, which
389   follows the mapping struct in memory.*/
390 typedef struct element_mapping {
391         BMHeader *element;
392         int len;
393 } element_mapping;
394
395 extern const int BMOP_OPSLOT_TYPEINFO[];
396
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);
401
402         /*sanity check*/
403         if (slot->slottype != BMOP_OPSLOT_MAPPING) return;
404         
405         mapping = (element_mapping*) BLI_memarena_alloc(op->arena, sizeof(*mapping) + len);
406
407         mapping->element = (BMHeader*) element;
408         mapping->len = len;
409         memcpy(mapping+1, data, len);
410
411         if (!slot->data.ghash) {
412                 slot->data.ghash = BLI_ghash_new(BLI_ghashutil_ptrhash, 
413                                                                                  BLI_ghashutil_ptrcmp, "bmesh op");
414         }
415         
416         BLI_ghash_insert(slot->data.ghash, element, mapping);
417 }
418
419 BM_INLINE void BMO_Insert_MapInt(BMesh *bm, BMOperator *op, const char *slotname, 
420                         void *element, int val)
421 {
422         BMO_Insert_Mapping(bm, op, slotname, element, &val, sizeof(int));
423 }
424
425 BM_INLINE void BMO_Insert_MapFloat(BMesh *bm, BMOperator *op, const char *slotname, 
426                         void *element, float val)
427 {
428         BMO_Insert_Mapping(bm, op, slotname, element, &val, sizeof(float));
429 }
430
431 BM_INLINE void BMO_Insert_MapPointer(BMesh *bm, BMOperator *op, const char *slotname, 
432                         void *element, void *val)
433 {
434         BMO_Insert_Mapping(bm, op, slotname, element, &val, sizeof(void*));
435 }
436
437 BM_INLINE int BMO_InMap(BMesh *UNUSED(bm), BMOperator *op, const char *slotname, void *element)
438 {
439         BMOpSlot *slot = BMO_GetSlot(op, slotname);
440
441         /*sanity check*/
442         if (slot->slottype != BMOP_OPSLOT_MAPPING) return 0;
443         if (!slot->data.ghash) return 0;
444
445         return BLI_ghash_haskey(slot->data.ghash, element);
446 }
447
448 BM_INLINE void *BMO_Get_MapData(BMesh *UNUSED(bm), BMOperator *op, const char *slotname,
449                       void *element)
450 {
451         element_mapping *mapping;
452         BMOpSlot *slot = BMO_GetSlot(op, slotname);
453
454         /*sanity check*/
455         if (slot->slottype != BMOP_OPSLOT_MAPPING) return NULL;
456         if (!slot->data.ghash) return NULL;
457
458         mapping = (element_mapping*) BLI_ghash_lookup(slot->data.ghash, element);
459         
460         if (!mapping) return NULL;
461
462         return mapping + 1;
463 }
464
465 BM_INLINE float BMO_Get_MapFloat(BMesh *bm, BMOperator *op, const char *slotname,
466                        void *element)
467 {
468         float *val = (float*) BMO_Get_MapData(bm, op, slotname, element);
469         if (val) return *val;
470
471         return 0.0f;
472 }
473
474 BM_INLINE int BMO_Get_MapInt(BMesh *bm, BMOperator *op, const char *slotname,
475                        void *element)
476 {
477         int *val = (int*) BMO_Get_MapData(bm, op, slotname, element);
478         if (val) return *val;
479
480         return 0;
481 }
482
483 BM_INLINE void *BMO_Get_MapPointer(BMesh *bm, BMOperator *op, const char *slotname,
484                        void *element)
485 {
486         void **val = (void**) BMO_Get_MapData(bm, op, slotname, element);
487         if (val) return *val;
488
489         return NULL;
490 }
491
492 #ifdef __cplusplus
493 }
494 #endif
495
496 #endif /* _BMESH_OPERATOR_API_H */