Code Cleanup: remove unused operator flags
[blender-staging.git] / source / blender / bmesh / intern / bmesh_operators.c
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, Geoffrey Bantle, Campbell Barton
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/bmesh/intern/bmesh_operators.c
24  *  \ingroup bmesh
25  *
26  * BMesh operator access.
27  */
28
29 #include "MEM_guardedalloc.h"
30
31 #include "BLI_utildefines.h"
32 #include "BLI_string.h"
33 #include "BLI_math.h"
34 #include "BLI_memarena.h"
35 #include "BLI_mempool.h"
36 #include "BLI_listbase.h"
37 #include "BLI_array.h"
38
39 #include "bmesh.h"
40 #include "bmesh_private.h"
41 #include "stdarg.h"
42
43 #include <string.h>
44
45 /* forward declarations */
46 static void alloc_flag_layer(BMesh *bm);
47 static void free_flag_layer(BMesh *bm);
48 static void clear_flag_layer(BMesh *bm);
49 static int bmesh_name_to_slotcode(BMOpDefine *def, const char *name);
50 static int bmesh_name_to_slotcode_check(BMOpDefine *def, const char *name);
51 static int bmesh_opname_to_opcode(const char *opname);
52
53 static const char *bmop_error_messages[] = {
54         NULL,
55         "Self intersection error",
56         "Could not dissolve vert",
57         "Could not connect vertices",
58         "Could not traverse mesh",
59         "Could not dissolve faces",
60         "Could not dissolve vertices",
61         "Tesselation error",
62         "Can not deal with non-manifold geometry",
63         "Invalid selection",
64         "Internal mesh error",
65 };
66
67
68 /* operator slot type information - size of one element of the type given. */
69 const int BMOP_OPSLOT_TYPEINFO[] = {
70         0,
71         sizeof(int),
72         sizeof(float),
73         sizeof(void *),
74         0, /* unused */
75         0, /* unused */
76         0, /* unused */
77         sizeof(void *), /* pointer buffer */
78         sizeof(BMOElemMapping)
79 };
80
81 /* Dummy slot so there is something to return when slot name lookup fails */
82 static BMOpSlot BMOpEmptySlot = { 0 };
83
84 void BMO_Set_OpFlag(BMesh *UNUSED(bm), BMOperator *op, int flag)
85 {
86         op->flag |= flag;
87 }
88
89 void BMO_Clear_OpFlag(BMesh *UNUSED(bm), BMOperator *op, int flag)
90 {
91         op->flag &= ~flag;
92 }
93
94 /*
95  * BMESH OPSTACK PUSH
96  *
97  * Pushes the opstack down one level
98  * and allocates a new flag layer if
99  * appropriate.
100  */
101 void BMO_push(BMesh *bm, BMOperator *UNUSED(op))
102 {
103         bm->stackdepth++;
104
105         /* add flag layer, if appropriate */
106         if (bm->stackdepth > 1)
107                 alloc_flag_layer(bm);
108         else
109                 clear_flag_layer(bm);
110 }
111
112 /*
113  * BMESH OPSTACK POP
114  *
115  * Pops the opstack one level
116  * and frees a flag layer if appropriate
117  * BMESH_TODO: investigate NOT freeing flag
118  * layers.
119  */
120 void BMO_pop(BMesh *bm)
121 {
122         if (bm->stackdepth > 1)
123                 free_flag_layer(bm);
124
125         bm->stackdepth--;
126 }
127
128 /*
129  * BMESH OPSTACK INIT OP
130  *
131  * Initializes an operator structure
132  * to a certain type
133  */
134 void BMO_Init_Op(BMesh *bm, BMOperator *op, const char *opname)
135 {
136         int i, opcode = bmesh_opname_to_opcode(opname);
137
138 #ifdef DEBUG
139         BM_ELEM_INDEX_VALIDATE(bm, "pre bmo", opname);
140 #else
141         (void)bm;
142 #endif
143
144         if (opcode == -1) {
145                 opcode = 0; /* error!, already printed, have a better way to handle this? */
146         }
147
148         memset(op, 0, sizeof(BMOperator));
149         op->type = opcode;
150         op->flag = opdefines[opcode]->flag;
151         
152         /* initialize the operator slot types */
153         for (i = 0; opdefines[opcode]->slottypes[i].type; i++) {
154                 op->slots[i].slottype = opdefines[opcode]->slottypes[i].type;
155                 op->slots[i].index = i;
156         }
157
158         /* callback */
159         op->exec = opdefines[opcode]->exec;
160
161         /* memarena, used for operator's slot buffers */
162         op->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "bmesh operator");
163         BLI_memarena_use_calloc (op->arena);
164 }
165
166 /*
167  * BMESH OPSTACK EXEC OP
168  *
169  * Executes a passed in operator. This handles
170  * the allocation and freeing of temporary flag
171  * layers and starting/stopping the modelling
172  * loop. Can be called from other operators
173  * exec callbacks as well.
174  */
175 void BMO_Exec_Op(BMesh *bm, BMOperator *op)
176 {
177         
178         BMO_push(bm, op);
179
180         if (bm->stackdepth == 2)
181                 bmesh_begin_edit(bm, op->flag);
182         op->exec(bm, op);
183         
184         if (bm->stackdepth == 2)
185                 bmesh_end_edit(bm, op->flag);
186         
187         BMO_pop(bm);
188 }
189
190 /*
191  * BMESH OPSTACK FINISH OP
192  *
193  * Does housekeeping chores related to finishing
194  * up an operator.
195  */
196 void BMO_Finish_Op(BMesh *bm, BMOperator *op)
197 {
198         BMOpSlot *slot;
199         int i;
200
201         for (i = 0; opdefines[op->type]->slottypes[i].type; i++) {
202                 slot = &op->slots[i];
203                 if (slot->slottype == BMOP_OPSLOT_MAPPING) {
204                         if (slot->data.ghash)
205                                 BLI_ghash_free(slot->data.ghash, NULL, NULL);
206                 }
207         }
208
209         BLI_memarena_free(op->arena);
210
211 #ifdef DEBUG
212         BM_ELEM_INDEX_VALIDATE(bm, "post bmo", opdefines[op->type]->name);
213 #else
214         (void)bm;
215 #endif
216 }
217
218 /*
219  * BMESH OPSTACK HAS SLOT
220  *
221  * Returns 1 if the named slot exists on the given operator,
222  * otherwise returns 0.
223  */
224 int BMO_HasSlot(BMOperator *op, const char *slotname)
225 {
226         int slotcode = bmesh_name_to_slotcode(opdefines[op->type], slotname);
227         return (slotcode >= 0);
228 }
229
230 /*
231  * BMESH OPSTACK GET SLOT
232  *
233  * Returns a pointer to the slot of
234  * type 'slotcode'
235  */
236 BMOpSlot *BMO_GetSlot(BMOperator *op, const char *slotname)
237 {
238         int slotcode = bmesh_name_to_slotcode_check(opdefines[op->type], slotname);
239
240         if (slotcode < 0) {
241                 return &BMOpEmptySlot;
242         }
243
244         return &(op->slots[slotcode]);
245 }
246
247 /*
248  * BMESH OPSTACK COPY SLOT
249  *
250  * Copies data from one slot to another
251  */
252 void BMO_CopySlot(BMOperator *source_op, BMOperator *dest_op, const char *src, const char *dst)
253 {
254         BMOpSlot *source_slot = BMO_GetSlot(source_op, src);
255         BMOpSlot *dest_slot = BMO_GetSlot(dest_op, dst);
256
257         if (source_slot == dest_slot)
258                 return;
259
260         if (source_slot->slottype != dest_slot->slottype)
261                 return;
262         
263         if (dest_slot->slottype > BMOP_OPSLOT_VEC) {
264                 if (dest_slot->slottype != BMOP_OPSLOT_MAPPING) {
265                         /* do buffer copy */
266                         dest_slot->data.buf = NULL;
267                         dest_slot->len = source_slot->len;
268                         if (dest_slot->len) {
269                                 const int slot_alloc_size = BMOP_OPSLOT_TYPEINFO[dest_slot->slottype] * dest_slot->len;
270                                 dest_slot->data.buf = BLI_memarena_alloc(dest_op->arena, slot_alloc_size);
271                                 memcpy(dest_slot->data.buf, source_slot->data.buf, slot_alloc_size);
272                         }
273                 }
274                 else {
275                         GHashIterator it;
276                         BMOElemMapping *srcmap, *dstmap;
277
278                         /* sanity check */
279                         if (!source_slot->data.ghash) return;
280                         
281                         if (!dest_slot->data.ghash) {
282                                 dest_slot->data.ghash = BLI_ghash_new(BLI_ghashutil_ptrhash,
283                                                                       BLI_ghashutil_ptrcmp, "bmesh operator 2");
284                         }
285
286                         BLI_ghashIterator_init(&it, source_slot->data.ghash);
287                         for ( ; (srcmap = BLI_ghashIterator_getValue(&it));
288                               BLI_ghashIterator_step(&it))
289                         {
290                                 dstmap = BLI_memarena_alloc(dest_op->arena, sizeof(*dstmap) + srcmap->len);
291
292                                 dstmap->element = srcmap->element;
293                                 dstmap->len = srcmap->len;
294                                 memcpy(dstmap + 1, srcmap + 1, srcmap->len);
295
296                                 BLI_ghash_insert(dest_slot->data.ghash, dstmap->element, dstmap);
297                         }
298                 }
299         }
300         else {
301                 dest_slot->data = source_slot->data;
302         }
303 }
304
305 /*
306  * BMESH OPSTACK SET XXX
307  *
308  * Sets the value of a slot depending on it's type
309  *
310  */
311
312 void BMO_Set_Float(BMOperator *op, const char *slotname, float f)
313 {
314         BMOpSlot *slot = BMO_GetSlot(op, slotname);
315         if (!(slot->slottype == BMOP_OPSLOT_FLT))
316                 return;
317
318         slot->data.f = f;
319 }
320
321 void BMO_Set_Int(BMOperator *op, const char *slotname, int i)
322 {
323         BMOpSlot *slot = BMO_GetSlot(op, slotname);
324         if (!(slot->slottype == BMOP_OPSLOT_INT))
325                 return;
326
327         slot->data.i = i;
328 }
329
330 /* only supports square mats */
331 void BMO_Set_Mat(struct BMOperator *op, const char *slotname, float *mat, int size)
332 {
333         BMOpSlot *slot = BMO_GetSlot(op, slotname);
334         if (!(slot->slottype == BMOP_OPSLOT_MAT))
335                 return;
336
337         slot->len = 4;
338         slot->data.p = BLI_memarena_alloc(op->arena, sizeof(float) * 4 * 4);
339         
340         if (size == 4) {
341                 memcpy(slot->data.p, mat, sizeof(float) * 4 * 4);
342         }
343         else if (size == 3) {
344                 copy_m4_m3(slot->data.p, (float (*)[3])mat);
345         }
346         else {
347                 fprintf(stderr, "%s: invalid size argument %d (bmesh internal error)\n", __func__, size);
348
349                 memset(slot->data.p, 0, sizeof(float) * 4 * 4);
350                 return;
351         }
352 }
353
354 void BMO_Get_Mat4(struct BMOperator *op, const char *slotname, float mat[4][4])
355 {
356         BMOpSlot *slot = BMO_GetSlot(op, slotname);
357         if (!(slot->slottype == BMOP_OPSLOT_MAT))
358                 return;
359
360         memcpy(mat, slot->data.p, sizeof(float) * 4 * 4);
361 }
362
363 void BMO_Get_Mat3(struct BMOperator *op, const char *slotname, float mat[3][3])
364 {
365         BMOpSlot *slot = BMO_GetSlot(op, slotname);
366         if (!(slot->slottype == BMOP_OPSLOT_MAT))
367                 return;
368
369         copy_m3_m4(mat, slot->data.p);
370 }
371
372 void BMO_Set_Pnt(BMOperator *op, const char *slotname, void *p)
373 {
374         BMOpSlot *slot = BMO_GetSlot(op, slotname);
375         if (!(slot->slottype == BMOP_OPSLOT_PNT))
376                 return;
377
378         slot->data.p = p;
379 }
380
381 void BMO_Set_Vec(BMOperator *op, const char *slotname, const float vec[3])
382 {
383         BMOpSlot *slot = BMO_GetSlot(op, slotname);
384         if (!(slot->slottype == BMOP_OPSLOT_VEC))
385                 return;
386
387         copy_v3_v3(slot->data.vec, vec);
388 }
389
390
391 float BMO_Get_Float(BMOperator *op, const char *slotname)
392 {
393         BMOpSlot *slot = BMO_GetSlot(op, slotname);
394         if (!(slot->slottype == BMOP_OPSLOT_FLT))
395                 return 0.0f;
396
397         return slot->data.f;
398 }
399
400 int BMO_Get_Int(BMOperator *op, const char *slotname)
401 {
402         BMOpSlot *slot = BMO_GetSlot(op, slotname);
403         if (!(slot->slottype == BMOP_OPSLOT_INT))
404                 return 0;
405
406         return slot->data.i;
407 }
408
409
410 void *BMO_Get_Pnt(BMOperator *op, const char *slotname)
411 {
412         BMOpSlot *slot = BMO_GetSlot(op, slotname);
413         if (!(slot->slottype == BMOP_OPSLOT_PNT))
414                 return NULL;
415
416         return slot->data.p;
417 }
418
419 void BMO_Get_Vec(BMOperator *op, const char *slotname, float r_vec[3])
420 {
421         BMOpSlot *slot = BMO_GetSlot(op, slotname);
422         if (!(slot->slottype == BMOP_OPSLOT_VEC))
423                 return;
424
425         copy_v3_v3(r_vec, slot->data.vec);
426 }
427
428 /*
429  * BMO_COUNTFLAG
430  *
431  * Counts the number of elements of a certain type that
432  * have a specific flag set.
433  *
434  */
435
436 int BMO_CountFlag(BMesh *bm, int flag, const char htype)
437 {
438         BMIter elements;
439         BMHeader *e;
440         int count = 0;
441
442         if (htype & BM_VERT) {
443                 for (e = BMIter_New(&elements, bm, BM_VERTS_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
444                         if (BMO_TestFlag(bm, e, flag))
445                                 count++;
446                 }
447         }
448         if (htype & BM_EDGE) {
449                 for (e = BMIter_New(&elements, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
450                         if (BMO_TestFlag(bm, e, flag))
451                                 count++;
452                 }
453         }
454         if (htype & BM_FACE) {
455                 for (e = BMIter_New(&elements, bm, BM_FACES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
456                         if (BMO_TestFlag(bm, e, flag))
457                                 count++;
458                 }
459         }
460
461         return count;
462 }
463
464 void BMO_Clear_Flag_All(BMesh *bm, BMOperator *UNUSED(op), const char htype, int flag)
465 {
466         BMIter iter;
467         BMHeader *ele;
468         int types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
469         int flags[3] = {BM_VERT, BM_EDGE, BM_FACE};
470         int i;
471
472         for (i = 0; i < 3; i++) {
473                 if (htype & flags[i]) {
474                         BM_ITER(ele, &iter, bm, types[i], NULL) {
475                                 BMO_ClearFlag(bm, ele, flag);
476                         }
477                 }
478         }
479 }
480
481 int BMO_CountSlotBuf(struct BMesh *UNUSED(bm), struct BMOperator *op, const char *slotname)
482 {
483         BMOpSlot *slot = BMO_GetSlot(op, slotname);
484         
485         /* check if its actually a buffer */
486         if (!(slot->slottype > BMOP_OPSLOT_VEC))
487                 return 0;
488
489         return slot->len;
490 }
491
492 int BMO_CountSlotMap(BMesh *UNUSED(bm), BMOperator *op, const char *slotname)
493 {
494         BMOpSlot *slot = BMO_GetSlot(op, slotname);
495         
496         /* check if its actually a buffer */
497         if (!(slot->slottype == BMOP_OPSLOT_MAPPING))
498                 return 0;
499
500         return slot->data.ghash ? BLI_ghash_size(slot->data.ghash) : 0;
501 }
502
503 #if 0
504 void *BMO_Grow_Array(BMesh *bm, BMOperator *op, int slotcode, int totadd)
505 {
506         BMOpSlot *slot = &op->slots[slotcode];
507         void *tmp;
508         
509         /* check if its actually a buffer */
510         if (!(slot->slottype > BMOP_OPSLOT_VEC))
511                 return NULL;
512
513         if (slot->flag & BMOS_DYNAMIC_ARRAY) {
514                 if (slot->len >= slot->size) {
515                         slot->size = (slot->size + 1 + totadd) * 2;
516
517                         tmp = slot->data.buf;
518                         slot->data.buf = MEM_callocN(BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode].type] * slot->size, "opslot dynamic array");
519                         memcpy(slot->data.buf, tmp, BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode].type] * slot->size);
520                         MEM_freeN(tmp);
521                 }
522
523                 slot->len += totadd;
524         }
525         else {
526                 slot->flag |= BMOS_DYNAMIC_ARRAY;
527                 slot->len += totadd;
528                 slot->size = slot->len + 2;
529                 tmp = slot->data.buf;
530                 slot->data.buf = MEM_callocN(BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode].type] * slot->len, "opslot dynamic array");
531                 memcpy(slot->data.buf, tmp, BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode].type] * slot->len);
532         }
533
534         return slot->data.buf;
535 }
536 #endif
537
538 void BMO_Mapping_To_Flag(struct BMesh *bm, struct BMOperator *op,
539                          const char *slotname, int flag)
540 {
541         GHashIterator it;
542         BMOpSlot *slot = BMO_GetSlot(op, slotname);
543         BMHeader *ele;
544
545         /* sanity check */
546         if (slot->slottype != BMOP_OPSLOT_MAPPING) return;
547         if (!slot->data.ghash) return;
548
549         BLI_ghashIterator_init(&it, slot->data.ghash);
550         for ( ; (ele = BLI_ghashIterator_getKey(&it)); BLI_ghashIterator_step(&it)) {
551                 BMO_SetFlag(bm, ele, flag);
552         }
553 }
554
555 static void *alloc_slot_buffer(BMOperator *op, const char *slotname, int len)
556 {
557         BMOpSlot *slot = BMO_GetSlot(op, slotname);
558
559         /* check if its actually a buffer */
560         if (!(slot->slottype > BMOP_OPSLOT_VEC))
561                 return NULL;
562         
563         slot->len = len;
564         if (len)
565                 slot->data.buf = BLI_memarena_alloc(op->arena, BMOP_OPSLOT_TYPEINFO[slot->slottype] * len);
566         return slot->data.buf;
567 }
568
569 /*
570  * BMO_ALL_TO_SLOT
571  *
572  * Copies all elements of a certain type into an operator slot.
573  *
574  */
575
576 static void BMO_All_To_Slot(BMesh *bm, BMOperator *op, const char *slotname, const char htype)
577 {
578         BMIter elements;
579         BMHeader *e;
580         BMOpSlot *output = BMO_GetSlot(op, slotname);
581         int totelement = 0, i = 0;
582         
583         if (htype & BM_VERT) totelement += bm->totvert;
584         if (htype & BM_EDGE) totelement += bm->totedge;
585         if (htype & BM_FACE) totelement += bm->totface;
586
587         if (totelement) {
588                 alloc_slot_buffer(op, slotname, totelement);
589
590                 if (htype & BM_VERT) {
591                         for (e = BMIter_New(&elements, bm, BM_VERTS_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
592                                 ((BMHeader **)output->data.p)[i] = e;
593                                 i++;
594                         }
595                 }
596
597                 if (htype & BM_EDGE) {
598                         for (e = BMIter_New(&elements, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
599                                 ((BMHeader **)output->data.p)[i] = e;
600                                 i++;
601                         }
602                 }
603
604                 if (htype & BM_FACE) {
605                         for (e = BMIter_New(&elements, bm, BM_FACES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
606                                 ((BMHeader **)output->data.p)[i] = e;
607                                 i++;
608                         }
609                 }
610         }
611 }
612
613 /*
614  * BMO_HEADERFLAG_TO_SLOT
615  *
616  * Copies elements of a certain type, which have a certain header flag set
617  * into a slot for an operator.
618  */
619
620 void BMO_HeaderFlag_To_Slot(BMesh *bm, BMOperator *op, const char *slotname,
621                             const char hflag, const char htype)
622 {
623         BMIter elements;
624         BMHeader *e;
625         BMOpSlot *output = BMO_GetSlot(op, slotname);
626         int totelement = 0, i = 0;
627         
628         totelement = BM_CountFlag(bm, htype, hflag, 1);
629
630         if (totelement) {
631                 alloc_slot_buffer(op, slotname, totelement);
632
633                 if (htype & BM_VERT) {
634                         for (e = BMIter_New(&elements, bm, BM_VERTS_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
635                                 if (!BM_TestHFlag(e, BM_HIDDEN) && BM_TestHFlag(e, hflag)) {
636                                         ((BMHeader **)output->data.p)[i] = e;
637                                         i++;
638                                 }
639                         }
640                 }
641
642                 if (htype & BM_EDGE) {
643                         for (e = BMIter_New(&elements, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
644                                 if (!BM_TestHFlag(e, BM_HIDDEN) && BM_TestHFlag(e, hflag)) {
645                                         ((BMHeader **)output->data.p)[i] = e;
646                                         i++;
647                                 }
648                         }
649                 }
650
651                 if (htype & BM_FACE) {
652                         for (e = BMIter_New(&elements, bm, BM_FACES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
653                                 if (!BM_TestHFlag(e, BM_HIDDEN) && BM_TestHFlag(e, hflag)) {
654                                         ((BMHeader **)output->data.p)[i] = e;
655                                         i++;
656                                 }
657                         }
658                 }
659         }
660         else {
661                 output->len = 0;
662         }
663 }
664
665 /*
666  *
667  * BMO_FLAG_TO_SLOT
668  *
669  * Copies elements of a certain type, which have a certain flag set
670  * into an output slot for an operator.
671  */
672 void BMO_Flag_To_Slot(BMesh *bm, BMOperator *op, const char *slotname,
673                       const int flag, const char htype)
674 {
675         BMIter elements;
676         BMHeader *e;
677         BMOpSlot *output = BMO_GetSlot(op, slotname);
678         int totelement = BMO_CountFlag(bm, flag, htype), i = 0;
679
680         if (totelement) {
681                 alloc_slot_buffer(op, slotname, totelement);
682
683                 if (htype & BM_VERT) {
684                         for (e = BMIter_New(&elements, bm, BM_VERTS_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
685                                 if (BMO_TestFlag(bm, e, flag)) {
686                                         ((BMHeader **)output->data.p)[i] = e;
687                                         i++;
688                                 }
689                         }
690                 }
691
692                 if (htype & BM_EDGE) {
693                         for (e = BMIter_New(&elements, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
694                                 if (BMO_TestFlag(bm, e, flag)) {
695                                         ((BMHeader **)output->data.p)[i] = e;
696                                         i++;
697                                 }
698                         }
699                 }
700
701                 if (htype & BM_FACE) {
702                         for (e = BMIter_New(&elements, bm, BM_FACES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
703                                 if (BMO_TestFlag(bm, e, flag)) {
704                                         ((BMHeader **)output->data.p)[i] = e;
705                                         i++;
706                                 }
707                         }
708                 }
709         }
710         else {
711                 output->len = 0;
712         }
713 }
714
715 /*
716  *
717  * BMO_FLAG_BUFFER
718  *
719  * Header Flags elements in a slots buffer, automatically
720  * using the selection API where appropriate.
721  */
722 void BMO_HeaderFlag_Buffer(BMesh *bm, BMOperator *op, const char *slotname,
723                            const char hflag, const char htype)
724 {
725         BMOpSlot *slot = BMO_GetSlot(op, slotname);
726         BMHeader **data =  slot->data.p;
727         int i;
728         
729         for (i = 0; i < slot->len; i++) {
730                 if (!(htype & data[i]->htype))
731                         continue;
732
733                 if (hflag & BM_SELECT) {
734                         BM_Select(bm, data[i], TRUE);
735                 }
736                 BM_SetHFlag(data[i], hflag);
737         }
738 }
739
740 /*
741  *
742  * BMO_FLAG_BUFFER
743  *
744  * Removes flags from elements in a slots buffer, automatically
745  * using the selection API where appropriate.
746  */
747 void BMO_UnHeaderFlag_Buffer(BMesh *bm, BMOperator *op, const char *slotname,
748                              const char hflag, const char htype)
749 {
750         BMOpSlot *slot = BMO_GetSlot(op, slotname);
751         BMHeader **data =  slot->data.p;
752         int i;
753         
754         for (i = 0; i < slot->len; i++) {
755                 if (!(htype & data[i]->htype))
756                         continue;
757
758                 if (hflag & BM_SELECT) {
759                         BM_Select(bm, data[i], FALSE);
760                 }
761
762                 BM_ClearHFlag(data[i], hflag);
763         }
764 }
765 int BMO_Vert_CountEdgeFlags(BMesh *bm, BMVert *v, int toolflag)
766 {
767         int count = 0;
768
769         if (v->e) {
770                 BMEdge *curedge;
771                 const int len = bmesh_disk_count(v);
772                 int i;
773                 
774                 for (i = 0, curedge = v->e; i < len; i++) {
775                         if (BMO_TestFlag(bm, curedge, toolflag))
776                                 count++;
777                         curedge = bmesh_disk_nextedge(curedge, v);
778                 }
779         }
780
781         return count;
782 }
783
784 /*
785  *
786  * BMO_FLAG_BUFFER
787  *
788  * Flags elements in a slots buffer
789  */
790 void BMO_Flag_Buffer(BMesh *bm, BMOperator *op, const char *slotname,
791                      const int hflag, const char htype)
792 {
793         BMOpSlot *slot = BMO_GetSlot(op, slotname);
794         BMHeader **data =  slot->data.p;
795         int i;
796         
797         for (i = 0; i < slot->len; i++) {
798                 if (!(htype & data[i]->htype))
799                         continue;
800
801                 BMO_SetFlag(bm, data[i], hflag);
802         }
803 }
804
805 /*
806  *
807  * BMO_FLAG_BUFFER
808  *
809  * Removes flags from elements in a slots buffer
810  */
811 void BMO_Unflag_Buffer(BMesh *bm, BMOperator *op, const char *slotname,
812                        const int flag, const char htype)
813 {
814         BMOpSlot *slot = BMO_GetSlot(op, slotname);
815         BMHeader **data =  slot->data.p;
816         int i;
817         
818         for (i = 0; i < slot->len; i++) {
819                 if (!(htype & data[i]->htype))
820                         continue;
821
822                 BMO_ClearFlag(bm, data[i], flag);
823         }
824 }
825
826
827 /*
828  *
829  *      ALLOC/FREE FLAG LAYER
830  *
831  *  Used by operator stack to free/allocate
832  *  private flag data. This is allocated
833  *  using a mempool so the allocation/frees
834  *  should be quite fast.
835  *
836  *  BMESH_TODO:
837  *      Investigate not freeing flag layers until
838  *  all operators have been executed. This would
839  *  save a lot of realloc potentially.
840  */
841 static void alloc_flag_layer(BMesh *bm)
842 {
843         BMHeader *ele;
844         /* set the index values since we are looping over all data anyway,
845          * may save time later on */
846         int i;
847
848         BMIter iter;
849         BLI_mempool *oldpool = bm->toolflagpool;                /* old flag pool */
850         BLI_mempool *newpool;
851         void *oldflags;
852
853         /* store memcpy size for reuse */
854         const size_t old_totflags_size = (bm->totflags * sizeof(BMFlagLayer));
855         
856         bm->totflags++;
857
858         /* allocate new flag poo */
859         bm->toolflagpool = newpool = BLI_mempool_create(sizeof(BMFlagLayer)*bm->totflags, 512, 512, FALSE, FALSE);
860         
861         /* now go through and memcpy all the flags. Loops don't get a flag layer at this time.. */
862         for (ele = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, bm), i = 0; ele; ele = BMIter_Step(&iter), i++) {
863                 oldflags = ele->flags;
864                 ele->flags = BLI_mempool_calloc(newpool);
865                 memcpy(ele->flags, oldflags, old_totflags_size);
866                 BM_SetIndex(ele, i); /* set_inline */
867         }
868         for (ele = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, bm), i = 0; ele; ele = BMIter_Step(&iter), i++) {
869                 oldflags = ele->flags;
870                 ele->flags = BLI_mempool_calloc(newpool);
871                 memcpy(ele->flags, oldflags, old_totflags_size);
872                 BM_SetIndex(ele, i); /* set_inline */
873         }
874         for (ele = BMIter_New(&iter, bm, BM_FACES_OF_MESH, bm), i = 0; ele; ele = BMIter_Step(&iter), i++) {
875                 oldflags = ele->flags;
876                 ele->flags = BLI_mempool_calloc(newpool);
877                 memcpy(ele->flags, oldflags, old_totflags_size);
878                 BM_SetIndex(ele, i); /* set_inline */
879         }
880
881         bm->elem_index_dirty &= ~(BM_VERT|BM_EDGE|BM_FACE);
882
883         BLI_mempool_destroy(oldpool);
884 }
885
886 static void free_flag_layer(BMesh *bm)
887 {
888         BMHeader *ele;
889         /* set the index values since we are looping over all data anyway,
890          * may save time later on */
891         int i;
892
893         BMIter iter;
894         BLI_mempool *oldpool = bm->toolflagpool;
895         BLI_mempool *newpool;
896         void *oldflags;
897         
898         /* store memcpy size for reuse */
899         const size_t new_totflags_size = ((bm->totflags - 1) * sizeof(BMFlagLayer));
900
901         /* de-increment the totflags first.. */
902         bm->totflags--;
903         /* allocate new flag poo */
904         bm->toolflagpool = newpool = BLI_mempool_create(new_totflags_size, 512, 512, TRUE, FALSE);
905         
906         /* now go through and memcpy all the flag */
907         for (ele = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, bm), i = 0; ele; ele = BMIter_Step(&iter), i++) {
908                 oldflags = ele->flags;
909                 ele->flags = BLI_mempool_calloc(newpool);
910                 memcpy(ele->flags, oldflags, new_totflags_size);
911                 BM_SetIndex(ele, i); /* set_inline */
912         }
913         for (ele = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, bm), i = 0; ele; ele = BMIter_Step(&iter), i++) {
914                 oldflags = ele->flags;
915                 ele->flags = BLI_mempool_calloc(newpool);
916                 memcpy(ele->flags, oldflags, new_totflags_size);
917                 BM_SetIndex(ele, i); /* set_inline */
918         }
919         for (ele = BMIter_New(&iter, bm, BM_FACES_OF_MESH, bm), i = 0; ele; ele = BMIter_Step(&iter), i++) {
920                 oldflags = ele->flags;
921                 ele->flags = BLI_mempool_calloc(newpool);
922                 memcpy(ele->flags, oldflags, new_totflags_size);
923                 BM_SetIndex(ele, i); /* set_inline */
924         }
925
926         bm->elem_index_dirty &= ~(BM_VERT|BM_EDGE|BM_FACE);
927
928         BLI_mempool_destroy(oldpool);
929 }
930
931 static void clear_flag_layer(BMesh *bm)
932 {
933         BMVert *v;
934         BMEdge *e;
935         BMFace *f;
936         
937         BMIter verts;
938         BMIter edges;
939         BMIter faces;
940         
941         /* now go through and memcpy all the flag */
942         for (v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts)) {
943                 memset(v->head.flags + (bm->totflags - 1), 0, sizeof(BMFlagLayer));
944         }
945         for (e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges)) {
946                 memset(e->head.flags + (bm->totflags - 1), 0, sizeof(BMFlagLayer));
947         }
948         for (f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces)) {
949                 memset(f->head.flags + (bm->totflags - 1), 0, sizeof(BMFlagLayer));
950         }
951 }
952
953 void *BMO_FirstElem(BMOperator *op, const char *slotname)
954 {
955         BMOpSlot *slot = BMO_GetSlot(op, slotname);
956         
957         if (slot->slottype != BMOP_OPSLOT_ELEMENT_BUF)
958                 return NULL;
959
960         return slot->data.buf ? *(void **)slot->data.buf : NULL;
961 }
962
963 void *BMO_IterNew(BMOIter *iter, BMesh *UNUSED(bm), BMOperator *op,
964                   const char *slotname, const char restrictmask)
965 {
966         BMOpSlot *slot = BMO_GetSlot(op, slotname);
967
968         memset(iter, 0, sizeof(BMOIter));
969
970         iter->slot = slot;
971         iter->cur = 0;
972         iter->restrictmask = restrictmask;
973
974         if (iter->slot->slottype == BMOP_OPSLOT_MAPPING) {
975                 if (iter->slot->data.ghash) {
976                         BLI_ghashIterator_init(&iter->giter, slot->data.ghash);
977                 }
978                 else {
979                         return NULL;
980                 }
981         }
982
983         return BMO_IterStep(iter);
984 }
985
986 void *BMO_IterStep(BMOIter *iter)
987 {
988         if (iter->slot->slottype == BMOP_OPSLOT_ELEMENT_BUF) {
989                 BMHeader *h;
990
991                 if (iter->cur >= iter->slot->len) {
992                         return NULL;
993                 }
994
995                 h = ((void **)iter->slot->data.buf)[iter->cur++];
996                 while (!(iter->restrictmask & h->htype)) {
997                         if (iter->cur >= iter->slot->len) {
998                                 return NULL;
999                         }
1000
1001                         h = ((void **)iter->slot->data.buf)[iter->cur++];
1002                 }
1003
1004                 return h;
1005         }
1006         else if (iter->slot->slottype == BMOP_OPSLOT_MAPPING) {
1007                 struct BMOElemMapping *map;
1008                 void *ret = BLI_ghashIterator_getKey(&iter->giter);
1009                 map = BLI_ghashIterator_getValue(&iter->giter);
1010                 
1011                 iter->val = map + 1;
1012
1013                 BLI_ghashIterator_step(&iter->giter);
1014
1015                 return ret;
1016         }
1017
1018         return NULL;
1019 }
1020
1021 /* used for iterating over mapping */
1022 void *BMO_IterMapVal(BMOIter *iter)
1023 {
1024         return iter->val;
1025 }
1026
1027 void *BMO_IterMapValp(BMOIter *iter)
1028 {
1029         return *((void **)iter->val);
1030 }
1031
1032 float BMO_IterMapValf(BMOIter *iter)
1033 {
1034         return *((float *)iter->val);
1035 }
1036
1037 /* error syste */
1038 typedef struct BMOpError {
1039        struct BMOpError *next, *prev;
1040        int errorcode;
1041        BMOperator *op;
1042        const char *msg;
1043 } BMOpError;
1044
1045 void BMO_ClearStack(BMesh *bm)
1046 {
1047         while (BMO_PopError(bm, NULL, NULL));
1048 }
1049
1050 void BMO_RaiseError(BMesh *bm, BMOperator *owner, int errcode, const char *msg)
1051 {
1052         BMOpError *err = MEM_callocN(sizeof(BMOpError), "bmop_error");
1053         
1054         err->errorcode = errcode;
1055         if (!msg) msg = bmop_error_messages[errcode];
1056         err->msg = msg;
1057         err->op = owner;
1058         
1059         BLI_addhead(&bm->errorstack, err);
1060 }
1061
1062 int BMO_HasError(BMesh *bm)
1063 {
1064         return bm->errorstack.first != NULL;
1065 }
1066
1067 /* returns error code or 0 if no erro */
1068 int BMO_GetError(BMesh *bm, const char **msg, BMOperator **op)
1069 {
1070         BMOpError *err = bm->errorstack.first;
1071         if (!err) {
1072                 return 0;
1073         }
1074
1075         if (msg) *msg = err->msg;
1076         if (op) *op = err->op;
1077         
1078         return err->errorcode;
1079 }
1080
1081 int BMO_PopError(BMesh *bm, const char **msg, BMOperator **op)
1082 {
1083         int errorcode = BMO_GetError(bm, msg, op);
1084         
1085         if (errorcode) {
1086                 BMOpError *err = bm->errorstack.first;
1087                 
1088                 BLI_remlink(&bm->errorstack, bm->errorstack.first);
1089                 MEM_freeN(err);
1090         }
1091
1092         return errorcode;
1093 }
1094
1095 #if 0
1096 typedef struct BMOFlag {
1097         const char *str;
1098         int flag;
1099 } BMOFlag;
1100
1101 #define PAIR(f) {#f, f},fv
1102 static const char *bmesh_flags = {
1103         PAIR(BM_SELECT);
1104         PAIR(BM_SEAM);
1105         PAIR(BM_FGON);
1106         PAIR(BM_HIDDEN);
1107         PAIR(BM_SHARP);
1108         PAIR(BM_SMOOTH);
1109         {NULL, 0};
1110 };
1111 #undef PAIR
1112
1113 int bmesh_str_to_flag(const char *str)
1114 {
1115         int i;
1116
1117         while (bmesh_flags[i]->name) {
1118                 if (!strcmp(bmesh_flags[i]->name, str))
1119                         return bmesh_flags[i]->flag;
1120         }
1121
1122         return -1;
1123 }
1124 #endif
1125
1126 /* example:
1127  * BMO_CallOp(bm, "del %d %hv", DEL_ONLYFACES, BM_SELECT);
1128  *
1129  *  d - int
1130  *  i - int
1131  *  f - float
1132  *  hv - header flagged verts
1133  *  he - header flagged edges
1134  *  hf - header flagged faces
1135  *  fv - flagged verts
1136  *  fe - flagged edges
1137  *  ff - flagged faces
1138  */
1139
1140 #define NEXT_CHAR(fmt) ((fmt)[0] != 0 ? (fmt)[1] : 0)
1141
1142 static int bmesh_name_to_slotcode(BMOpDefine *def, const char *name)
1143 {
1144         int i;
1145
1146         for (i = 0; def->slottypes[i].type; i++) {
1147                 if (!strncmp(name, def->slottypes[i].name, MAX_SLOTNAME)) {
1148                         return i;
1149                 }
1150         }
1151
1152         return -1;
1153 }
1154
1155 static int bmesh_name_to_slotcode_check(BMOpDefine *def, const char *name)
1156 {
1157         int i = bmesh_name_to_slotcode(def, name);
1158         if (i < 0) {
1159                 fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, name);
1160         }
1161
1162         return i;
1163 }
1164
1165 static int bmesh_opname_to_opcode(const char *opname)
1166 {
1167         int i;
1168
1169         for (i = 0; i < bmesh_total_ops; i++) {
1170                 if (!strcmp(opname, opdefines[i]->name)) {
1171                         return i;
1172                 }
1173         }
1174
1175         fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, opname);
1176         return -1;
1177 }
1178
1179 int BMO_VInitOpf(BMesh *bm, BMOperator *op, const char *_fmt, va_list vlist)
1180 {
1181         BMOpDefine *def;
1182         char *opname, *ofmt, *fmt;
1183         char slotname[64] = {0};
1184         int i /*, n = strlen(fmt) */, stop /*, slotcode = -1 */, ret, type, state;
1185         int noslot = 0;
1186
1187
1188         /* basic useful info to help find where bmop formatting strings fail */
1189         int lineno = -1;
1190 #   define GOTO_ERROR { lineno = __LINE__; goto error; }
1191
1192
1193         /* we muck around in here, so dup i */
1194         fmt = ofmt = BLI_strdup(_fmt);
1195         
1196         /* find operator nam */
1197         i = strcspn(fmt, " \t");
1198
1199         opname = fmt;
1200         if (!opname[i]) noslot = 1;
1201         opname[i] = '\0';
1202
1203         fmt += i + (noslot ? 0 : 1);
1204         
1205         i = bmesh_opname_to_opcode(opname);
1206
1207         if (i == -1) {
1208                 MEM_freeN(ofmt);
1209                 return FALSE;
1210         }
1211
1212         BMO_Init_Op(bm, op, opname);
1213         def = opdefines[i];
1214         
1215         i = 0;
1216         state = 1; /* 0: not inside slotcode name, 1: inside slotcode name */
1217
1218         while (*fmt) {
1219                 if (state) {
1220                         /* jump past leading whitespac */
1221                         i = strspn(fmt, " \t");
1222                         fmt += i;
1223                         
1224                         /* ignore trailing whitespac */
1225                         if (!fmt[i])
1226                                 break;
1227
1228                         /* find end of slot name.  currently this is
1229                          * a little flexible, allowing "slot=%f",
1230                          * "slot %f", "slot%f", and "slot\t%f". */
1231                         i = strcspn(fmt, "= \t%");
1232                         if (!fmt[i]) GOTO_ERROR;
1233
1234                         fmt[i] = 0;
1235
1236                         if (bmesh_name_to_slotcode_check(def, fmt) < 0) GOTO_ERROR;
1237                         
1238                         BLI_strncpy(slotname, fmt, sizeof(slotname));
1239                         
1240                         state = 0;
1241                         fmt += i;
1242                 }
1243                 else {
1244                         switch (*fmt) {
1245                         case ' ':
1246                         case '\t':
1247                         case '=':
1248                         case '%':
1249                                 break;
1250                         case 'm': {
1251                                 int size, c;
1252                                 
1253                                 c = NEXT_CHAR(fmt);
1254                                 fmt++;
1255
1256                                 if (c == '3') size = 3;
1257                                 else if (c == '4') size = 4;
1258                                 else GOTO_ERROR;
1259
1260                                 BMO_Set_Mat(op, slotname, va_arg(vlist, void *), size);
1261                                 state = 1;
1262                                 break;
1263                         }
1264                         case 'v': {
1265                                 BMO_Set_Vec(op, slotname, va_arg(vlist, float *));
1266                                 state = 1;
1267                                 break;
1268                         }
1269                         case 'e': {
1270                                 BMHeader *ele = va_arg(vlist, void *);
1271                                 BMOpSlot *slot = BMO_GetSlot(op, slotname);
1272
1273                                 slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(void *) * 4);
1274                                 slot->len = 1;
1275                                 *((void **)slot->data.buf) = ele;
1276
1277                                 state = 1;
1278                                 break;
1279                         }
1280                         case 's': {
1281                                 BMOperator *op2 = va_arg(vlist, void *);
1282                                 const char *slotname2 = va_arg(vlist, char *);
1283
1284                                 BMO_CopySlot(op2, op, slotname2, slotname);
1285                                 state = 1;
1286                                 break;
1287                         }
1288                         case 'i':
1289                         case 'd':
1290                                 BMO_Set_Int(op, slotname, va_arg(vlist, int));
1291                                 state = 1;
1292                                 break;
1293                         case 'p':
1294                                 BMO_Set_Pnt(op, slotname, va_arg(vlist, void *));
1295                                 state = 1;
1296                                 break;
1297                         case 'f':
1298                         case 'h':
1299                         case 'a':
1300                                 type = *fmt;
1301
1302                                 if (NEXT_CHAR(fmt) == ' ' || NEXT_CHAR(fmt) == '\t' || NEXT_CHAR(fmt) == '\0') {
1303                                         BMO_Set_Float(op, slotname, va_arg(vlist, double));
1304                                 }
1305                                 else {
1306                                         ret = 0;
1307                                         stop = 0;
1308                                         while (1) {
1309                                                 switch (NEXT_CHAR(fmt)) {
1310                                                         case 'f': ret |= BM_FACE; break;
1311                                                         case 'e': ret |= BM_EDGE; break;
1312                                                         case 'v': ret |= BM_VERT; break;
1313                                                         default:
1314                                                                 stop = 1;
1315                                                                 break;
1316                                                 }
1317                                                 if (stop) {
1318                                                         break;
1319                                                 }
1320
1321                                                 fmt++;
1322                                         }
1323
1324                                         if (type == 'h') {
1325                                                 BMO_HeaderFlag_To_Slot(bm, op, slotname, va_arg(vlist, int), ret);
1326                                         }
1327                                         else if (type == 'a') {
1328                                                 BMO_All_To_Slot(bm, op, slotname, ret);
1329                                         }
1330                                         else {
1331                                                 BMO_Flag_To_Slot(bm, op, slotname, va_arg(vlist, int), ret);
1332                                         }
1333                                 }
1334
1335                                 state = 1;
1336                                 break;
1337                         default:
1338                                 fprintf(stderr,
1339                                         "%s: unrecognized bmop format char: %c, %d in '%s'\n",
1340                                         __func__, *fmt, (int)(fmt - ofmt), ofmt);
1341                                 break;
1342                         }
1343                 }
1344                 fmt++;
1345         }
1346
1347         MEM_freeN(ofmt);
1348         return TRUE;
1349 error:
1350
1351         /* non urgent todo - explain exactly what is failing */
1352         fprintf(stderr,
1353                 "%s: error parsing formatting string, %d in '%s'\n    see - %s:%d\n",
1354                 __func__, (int)(fmt - ofmt), _fmt, __FILE__, lineno);
1355         MEM_freeN(ofmt);
1356
1357         BMO_Finish_Op(bm, op);
1358         return FALSE;
1359
1360 #undef GOTO_ERROR
1361
1362 }
1363
1364
1365 int BMO_InitOpf(BMesh *bm, BMOperator *op, const char *fmt, ...)
1366 {
1367         va_list list;
1368
1369         va_start(list, fmt);
1370         if (!BMO_VInitOpf(bm, op, fmt, list)) {
1371                 printf("%s: failed\n", __func__);
1372                 va_end(list);
1373                 return FALSE;
1374         }
1375         va_end(list);
1376
1377         return TRUE;
1378 }
1379
1380 int BMO_CallOpf(BMesh *bm, const char *fmt, ...)
1381 {
1382         va_list list;
1383         BMOperator op;
1384
1385         va_start(list, fmt);
1386         if (!BMO_VInitOpf(bm, &op, fmt, list)) {
1387                 printf("%s: failed, format is:\n    \"%s\"\n", __func__, fmt);
1388                 va_end(list);
1389                 return FALSE;
1390         }
1391
1392         BMO_Exec_Op(bm, &op);
1393         BMO_Finish_Op(bm, &op);
1394
1395         va_end(list);
1396         return TRUE;
1397 }
1398
1399 /*
1400  * BMO_TOGGLEFLAG
1401  *
1402  * Toggles a flag for a certain element
1403  */
1404 #ifdef BMO_ToggleFlag
1405 #undef BMO_ToggleFlag
1406 #endif
1407 static void BMO_ToggleFlag(BMesh *bm, void *element, int flag)
1408 {
1409         BMHeader *head = element;
1410         head->flags[bm->stackdepth - 1].f ^= flag;
1411 }
1412
1413 /*
1414  * BMO_SETFLAG
1415  *
1416  * Sets a flag for a certain element
1417  */
1418 #ifdef BMO_SetFlag
1419 #undef BMO_SetFlag
1420 #endif
1421 static void BMO_SetFlag(BMesh *bm, void *element, const int flag)
1422 {
1423         BMHeader *head = element;
1424         head->flags[bm->stackdepth - 1].f |= flag;
1425 }
1426
1427 /*
1428  * BMO_CLEARFLAG
1429  *
1430  * Clears a specific flag from a given element
1431  */
1432 #ifdef BMO_ClearFlag
1433 #undef BMO_ClearFlag
1434 #endif
1435 static void BMO_ClearFlag(BMesh *bm, void *element, const int flag)
1436 {
1437         BMHeader *head = element;
1438         head->flags[bm->stackdepth - 1].f &= ~flag;
1439 }
1440
1441 /*
1442  * BMO_TESTFLAG
1443  *
1444  * Tests whether or not a flag is set for a specific element
1445  *
1446  */
1447 #ifdef BMO_TestFlag
1448 #undef BMO_TestFlag
1449 #endif
1450 static int BMO_TestFlag(BMesh *bm, void *element, int flag)
1451 {
1452         BMHeader *head = element;
1453         if (head->flags[bm->stackdepth - 1].f & flag)
1454                 return TRUE;
1455         return FALSE;
1456 }