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