Code Cleanup:
[blender.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, const int flag)
85 {
86         op->flag |= flag;
87 }
88
89 void BMO_Clear_OpFlag(BMesh *UNUSED(bm), BMOperator *op, const 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, const int oflag, 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, oflag))
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, oflag))
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, oflag))
457                                 count++;
458                 }
459         }
460
461         return count;
462 }
463
464 void BMO_Clear_Flag_All(BMesh *bm, BMOperator *UNUSED(op), const char htype, const int oflag)
465 {
466         const char iter_types[3] = {BM_VERTS_OF_MESH,
467                                     BM_EDGES_OF_MESH,
468                                     BM_FACES_OF_MESH};
469
470         const char flag_types[3] = {BM_VERT, BM_EDGE, BM_FACE};
471
472         BMIter iter;
473         BMHeader *ele;
474         int i;
475
476         for (i = 0; i < 3; i++) {
477                 if (htype & flag_types[i]) {
478                         BM_ITER(ele, &iter, bm, iter_types[i], NULL) {
479                                 BMO_ClearFlag(bm, ele, oflag);
480                         }
481                 }
482         }
483 }
484
485 int BMO_CountSlotBuf(struct BMesh *UNUSED(bm), struct BMOperator *op, const char *slotname)
486 {
487         BMOpSlot *slot = BMO_GetSlot(op, slotname);
488         
489         /* check if its actually a buffer */
490         if (!(slot->slottype > BMOP_OPSLOT_VEC))
491                 return 0;
492
493         return slot->len;
494 }
495
496 int BMO_CountSlotMap(BMesh *UNUSED(bm), BMOperator *op, const char *slotname)
497 {
498         BMOpSlot *slot = BMO_GetSlot(op, slotname);
499         
500         /* check if its actually a buffer */
501         if (!(slot->slottype == BMOP_OPSLOT_MAPPING))
502                 return 0;
503
504         return slot->data.ghash ? BLI_ghash_size(slot->data.ghash) : 0;
505 }
506
507 #if 0
508 void *BMO_Grow_Array(BMesh *bm, BMOperator *op, int slotcode, int totadd)
509 {
510         BMOpSlot *slot = &op->slots[slotcode];
511         void *tmp;
512         
513         /* check if its actually a buffer */
514         if (!(slot->slottype > BMOP_OPSLOT_VEC))
515                 return NULL;
516
517         if (slot->flag & BMOS_DYNAMIC_ARRAY) {
518                 if (slot->len >= slot->size) {
519                         slot->size = (slot->size + 1 + totadd) * 2;
520
521                         tmp = slot->data.buf;
522                         slot->data.buf = MEM_callocN(BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode].type] * slot->size, "opslot dynamic array");
523                         memcpy(slot->data.buf, tmp, BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode].type] * slot->size);
524                         MEM_freeN(tmp);
525                 }
526
527                 slot->len += totadd;
528         }
529         else {
530                 slot->flag |= BMOS_DYNAMIC_ARRAY;
531                 slot->len += totadd;
532                 slot->size = slot->len + 2;
533                 tmp = slot->data.buf;
534                 slot->data.buf = MEM_callocN(BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode].type] * slot->len, "opslot dynamic array");
535                 memcpy(slot->data.buf, tmp, BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode].type] * slot->len);
536         }
537
538         return slot->data.buf;
539 }
540 #endif
541
542 void BMO_Mapping_To_Flag(struct BMesh *bm, struct BMOperator *op,
543                          const char *slotname, const int oflag)
544 {
545         GHashIterator it;
546         BMOpSlot *slot = BMO_GetSlot(op, slotname);
547         BMHeader *ele;
548
549         /* sanity check */
550         if (slot->slottype != BMOP_OPSLOT_MAPPING) return;
551         if (!slot->data.ghash) return;
552
553         BLI_ghashIterator_init(&it, slot->data.ghash);
554         for ( ; (ele = BLI_ghashIterator_getKey(&it)); BLI_ghashIterator_step(&it)) {
555                 BMO_SetFlag(bm, ele, oflag);
556         }
557 }
558
559 static void *alloc_slot_buffer(BMOperator *op, const char *slotname, int len)
560 {
561         BMOpSlot *slot = BMO_GetSlot(op, slotname);
562
563         /* check if its actually a buffer */
564         if (!(slot->slottype > BMOP_OPSLOT_VEC))
565                 return NULL;
566         
567         slot->len = len;
568         if (len)
569                 slot->data.buf = BLI_memarena_alloc(op->arena, BMOP_OPSLOT_TYPEINFO[slot->slottype] * len);
570         return slot->data.buf;
571 }
572
573 /*
574  * BMO_ALL_TO_SLOT
575  *
576  * Copies all elements of a certain type into an operator slot.
577  *
578  */
579
580 static void BMO_All_To_Slot(BMesh *bm, BMOperator *op, const char *slotname, const char htype)
581 {
582         BMIter elements;
583         BMHeader *e;
584         BMOpSlot *output = BMO_GetSlot(op, slotname);
585         int totelement = 0, i = 0;
586         
587         if (htype & BM_VERT) totelement += bm->totvert;
588         if (htype & BM_EDGE) totelement += bm->totedge;
589         if (htype & BM_FACE) totelement += bm->totface;
590
591         if (totelement) {
592                 alloc_slot_buffer(op, slotname, totelement);
593
594                 if (htype & BM_VERT) {
595                         for (e = BMIter_New(&elements, bm, BM_VERTS_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
596                                 ((BMHeader **)output->data.p)[i] = e;
597                                 i++;
598                         }
599                 }
600
601                 if (htype & BM_EDGE) {
602                         for (e = BMIter_New(&elements, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
603                                 ((BMHeader **)output->data.p)[i] = e;
604                                 i++;
605                         }
606                 }
607
608                 if (htype & BM_FACE) {
609                         for (e = BMIter_New(&elements, bm, BM_FACES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
610                                 ((BMHeader **)output->data.p)[i] = e;
611                                 i++;
612                         }
613                 }
614         }
615 }
616
617 /*
618  * BMO_HEADERFLAG_TO_SLOT
619  *
620  * Copies elements of a certain type, which have a certain header flag set
621  * into a slot for an operator.
622  */
623
624 void BMO_HeaderFlag_To_Slot(BMesh *bm, BMOperator *op, const char *slotname,
625                             const char hflag, const char htype)
626 {
627         BMIter elements;
628         BMHeader *e;
629         BMOpSlot *output = BMO_GetSlot(op, slotname);
630         int totelement = 0, i = 0;
631         
632         totelement = BM_CountFlag(bm, htype, hflag, 1);
633
634         if (totelement) {
635                 alloc_slot_buffer(op, slotname, totelement);
636
637                 if (htype & BM_VERT) {
638                         for (e = BMIter_New(&elements, bm, BM_VERTS_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
639                                 if (!BM_TestHFlag(e, BM_HIDDEN) && BM_TestHFlag(e, hflag)) {
640                                         ((BMHeader **)output->data.p)[i] = e;
641                                         i++;
642                                 }
643                         }
644                 }
645
646                 if (htype & BM_EDGE) {
647                         for (e = BMIter_New(&elements, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
648                                 if (!BM_TestHFlag(e, BM_HIDDEN) && BM_TestHFlag(e, hflag)) {
649                                         ((BMHeader **)output->data.p)[i] = e;
650                                         i++;
651                                 }
652                         }
653                 }
654
655                 if (htype & BM_FACE) {
656                         for (e = BMIter_New(&elements, bm, BM_FACES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
657                                 if (!BM_TestHFlag(e, BM_HIDDEN) && BM_TestHFlag(e, hflag)) {
658                                         ((BMHeader **)output->data.p)[i] = e;
659                                         i++;
660                                 }
661                         }
662                 }
663         }
664         else {
665                 output->len = 0;
666         }
667 }
668
669 /*
670  * BMO_FLAG_TO_SLOT
671  *
672  * Copies elements of a certain type, which have a certain flag set
673  * into an output slot for an operator.
674  */
675 void BMO_Flag_To_Slot(BMesh *bm, BMOperator *op, const char *slotname,
676                       const int oflag, const char htype)
677 {
678         BMIter elements;
679         BMHeader *e;
680         BMOpSlot *output = BMO_GetSlot(op, slotname);
681         int totelement = BMO_CountFlag(bm, oflag, htype), i = 0;
682
683         if (totelement) {
684                 alloc_slot_buffer(op, slotname, totelement);
685
686                 if (htype & BM_VERT) {
687                         for (e = BMIter_New(&elements, bm, BM_VERTS_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
688                                 if (BMO_TestFlag(bm, e, oflag)) {
689                                         ((BMHeader **)output->data.p)[i] = e;
690                                         i++;
691                                 }
692                         }
693                 }
694
695                 if (htype & BM_EDGE) {
696                         for (e = BMIter_New(&elements, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
697                                 if (BMO_TestFlag(bm, e, oflag)) {
698                                         ((BMHeader **)output->data.p)[i] = e;
699                                         i++;
700                                 }
701                         }
702                 }
703
704                 if (htype & BM_FACE) {
705                         for (e = BMIter_New(&elements, bm, BM_FACES_OF_MESH, bm); e; e = BMIter_Step(&elements)) {
706                                 if (BMO_TestFlag(bm, e, oflag)) {
707                                         ((BMHeader **)output->data.p)[i] = e;
708                                         i++;
709                                 }
710                         }
711                 }
712         }
713         else {
714                 output->len = 0;
715         }
716 }
717
718 /*
719  *
720  * BMO_FLAG_BUFFER
721  *
722  * Header Flags elements in a slots buffer, automatically
723  * using the selection API where appropriate.
724  */
725 void BMO_HeaderFlag_Buffer(BMesh *bm, BMOperator *op, const char *slotname,
726                            const char hflag, const char htype)
727 {
728         BMOpSlot *slot = BMO_GetSlot(op, slotname);
729         BMHeader **data =  slot->data.p;
730         int i;
731         
732         for (i = 0; i < slot->len; i++) {
733                 if (!(htype & data[i]->htype))
734                         continue;
735
736                 if (hflag & BM_SELECT) {
737                         BM_Select(bm, data[i], TRUE);
738                 }
739                 BM_SetHFlag(data[i], hflag);
740         }
741 }
742
743 /*
744  *
745  * BMO_FLAG_BUFFER
746  *
747  * Removes flags from elements in a slots buffer, automatically
748  * using the selection API where appropriate.
749  */
750 void BMO_UnHeaderFlag_Buffer(BMesh *bm, BMOperator *op, const char *slotname,
751                              const char hflag, const char htype)
752 {
753         BMOpSlot *slot = BMO_GetSlot(op, slotname);
754         BMHeader **data =  slot->data.p;
755         int i;
756         
757         for (i = 0; i < slot->len; i++) {
758                 if (!(htype & data[i]->htype))
759                         continue;
760
761                 if (hflag & BM_SELECT) {
762                         BM_Select(bm, data[i], FALSE);
763                 }
764
765                 BM_ClearHFlag(data[i], hflag);
766         }
767 }
768 int BMO_Vert_CountEdgeFlags(BMesh *bm, BMVert *v, const int oflag)
769 {
770         int count = 0;
771
772         if (v->e) {
773                 BMEdge *curedge;
774                 const int len = bmesh_disk_count(v);
775                 int i;
776                 
777                 for (i = 0, curedge = v->e; i < len; i++) {
778                         if (BMO_TestFlag(bm, curedge, oflag))
779                                 count++;
780                         curedge = bmesh_disk_nextedge(curedge, v);
781                 }
782         }
783
784         return count;
785 }
786
787 /*
788  *
789  * BMO_FLAG_BUFFER
790  *
791  * Flags elements in a slots buffer
792  */
793 void BMO_Flag_Buffer(BMesh *bm, BMOperator *op, const char *slotname,
794                      const int oflag, const char htype)
795 {
796         BMOpSlot *slot = BMO_GetSlot(op, slotname);
797         BMHeader **data =  slot->data.p;
798         int i;
799         
800         for (i = 0; i < slot->len; i++) {
801                 if (!(htype & data[i]->htype))
802                         continue;
803
804                 BMO_SetFlag(bm, data[i], oflag);
805         }
806 }
807
808 /*
809  *
810  * BMO_FLAG_BUFFER
811  *
812  * Removes flags from elements in a slots buffer
813  */
814 void BMO_Unflag_Buffer(BMesh *bm, BMOperator *op, const char *slotname,
815                        const int oflag, const char htype)
816 {
817         BMOpSlot *slot = BMO_GetSlot(op, slotname);
818         BMHeader **data =  slot->data.p;
819         int i;
820         
821         for (i = 0; i < slot->len; i++) {
822                 if (!(htype & data[i]->htype))
823                         continue;
824
825                 BMO_ClearFlag(bm, data[i], oflag);
826         }
827 }
828
829
830 /*
831  *
832  *      ALLOC/FREE FLAG LAYER
833  *
834  *  Used by operator stack to free/allocate
835  *  private flag data. This is allocated
836  *  using a mempool so the allocation/frees
837  *  should be quite fast.
838  *
839  *  BMESH_TODO:
840  *      Investigate not freeing flag layers until
841  *  all operators have been executed. This would
842  *  save a lot of realloc potentially.
843  */
844 static void alloc_flag_layer(BMesh *bm)
845 {
846         BMHeader *ele;
847         /* set the index values since we are looping over all data anyway,
848          * may save time later on */
849         int i;
850
851         BMIter iter;
852         BLI_mempool *oldpool = bm->toolflagpool;                /* old flag pool */
853         BLI_mempool *newpool;
854         void *oldflags;
855
856         /* store memcpy size for reuse */
857         const size_t old_totflags_size = (bm->totflags * sizeof(BMFlagLayer));
858         
859         bm->totflags++;
860
861         /* allocate new flag poo */
862         bm->toolflagpool = newpool = BLI_mempool_create(sizeof(BMFlagLayer)*bm->totflags, 512, 512, FALSE, FALSE);
863         
864         /* now go through and memcpy all the flags. Loops don't get a flag layer at this time.. */
865         for (ele = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, bm), i = 0; ele; ele = BMIter_Step(&iter), i++) {
866                 oldflags = ele->flags;
867                 ele->flags = BLI_mempool_calloc(newpool);
868                 memcpy(ele->flags, oldflags, old_totflags_size);
869                 BM_SetIndex(ele, i); /* set_inline */
870         }
871         for (ele = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, bm), i = 0; ele; ele = BMIter_Step(&iter), i++) {
872                 oldflags = ele->flags;
873                 ele->flags = BLI_mempool_calloc(newpool);
874                 memcpy(ele->flags, oldflags, old_totflags_size);
875                 BM_SetIndex(ele, i); /* set_inline */
876         }
877         for (ele = BMIter_New(&iter, bm, BM_FACES_OF_MESH, bm), i = 0; ele; ele = BMIter_Step(&iter), i++) {
878                 oldflags = ele->flags;
879                 ele->flags = BLI_mempool_calloc(newpool);
880                 memcpy(ele->flags, oldflags, old_totflags_size);
881                 BM_SetIndex(ele, i); /* set_inline */
882         }
883
884         bm->elem_index_dirty &= ~(BM_VERT|BM_EDGE|BM_FACE);
885
886         BLI_mempool_destroy(oldpool);
887 }
888
889 static void free_flag_layer(BMesh *bm)
890 {
891         BMHeader *ele;
892         /* set the index values since we are looping over all data anyway,
893          * may save time later on */
894         int i;
895
896         BMIter iter;
897         BLI_mempool *oldpool = bm->toolflagpool;
898         BLI_mempool *newpool;
899         void *oldflags;
900         
901         /* store memcpy size for reuse */
902         const size_t new_totflags_size = ((bm->totflags - 1) * sizeof(BMFlagLayer));
903
904         /* de-increment the totflags first.. */
905         bm->totflags--;
906         /* allocate new flag poo */
907         bm->toolflagpool = newpool = BLI_mempool_create(new_totflags_size, 512, 512, TRUE, FALSE);
908         
909         /* now go through and memcpy all the flag */
910         for (ele = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, bm), i = 0; ele; ele = BMIter_Step(&iter), i++) {
911                 oldflags = ele->flags;
912                 ele->flags = BLI_mempool_calloc(newpool);
913                 memcpy(ele->flags, oldflags, new_totflags_size);
914                 BM_SetIndex(ele, i); /* set_inline */
915         }
916         for (ele = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, bm), i = 0; ele; ele = BMIter_Step(&iter), i++) {
917                 oldflags = ele->flags;
918                 ele->flags = BLI_mempool_calloc(newpool);
919                 memcpy(ele->flags, oldflags, new_totflags_size);
920                 BM_SetIndex(ele, i); /* set_inline */
921         }
922         for (ele = BMIter_New(&iter, bm, BM_FACES_OF_MESH, bm), i = 0; ele; ele = BMIter_Step(&iter), i++) {
923                 oldflags = ele->flags;
924                 ele->flags = BLI_mempool_calloc(newpool);
925                 memcpy(ele->flags, oldflags, new_totflags_size);
926                 BM_SetIndex(ele, i); /* set_inline */
927         }
928
929         bm->elem_index_dirty &= ~(BM_VERT|BM_EDGE|BM_FACE);
930
931         BLI_mempool_destroy(oldpool);
932 }
933
934 static void clear_flag_layer(BMesh *bm)
935 {
936         BMVert *v;
937         BMEdge *e;
938         BMFace *f;
939         
940         BMIter verts;
941         BMIter edges;
942         BMIter faces;
943         
944         /* now go through and memcpy all the flag */
945         for (v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts)) {
946                 memset(v->head.flags + (bm->totflags - 1), 0, sizeof(BMFlagLayer));
947         }
948         for (e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges)) {
949                 memset(e->head.flags + (bm->totflags - 1), 0, sizeof(BMFlagLayer));
950         }
951         for (f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces)) {
952                 memset(f->head.flags + (bm->totflags - 1), 0, sizeof(BMFlagLayer));
953         }
954 }
955
956 void *BMO_FirstElem(BMOperator *op, const char *slotname)
957 {
958         BMOpSlot *slot = BMO_GetSlot(op, slotname);
959         
960         if (slot->slottype != BMOP_OPSLOT_ELEMENT_BUF)
961                 return NULL;
962
963         return slot->data.buf ? *(void **)slot->data.buf : NULL;
964 }
965
966 void *BMO_IterNew(BMOIter *iter, BMesh *UNUSED(bm), BMOperator *op,
967                   const char *slotname, const char restrictmask)
968 {
969         BMOpSlot *slot = BMO_GetSlot(op, slotname);
970
971         memset(iter, 0, sizeof(BMOIter));
972
973         iter->slot = slot;
974         iter->cur = 0;
975         iter->restrictmask = restrictmask;
976
977         if (iter->slot->slottype == BMOP_OPSLOT_MAPPING) {
978                 if (iter->slot->data.ghash) {
979                         BLI_ghashIterator_init(&iter->giter, slot->data.ghash);
980                 }
981                 else {
982                         return NULL;
983                 }
984         }
985
986         return BMO_IterStep(iter);
987 }
988
989 void *BMO_IterStep(BMOIter *iter)
990 {
991         if (iter->slot->slottype == BMOP_OPSLOT_ELEMENT_BUF) {
992                 BMHeader *h;
993
994                 if (iter->cur >= iter->slot->len) {
995                         return NULL;
996                 }
997
998                 h = ((void **)iter->slot->data.buf)[iter->cur++];
999                 while (!(iter->restrictmask & h->htype)) {
1000                         if (iter->cur >= iter->slot->len) {
1001                                 return NULL;
1002                         }
1003
1004                         h = ((void **)iter->slot->data.buf)[iter->cur++];
1005                 }
1006
1007                 return h;
1008         }
1009         else if (iter->slot->slottype == BMOP_OPSLOT_MAPPING) {
1010                 struct BMOElemMapping *map;
1011                 void *ret = BLI_ghashIterator_getKey(&iter->giter);
1012                 map = BLI_ghashIterator_getValue(&iter->giter);
1013                 
1014                 iter->val = map + 1;
1015
1016                 BLI_ghashIterator_step(&iter->giter);
1017
1018                 return ret;
1019         }
1020
1021         return NULL;
1022 }
1023
1024 /* used for iterating over mapping */
1025 void *BMO_IterMapVal(BMOIter *iter)
1026 {
1027         return iter->val;
1028 }
1029
1030 void *BMO_IterMapValp(BMOIter *iter)
1031 {
1032         return *((void **)iter->val);
1033 }
1034
1035 float BMO_IterMapValf(BMOIter *iter)
1036 {
1037         return *((float *)iter->val);
1038 }
1039
1040 /* error syste */
1041 typedef struct BMOpError {
1042        struct BMOpError *next, *prev;
1043        int errorcode;
1044        BMOperator *op;
1045        const char *msg;
1046 } BMOpError;
1047
1048 void BMO_ClearStack(BMesh *bm)
1049 {
1050         while (BMO_PopError(bm, NULL, NULL));
1051 }
1052
1053 void BMO_RaiseError(BMesh *bm, BMOperator *owner, int errcode, const char *msg)
1054 {
1055         BMOpError *err = MEM_callocN(sizeof(BMOpError), "bmop_error");
1056         
1057         err->errorcode = errcode;
1058         if (!msg) msg = bmop_error_messages[errcode];
1059         err->msg = msg;
1060         err->op = owner;
1061         
1062         BLI_addhead(&bm->errorstack, err);
1063 }
1064
1065 int BMO_HasError(BMesh *bm)
1066 {
1067         return bm->errorstack.first != NULL;
1068 }
1069
1070 /* returns error code or 0 if no erro */
1071 int BMO_GetError(BMesh *bm, const char **msg, BMOperator **op)
1072 {
1073         BMOpError *err = bm->errorstack.first;
1074         if (!err) {
1075                 return 0;
1076         }
1077
1078         if (msg) *msg = err->msg;
1079         if (op) *op = err->op;
1080         
1081         return err->errorcode;
1082 }
1083
1084 int BMO_PopError(BMesh *bm, const char **msg, BMOperator **op)
1085 {
1086         int errorcode = BMO_GetError(bm, msg, op);
1087         
1088         if (errorcode) {
1089                 BMOpError *err = bm->errorstack.first;
1090                 
1091                 BLI_remlink(&bm->errorstack, bm->errorstack.first);
1092                 MEM_freeN(err);
1093         }
1094
1095         return errorcode;
1096 }
1097
1098 #if 0
1099 typedef struct BMOFlag {
1100         const char *str;
1101         int flag;
1102 } BMOFlag;
1103
1104 #define PAIR(f) {#f, f},fv
1105 static const char *bmesh_flags = {
1106         PAIR(BM_SELECT);
1107         PAIR(BM_SEAM);
1108         PAIR(BM_FGON);
1109         PAIR(BM_HIDDEN);
1110         PAIR(BM_SHARP);
1111         PAIR(BM_SMOOTH);
1112         {NULL, 0};
1113 };
1114 #undef PAIR
1115
1116 int bmesh_str_to_flag(const char *str)
1117 {
1118         int i;
1119
1120         while (bmesh_flags[i]->name) {
1121                 if (!strcmp(bmesh_flags[i]->name, str))
1122                         return bmesh_flags[i]->flag;
1123         }
1124
1125         return -1;
1126 }
1127 #endif
1128
1129 /* example:
1130  * BMO_CallOp(bm, "del %d %hv", DEL_ONLYFACES, BM_SELECT);
1131  *
1132  *  d - int
1133  *  i - int
1134  *  f - float
1135  *  hv - header flagged verts
1136  *  he - header flagged edges
1137  *  hf - header flagged faces
1138  *  fv - flagged verts
1139  *  fe - flagged edges
1140  *  ff - flagged faces
1141  */
1142
1143 #define NEXT_CHAR(fmt) ((fmt)[0] != 0 ? (fmt)[1] : 0)
1144
1145 static int bmesh_name_to_slotcode(BMOpDefine *def, const char *name)
1146 {
1147         int i;
1148
1149         for (i = 0; def->slottypes[i].type; i++) {
1150                 if (!strncmp(name, def->slottypes[i].name, MAX_SLOTNAME)) {
1151                         return i;
1152                 }
1153         }
1154
1155         return -1;
1156 }
1157
1158 static int bmesh_name_to_slotcode_check(BMOpDefine *def, const char *name)
1159 {
1160         int i = bmesh_name_to_slotcode(def, name);
1161         if (i < 0) {
1162                 fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, name);
1163         }
1164
1165         return i;
1166 }
1167
1168 static int bmesh_opname_to_opcode(const char *opname)
1169 {
1170         int i;
1171
1172         for (i = 0; i < bmesh_total_ops; i++) {
1173                 if (!strcmp(opname, opdefines[i]->name)) {
1174                         return i;
1175                 }
1176         }
1177
1178         fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, opname);
1179         return -1;
1180 }
1181
1182 int BMO_VInitOpf(BMesh *bm, BMOperator *op, const char *_fmt, va_list vlist)
1183 {
1184         BMOpDefine *def;
1185         char *opname, *ofmt, *fmt;
1186         char slotname[64] = {0};
1187         int i /*, n = strlen(fmt) */, stop /*, slotcode = -1 */, ret, type, state;
1188         int noslot = 0;
1189
1190
1191         /* basic useful info to help find where bmop formatting strings fail */
1192         int lineno = -1;
1193 #   define GOTO_ERROR { lineno = __LINE__; goto error; }
1194
1195
1196         /* we muck around in here, so dup i */
1197         fmt = ofmt = BLI_strdup(_fmt);
1198         
1199         /* find operator nam */
1200         i = strcspn(fmt, " \t");
1201
1202         opname = fmt;
1203         if (!opname[i]) noslot = 1;
1204         opname[i] = '\0';
1205
1206         fmt += i + (noslot ? 0 : 1);
1207         
1208         i = bmesh_opname_to_opcode(opname);
1209
1210         if (i == -1) {
1211                 MEM_freeN(ofmt);
1212                 return FALSE;
1213         }
1214
1215         BMO_Init_Op(bm, op, opname);
1216         def = opdefines[i];
1217         
1218         i = 0;
1219         state = 1; /* 0: not inside slotcode name, 1: inside slotcode name */
1220
1221         while (*fmt) {
1222                 if (state) {
1223                         /* jump past leading whitespac */
1224                         i = strspn(fmt, " \t");
1225                         fmt += i;
1226                         
1227                         /* ignore trailing whitespac */
1228                         if (!fmt[i])
1229                                 break;
1230
1231                         /* find end of slot name.  currently this is
1232                          * a little flexible, allowing "slot=%f",
1233                          * "slot %f", "slot%f", and "slot\t%f". */
1234                         i = strcspn(fmt, "= \t%");
1235                         if (!fmt[i]) GOTO_ERROR;
1236
1237                         fmt[i] = 0;
1238
1239                         if (bmesh_name_to_slotcode_check(def, fmt) < 0) GOTO_ERROR;
1240                         
1241                         BLI_strncpy(slotname, fmt, sizeof(slotname));
1242                         
1243                         state = 0;
1244                         fmt += i;
1245                 }
1246                 else {
1247                         switch (*fmt) {
1248                         case ' ':
1249                         case '\t':
1250                         case '=':
1251                         case '%':
1252                                 break;
1253                         case 'm': {
1254                                 int size, c;
1255                                 
1256                                 c = NEXT_CHAR(fmt);
1257                                 fmt++;
1258
1259                                 if (c == '3') size = 3;
1260                                 else if (c == '4') size = 4;
1261                                 else GOTO_ERROR;
1262
1263                                 BMO_Set_Mat(op, slotname, va_arg(vlist, void *), size);
1264                                 state = 1;
1265                                 break;
1266                         }
1267                         case 'v': {
1268                                 BMO_Set_Vec(op, slotname, va_arg(vlist, float *));
1269                                 state = 1;
1270                                 break;
1271                         }
1272                         case 'e': {
1273                                 BMHeader *ele = va_arg(vlist, void *);
1274                                 BMOpSlot *slot = BMO_GetSlot(op, slotname);
1275
1276                                 slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(void *) * 4);
1277                                 slot->len = 1;
1278                                 *((void **)slot->data.buf) = ele;
1279
1280                                 state = 1;
1281                                 break;
1282                         }
1283                         case 's': {
1284                                 BMOperator *op2 = va_arg(vlist, void *);
1285                                 const char *slotname2 = va_arg(vlist, char *);
1286
1287                                 BMO_CopySlot(op2, op, slotname2, slotname);
1288                                 state = 1;
1289                                 break;
1290                         }
1291                         case 'i':
1292                         case 'd':
1293                                 BMO_Set_Int(op, slotname, va_arg(vlist, int));
1294                                 state = 1;
1295                                 break;
1296                         case 'p':
1297                                 BMO_Set_Pnt(op, slotname, va_arg(vlist, void *));
1298                                 state = 1;
1299                                 break;
1300                         case 'f':
1301                         case 'h':
1302                         case 'a':
1303                                 type = *fmt;
1304
1305                                 if (NEXT_CHAR(fmt) == ' ' || NEXT_CHAR(fmt) == '\t' || NEXT_CHAR(fmt) == '\0') {
1306                                         BMO_Set_Float(op, slotname, va_arg(vlist, double));
1307                                 }
1308                                 else {
1309                                         ret = 0;
1310                                         stop = 0;
1311                                         while (1) {
1312                                                 switch (NEXT_CHAR(fmt)) {
1313                                                         case 'f': ret |= BM_FACE; break;
1314                                                         case 'e': ret |= BM_EDGE; break;
1315                                                         case 'v': ret |= BM_VERT; break;
1316                                                         default:
1317                                                                 stop = 1;
1318                                                                 break;
1319                                                 }
1320                                                 if (stop) {
1321                                                         break;
1322                                                 }
1323
1324                                                 fmt++;
1325                                         }
1326
1327                                         if (type == 'h') {
1328                                                 BMO_HeaderFlag_To_Slot(bm, op, slotname, va_arg(vlist, int), ret);
1329                                         }
1330                                         else if (type == 'a') {
1331                                                 BMO_All_To_Slot(bm, op, slotname, ret);
1332                                         }
1333                                         else {
1334                                                 BMO_Flag_To_Slot(bm, op, slotname, va_arg(vlist, int), ret);
1335                                         }
1336                                 }
1337
1338                                 state = 1;
1339                                 break;
1340                         default:
1341                                 fprintf(stderr,
1342                                         "%s: unrecognized bmop format char: %c, %d in '%s'\n",
1343                                         __func__, *fmt, (int)(fmt - ofmt), ofmt);
1344                                 break;
1345                         }
1346                 }
1347                 fmt++;
1348         }
1349
1350         MEM_freeN(ofmt);
1351         return TRUE;
1352 error:
1353
1354         /* non urgent todo - explain exactly what is failing */
1355         fprintf(stderr,
1356                 "%s: error parsing formatting string, %d in '%s'\n    see - %s:%d\n",
1357                 __func__, (int)(fmt - ofmt), _fmt, __FILE__, lineno);
1358         MEM_freeN(ofmt);
1359
1360         BMO_Finish_Op(bm, op);
1361         return FALSE;
1362
1363 #undef GOTO_ERROR
1364
1365 }
1366
1367
1368 int BMO_InitOpf(BMesh *bm, BMOperator *op, const char *fmt, ...)
1369 {
1370         va_list list;
1371
1372         va_start(list, fmt);
1373         if (!BMO_VInitOpf(bm, op, fmt, list)) {
1374                 printf("%s: failed\n", __func__);
1375                 va_end(list);
1376                 return FALSE;
1377         }
1378         va_end(list);
1379
1380         return TRUE;
1381 }
1382
1383 int BMO_CallOpf(BMesh *bm, const char *fmt, ...)
1384 {
1385         va_list list;
1386         BMOperator op;
1387
1388         va_start(list, fmt);
1389         if (!BMO_VInitOpf(bm, &op, fmt, list)) {
1390                 printf("%s: failed, format is:\n    \"%s\"\n", __func__, fmt);
1391                 va_end(list);
1392                 return FALSE;
1393         }
1394
1395         BMO_Exec_Op(bm, &op);
1396         BMO_Finish_Op(bm, &op);
1397
1398         va_end(list);
1399         return TRUE;
1400 }
1401
1402 /*
1403  * BMO_TOGGLEFLAG
1404  *
1405  * Toggles a flag for a certain element
1406  */
1407 #ifdef BMO_ToggleFlag
1408 #undef BMO_ToggleFlag
1409 #endif
1410 static void BMO_ToggleFlag(BMesh *bm, void *element, int oflag)
1411 {
1412         BMHeader *head = element;
1413         head->flags[bm->stackdepth - 1].f ^= oflag;
1414 }
1415
1416 /*
1417  * BMO_SETFLAG
1418  *
1419  * Sets a flag for a certain element
1420  */
1421 #ifdef BMO_SetFlag
1422 #undef BMO_SetFlag
1423 #endif
1424 static void BMO_SetFlag(BMesh *bm, void *element, const int oflag)
1425 {
1426         BMHeader *head = element;
1427         head->flags[bm->stackdepth - 1].f |= oflag;
1428 }
1429
1430 /*
1431  * BMO_CLEARFLAG
1432  *
1433  * Clears a specific flag from a given element
1434  */
1435 #ifdef BMO_ClearFlag
1436 #undef BMO_ClearFlag
1437 #endif
1438 static void BMO_ClearFlag(BMesh *bm, void *element, const int oflag)
1439 {
1440         BMHeader *head = element;
1441         head->flags[bm->stackdepth - 1].f &= ~oflag;
1442 }
1443
1444 /*
1445  * BMO_TESTFLAG
1446  *
1447  * Tests whether or not a flag is set for a specific element
1448  *
1449  */
1450 #ifdef BMO_TestFlag
1451 #undef BMO_TestFlag
1452 #endif
1453 static int BMO_TestFlag(BMesh *bm, void *element, const int oflag)
1454 {
1455         BMHeader *head = element;
1456         if (head->flags[bm->stackdepth - 1].f & oflag)
1457                 return TRUE;
1458         return FALSE;
1459 }