7bbb579685d8d1dcd344883e3ecbf2c96579963f
[blender.git] / source / blender / bmesh / bmesh_operator_api.h
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
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.
8  *
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.
13  *
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.
17  *
18  * Contributor(s): Joseph Eagar.
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 #ifndef __BMESH_OPERATOR_API_H__
24 #define __BMESH_OPERATOR_API_H__
25
26 /** \file blender/bmesh/bmesh_operator_api.h
27  *  \ingroup bmesh
28  */
29
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33
34 #include "BLI_memarena.h"
35 #include "BLI_ghash.h"
36
37 #include "BKE_utildefines.h"
38
39 #include <stdarg.h>
40 #include <string.h> /* for memcpy */
41
42 /*
43  * operators represent logical, executable mesh modules.  all topological
44  * operations involving a bmesh has to go through them.
45  *
46  * operators are nested, as are tool flags, which are private to an operator
47  * when it's executed.  tool flags are allocated in layers, one per operator
48  * execution, and are used for all internal flagging a tool needs to do.
49  *
50  * each operator has a series of "slots," which can be of the following types:
51  * - simple numerical types
52  * - arrays of elements (e.g. arrays of faces).
53  * - hash mappings.
54  *
55  * each slot is identified by a slot code, as are each operator.
56  * operators, and their slots, are defined in bmesh_opdefines.c (with their
57  * execution functions prototyped in bmesh_operators_private.h), with all their
58  * operator code and slot codes defined in bmesh_operators.h.  see
59  * bmesh_opdefines.c and the BMOpDefine struct for how to define new operators.
60  *
61  * in general, operators are fed arrays of elements, created using either
62  * BM_HeaderFlag_To_Slot or BM_Flag_To_Slot (or through one of the format
63  * specifyers in BMO_op_callf or BMO_op_initf).  Note that multiple element
64  * types (e.g. faces and edges) can be fed to the same slot array.  Operators
65  * act on this data, and possibly spit out data into output slots.
66  *
67  * some notes:
68  * - operators should never read from header flags (e.g. element->head.flag). for
69  *   example, if you want an operator to only operate on selected faces, you
70  *   should use BM_HeaderFlag_To_Slot to put the selected elements into a slot.
71  * - when you read from an element slot array or mapping, you can either tool-flag
72  *   all the elements in it, or read them using an iterator APi (which is
73  *   semantically similar to the iterator api in bmesh_iterators.h).
74  */
75
76 struct GHashIterator;
77
78 /* slot type arrays are terminated by the last member
79  * having a slot type of 0.*/
80 #define BMO_OP_SLOT_SENTINEL    0
81 #define BMO_OP_SLOT_INT                 1
82 #define BMO_OP_SLOT_FLT                 2
83 #define BMO_OP_SLOT_PNT                 3
84 #define BMO_OP_SLOT_MAT                 4
85 #define BMO_OP_SLOT_VEC                 7
86
87 /* after BMO_OP_SLOT_VEC, everything is
88
89  * dynamically allocated arrays.  we
90  * leave a space in the identifiers
91  * for future growth.
92  */
93 //it's very important this remain a power of two
94 #define BMO_OP_SLOT_ELEMENT_BUF         8
95 #define BMO_OP_SLOT_MAPPING                     9
96 /* #define BMO_OP_SLOT_TOTAL_TYPES              10 */ /* not used yet */
97
98 /* please ignore all these structures, don't touch them in tool code, except
99  * for when your defining an operator with BMOpDefine.*/
100
101 typedef struct BMOpSlot{
102         int slottype;
103         int len;
104         int flag;
105         int index; /* index within slot array */
106         union {
107                 int i;
108                 float f;
109                 void *p;
110                 float vec[3];
111                 void *buf;
112                 GHash *ghash;
113         } data;
114 } BMOpSlot;
115
116 #define BMO_OP_MAX_SLOTS 16 /* way more than probably needed */
117
118 #ifdef slots
119 #undef slots
120 #endif
121
122 typedef struct BMOperator {
123         int type;
124         int slottype;
125         int needflag;
126         int flag;
127         struct BMOpSlot slots[BMO_OP_MAX_SLOTS];
128         void (*exec)(struct BMesh *bm, struct BMOperator *op);
129         MemArena *arena;
130 } BMOperator;
131
132 #define MAX_SLOTNAME    32
133
134 typedef struct BMOSlotType {
135         int type;
136         char name[MAX_SLOTNAME];
137 } BMOSlotType;
138
139 typedef struct BMOpDefine {
140         const char *name;
141         BMOSlotType slottypes[BMO_OP_MAX_SLOTS];
142         void (*exec)(BMesh *bm, BMOperator *op);
143         int flag;
144 } BMOpDefine;
145
146 /* BMOpDefine->flag */
147 #define BMO_OP_FLAG_UNTAN_MULTIRES              1 /*switch from multires tangent space to absolute coordinates*/
148
149 /* ensures consistent normals before operator execution,
150  * restoring the original ones windings/normals afterwards.
151  * keep in mind, this won't work if the input mesh isn't
152  * manifold.*/
153 #define BMO_OP_FLAG_RATIONALIZE_NORMALS 2
154
155 /*------------- Operator API --------------*/
156
157 /* data types that use pointers (arrays, etc) should never
158  * have it set directly.  and never use BMO_slot_ptr_set to
159  * pass in a list of edges or any arrays, really.*/
160
161 void BMO_op_init(struct BMesh *bm, struct BMOperator *op, const char *opname);
162
163 /* executes an operator, pushing and popping a new tool flag
164  * layer as appropriate.*/
165 void BMO_op_exec(struct BMesh *bm, struct BMOperator *op);
166
167 /* finishes an operator (though note the operator's tool flag is removed
168  * after it finishes executing in BMO_op_exec).*/
169 void BMO_op_finish(struct BMesh *bm, struct BMOperator *op);
170
171
172 /* tool flag API. never, ever ever should tool code put junk in
173  * header flags (element->head.flag), nor should they use
174  * element->head.eflag1/eflag2.  instead, use this api to set
175  * flags.
176  *
177  * if you need to store a value per element, use a
178  * ghash or a mapping slot to do it. */
179
180 /* flags 15 and 16 (1<<14 and 1<<15) are reserved for bmesh api use */
181 #define BMO_elem_flag_test(bm, element, oflag)    ((element)->oflags[bm->stackdepth-1].f &   (oflag))
182 #define BMO_elem_flag_enable(bm, element, oflag)  ((element)->oflags[bm->stackdepth-1].f |=  (oflag))
183 #define BMO_elem_flag_disable(bm, element, oflag) ((element)->oflags[bm->stackdepth-1].f &= ~(oflag))
184 #define BMO_elem_flag_toggle(bm, element, oflag)  ((element)->oflags[bm->stackdepth-1].f ^=  (oflag))
185
186 /* profiling showed a significant amount of time spent in BMO_elem_flag_test */
187 #if 0
188 void BMO_elem_flag_enable(struct BMesh *bm, void *element, const short oflag);
189 void BMO_elem_flag_disable(struct BMesh *bm, void *element, const short oflag);
190 int BMO_elem_flag_test(struct BMesh *bm, void *element, const short oflag);
191 #endif
192
193 /* count the number of elements with a specific flag.
194  * type can be a bitmask of BM_FACE, BM_EDGE, or BM_FACE. */
195 int BMO_mesh_flag_count(struct BMesh *bm, const short oflag, const char htype);
196
197 /*---------formatted operator initialization/execution-----------*/
198 /*
199  * this system is used to execute or initialize an operator,
200  * using a formatted-string system.
201  *
202  * for example, BMO_op_callf(bm, "del geom=%hf context=%d", BM_ELEM_SELECT, DEL_FACES);
203  * . . .will execute the delete operator, feeding in selected faces, deleting them.
204  *
205  * the basic format for the format string is:
206  *   [operatorname] [slotname]=%[code] [slotname]=%[code]
207  *
208  * as in printf, you pass in one additional argument to the function
209  * for every code.
210  *
211  * the formatting codes are:
212  *    %d - put int in slot
213  *    %f - put float in slot
214  *    %p - put pointer in slot
215  *    %h[f/e/v] - put elements with a header flag in slot.
216  *                 the letters after %h define which element types to use,
217  *             so e.g. %hf will do faces, %hfe will do faces and edges,
218  *             %hv will do verts, etc.  must pass in at least one
219  *             element type letter.
220  *    %f[f/e/v] - same as %h, except it deals with tool flags instead of
221  *                 header flags.
222  *    %a[f/e/v] - pass all elements (of types specified by f/e/v) to the
223  *                 slot.
224  *    %e        - pass in a single element.
225  *    %v - pointer to a float vector of length 3.
226  *    %m[3/4] - matrix, 3/4 refers to the matrix size, 3 or 4.  the
227  *              corrusponding argument must be a pointer to
228  *          a float matrix.
229  *    %s - copy a slot from another op, instead of mapping to one
230  *         argument, it maps to two, a pointer to an operator and
231  *     a slot name.
232  */
233 void BMO_push(BMesh *bm, BMOperator *op);
234 void BMO_pop(BMesh *bm);
235
236 /*executes an operator*/
237 int BMO_op_callf(BMesh *bm, const char *fmt, ...);
238
239 /* initializes, but doesn't execute an operator.  this is so you can
240  * gain access to the outputs of the operator.  note that you have
241  * to execute/finitsh (BMO_op_exec and BMO_op_finish) yourself. */
242 int BMO_op_initf(BMesh *bm, BMOperator *op, const char *fmt, ...);
243
244 /* va_list version, used to implement the above two functions,
245  * plus EDBM_CallOpf in bmeshutils.c. */
246 int BMO_op_vinitf(BMesh *bm, BMOperator *op, const char *fmt, va_list vlist);
247
248 /* test whether a named slot exists */
249 int BMO_slot_exists(struct BMOperator *op, const char *slotname);
250
251 /* get a pointer to a slot.  this may be removed layer on from the public API. */
252 BMOpSlot *BMO_slot_get(struct BMOperator *op, const char *slotname);
253
254 /* copies the data of a slot from one operator to another.  src and dst are the
255  * source/destination slot codes, respectively. */
256 void BMO_slot_copy(struct BMOperator *source_op, struct BMOperator *dest_op,
257                    const char *src, const char *dst);
258
259 /* remove tool flagged elements */
260 void BMO_remove_tagged_faces(struct BMesh *bm, const short oflag);
261 void BMO_remove_tagged_edges(struct BMesh *bm, const short oflag);
262 void BMO_remove_tagged_verts(struct BMesh *bm, const short oflag);
263
264 /* take care, uses operator flag DEL_WIREVERT */
265 void BMO_remove_tagged_context(BMesh *bm, const short oflag, const int type);
266
267 /* del "context" slot values, used for operator too */
268 enum {
269         DEL_VERTS = 1,
270         DEL_EDGES,
271         DEL_ONLYFACES,
272         DEL_EDGESFACES,
273         DEL_FACES,
274         DEL_ALL ,
275         DEL_ONLYTAGGED
276 };
277
278 void BMO_op_flag_enable(struct BMesh *bm, struct BMOperator *op, const int op_flag);
279 void BMO_op_flag_disable(struct BMesh *bm, struct BMOperator *op, const int op_flag);
280
281 void  BMO_slot_float_set(struct BMOperator *op, const char *slotname, const float f);
282 float BMO_slot_float_get(BMOperator *op, const char *slotname);
283 void  BMO_slot_int_set(struct BMOperator *op, const char *slotname, const int i);
284 int   BMO_slot_int_get(BMOperator *op, const char *slotname);
285
286 /* don't pass in arrays that are supposed to map to elements this way.
287  *
288  * so, e.g. passing in list of floats per element in another slot is bad.
289  * passing in, e.g. pointer to an editmesh for the conversion operator is fine
290  * though. */
291 void  BMO_slot_ptr_set(struct BMOperator *op, const char *slotname, void *p);
292 void *BMO_slot_ptr_get(BMOperator *op, const char *slotname);
293 void  BMO_slot_vec_set(struct BMOperator *op, const char *slotname, const float vec[3]);
294 void  BMO_slot_vec_get(BMOperator *op, const char *slotname, float r_vec[3]);
295
296 /* only supports square mats */
297 /* size must be 3 or 4; this api is meant only for transformation matrices.
298  * note that internally the matrix is stored in 4x4 form, and it's safe to
299  * call whichever BMO_Get_Mat* function you want. */
300 void BMO_slot_mat_set(struct BMOperator *op, const char *slotname, const float *mat, int size);
301 void BMO_slot_mat4_get(struct BMOperator *op, const char *slotname, float r_mat[4][4]);
302 void BMO_slot_mat3_set(struct BMOperator *op, const char *slotname, float r_mat[3][3]);
303
304 void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *op, const char htype, const short oflag);
305
306 /* puts every element of type type (which is a bitmask) with tool flag flag,
307  * into a slot. */
308 void BMO_slot_from_flag(struct BMesh *bm, struct BMOperator *op, const char *slotname,
309                         const short oflag, const char htype);
310
311 /* tool-flags all elements inside an element slot array with flag flag. */
312 void BMO_slot_buffer_flag_enable(struct BMesh *bm, struct BMOperator *op, const char *slotname,
313                           const short oflag, const char htype);
314 /* clears tool-flag flag from all elements inside a slot array. */
315 void BMO_slot_buffer_flag_disable(struct BMesh *bm, struct BMOperator *op, const char *slotname,
316                                 const short oflag, const char htype);
317
318 /* tool-flags all elements inside an element slot array with flag flag. */
319 void BMO_slot_buffer_hflag_enable(struct BMesh *bm, struct BMOperator *op, const char *slotname,
320                                   const char hflag, const char htype);
321 /* clears tool-flag flag from all elements inside a slot array. */
322 void BMO_slot_buffer_hflag_disable(struct BMesh *bm, struct BMOperator *op, const char *slotname,
323                                    const char hflag, const char htype);
324
325 /* puts every element of type type (which is a bitmask) with header flag
326  * flag, into a slot.  note: ignores hidden elements (e.g. elements with
327  * header flag BM_ELEM_HIDDEN set).*/
328 void BMO_slot_from_hflag(struct BMesh *bm, struct BMOperator *op, const char *slotname,
329                          const char hflag, const char htype);
330
331 /* counts number of elements inside a slot array. */
332 int BMO_slot_buf_count(struct BMesh *bm, struct BMOperator *op, const char *slotname);
333 int BMO_slot_map_count(struct BMesh *bm, struct BMOperator *op, const char *slotname);
334
335 /* Counts the number of edges with tool flag toolflag around
336  */
337 int BMO_vert_edge_flags_count(BMesh *bm, BMVert *v, const short oflag);
338
339 /* inserts a key/value mapping into a mapping slot.  note that it copies the
340  * value, it doesn't store a reference to it. */
341
342 #if 0
343
344 BM_INLINE void BMO_slot_map_insert(BMesh *bm, BMOperator *op, const char *slotname,
345                                    void *element, void *data, int len);
346
347 /* inserts a key/float mapping pair into a mapping slot. */
348 BM_INLINE void BMO_slot_map_float_insert(BMesh *bm, BMOperator *op, const char *slotname,
349                                          void *element, float val);
350
351 /* returns 1 if the specified pointer is in the map. */
352 BM_INLINE int BMO_slot_map_contains(BMesh *bm, BMOperator *op, const char *slotname, void *element);
353
354 /* returns a point to the value of a specific key. */
355 BM_INLINE void *BMO_slot_map_data_get(BMesh *bm, BMOperator *op, const char *slotname, void *element);
356
357 /* returns the float part of a key/float pair. */
358 BM_INLINE float BMO_slot_map_float_get(BMesh *bm, BMOperator *op, const char *slotname, void *element);
359
360 #endif
361
362 /* flags all elements in a mapping.  note that the mapping must only have
363  * bmesh elements in it.*/
364 void BMO_slot_map_to_flag(struct BMesh *bm, struct BMOperator *op,
365                           const char *slotname, const short oflag);
366
367 /* pointer versoins of BMO_slot_map_float_get and BMO_slot_map_float_insert.
368  *
369  * do NOT use these for non-operator-api-allocated memory! instead
370  * use BMO_slot_map_data_get and BMO_slot_map_insert, which copies the data. */
371
372 #if 0
373 BM_INLINE void BMO_slot_map_ptr_insert(BMesh *bm, BMOperator *op, const char *slotname, void *key, void *val);
374 BM_INLINE void *BMO_slot_map_ptr_get(BMesh *bm, BMOperator *op, const char *slotname, void *key);
375 #endif
376
377 /* this part of the API is used to iterate over element buffer or
378  * mapping slots.
379  *
380  * for example, iterating over the faces in a slot is:
381  *
382  *    BMOIter oiter;
383  *    BMFace *f;
384  *
385  *    f = BMO_iter_new(&oiter, bm, some_operator, "slotname", BM_FACE);
386  *    for (; f; f=BMO_iter_step(&oiter)) {
387  *        /do something with the face
388  *    }
389  *
390  * another example, iterating over a mapping:
391  *    BMOIter oiter;
392  *    void *key;
393  *    void *val;
394  *
395  *    key = BMO_iter_new(&oiter, bm, some_operator, "slotname", 0);
396  *    for (; key; key=BMO_iter_step(&oiter)) {
397  *        val = BMO_iter_map_value(&oiter);
398  *        //do something with the key/val pair
399  *        //note that val is a pointer to the val data,
400  *        //whether it's a float, pointer, whatever.
401  *        //
402  *        // so to get a pointer, for example, use:
403  *        //  *((void**)BMO_iter_map_value(&oiter));
404  *        //or something like that.
405  *    }
406  */
407
408 /* contents of this structure are private,
409  * don't directly access. */
410 typedef struct BMOIter {
411         BMOpSlot *slot;
412         int cur; //for arrays
413         struct GHashIterator giter;
414         void *val;
415         char restrictmask; /* bitwise '&' with BMHeader.htype */
416 } BMOIter;
417
418 void *BMO_slot_elem_first(BMOperator *op, const char *slotname);
419
420 /* restrictmask restricts the iteration to certain element types
421  * (e.g. combination of BM_VERT, BM_EDGE, BM_FACE), if iterating
422  * over an element buffer (not a mapping).*/
423 void *BMO_iter_new(BMOIter *iter, BMesh *bm, BMOperator *op,
424                    const char *slotname, const char restrictmask);
425 void *BMO_iter_step(BMOIter *iter);
426
427 /* returns a pointer to the key value when iterating over mappings.
428  * remember for pointer maps this will be a pointer to a pointer.*/
429 void *BMO_iter_map_value(BMOIter *iter);
430
431 /* use this for pointer mappings */
432 void *BMO_iter_map_value_p(BMOIter *iter);
433
434 /* use this for float mappings */
435 float BMO_iter_map_value_f(BMOIter *iter);
436
437 #define BMO_ITER(ele, iter, bm, op, slotname, restrict)   \
438         ele = BMO_iter_new(iter, bm, op, slotname, restrict); \
439         for ( ; ele; ele=BMO_iter_step(iter))
440
441 /******************* Inlined Functions********************/
442 typedef void (*opexec)(struct BMesh *bm, struct BMOperator *op);
443
444 /* mappings map elements to data, which
445  * follows the mapping struct in memory. */
446 typedef struct BMOElemMapping {
447         BMHeader *element;
448         int len;
449 } BMOElemMapping;
450
451 extern const int BMO_OPSLOT_TYPEINFO[];
452
453 BM_INLINE void BMO_slot_map_insert(BMesh *UNUSED(bm), BMOperator *op, const char *slotname,
454                                    void *element, void *data, int len)
455 {
456         BMOElemMapping *mapping;
457         BMOpSlot *slot = BMO_slot_get(op, slotname);
458
459         /*sanity check*/
460         if (slot->slottype != BMO_OP_SLOT_MAPPING) {
461                 return;
462         }
463
464         mapping = (BMOElemMapping *) BLI_memarena_alloc(op->arena, sizeof(*mapping) + len);
465
466         mapping->element = (BMHeader*) element;
467         mapping->len = len;
468         memcpy(mapping + 1, data, len);
469
470         if (!slot->data.ghash) {
471                 slot->data.ghash = BLI_ghash_new(BLI_ghashutil_ptrhash,
472                                                  BLI_ghashutil_ptrcmp, "bmesh op");
473         }
474
475         BLI_ghash_insert(slot->data.ghash, element, mapping);
476 }
477
478 BM_INLINE void BMO_slot_map_int_insert(BMesh *bm, BMOperator *op, const char *slotname,
479                                        void *element, int val)
480 {
481         BMO_slot_map_insert(bm, op, slotname, element, &val, sizeof(int));
482 }
483
484 BM_INLINE void BMO_slot_map_float_insert(BMesh *bm, BMOperator *op, const char *slotname,
485                                          void *element, float val)
486 {
487         BMO_slot_map_insert(bm, op, slotname, element, &val, sizeof(float));
488 }
489
490 BM_INLINE void BMO_slot_map_ptr_insert(BMesh *bm, BMOperator *op, const char *slotname,
491                                        void *element, void *val)
492 {
493         BMO_slot_map_insert(bm, op, slotname, element, &val, sizeof(void*));
494 }
495
496 BM_INLINE int BMO_slot_map_contains(BMesh *UNUSED(bm), BMOperator *op, const char *slotname, void *element)
497 {
498         BMOpSlot *slot = BMO_slot_get(op, slotname);
499
500         /*sanity check*/
501         if (slot->slottype != BMO_OP_SLOT_MAPPING) return 0;
502         if (!slot->data.ghash) return 0;
503
504         return BLI_ghash_haskey(slot->data.ghash, element);
505 }
506
507 BM_INLINE void *BMO_slot_map_data_get(BMesh *UNUSED(bm), BMOperator *op, const char *slotname,
508                                       void *element)
509 {
510         BMOElemMapping *mapping;
511         BMOpSlot *slot = BMO_slot_get(op, slotname);
512
513         /*sanity check*/
514         if (slot->slottype != BMO_OP_SLOT_MAPPING) return NULL;
515         if (!slot->data.ghash) return NULL;
516
517         mapping = (BMOElemMapping *)BLI_ghash_lookup(slot->data.ghash, element);
518
519         if (!mapping) return NULL;
520
521         return mapping + 1;
522 }
523
524 BM_INLINE float BMO_slot_map_float_get(BMesh *bm, BMOperator *op, const char *slotname,
525                                        void *element)
526 {
527         float *val = (float*) BMO_slot_map_data_get(bm, op, slotname, element);
528         if (val) return *val;
529
530         return 0.0f;
531 }
532
533 BM_INLINE int BMO_slot_map_int_get(BMesh *bm, BMOperator *op, const char *slotname,
534                                    void *element)
535 {
536         int *val = (int*) BMO_slot_map_data_get(bm, op, slotname, element);
537         if (val) return *val;
538
539         return 0;
540 }
541
542 BM_INLINE void *BMO_slot_map_ptr_get(BMesh *bm, BMOperator *op, const char *slotname,
543                                      void *element)
544 {
545         void **val = (void**) BMO_slot_map_data_get(bm, op, slotname, element);
546         if (val) return *val;
547
548         return NULL;
549 }
550
551 #ifdef __cplusplus
552 }
553 #endif
554
555 #endif /* __BMESH_OPERATOR_API_H__ */