split dissolve_disk into dissolve_vert dissolve_disk as agreed. also made dissolve...
[blender.git] / source / blender / bmesh / intern / bmesh_operators.c
1 #include "MEM_guardedalloc.h"
2
3 #include "BLI_memarena.h"
4 #include "BLI_mempool.h"
5
6 #include "BKE_utildefines.h"
7
8 #include "bmesh.h"
9 #include "bmesh_private.h"
10
11 #include <string.h>
12
13 /*forward declarations*/
14 static void alloc_flag_layer(BMesh *bm);
15 static void free_flag_layer(BMesh *bm);
16 static void clear_flag_layer(BMesh *bm);
17
18 typedef void (*opexec)(struct BMesh *bm, struct BMOperator *op);
19
20 /*mappings map elements to data, which
21   follows the mapping struct in memory.*/
22 typedef struct element_mapping {
23         BMHeader *element;
24         int len;
25 } element_mapping;
26
27
28 /*operator slot type information - size of one element of the type given.*/
29 const int BMOP_OPSLOT_TYPEINFO[] = {
30         sizeof(int),
31         sizeof(float),
32         sizeof(void*),
33         0, /* unused */
34         0, /* unused */
35         0, /* unused */
36         sizeof(void*),  /* pointer buffer */
37         sizeof(element_mapping)
38 };
39
40 /*
41  * BMESH OPSTACK PUSH
42  *
43  * Pushes the opstack down one level 
44  * and allocates a new flag layer if
45  * appropriate.
46  *
47 */
48
49 void BMO_push(BMesh *bm, BMOperator *op)
50 {
51         bm->stackdepth++;
52
53         /*add flag layer, if appropriate*/
54         if (bm->stackdepth > 1)
55                 alloc_flag_layer(bm);
56         else
57                 clear_flag_layer(bm);
58 }
59
60 /*
61  * BMESH OPSTACK POP
62  *
63  * Pops the opstack one level  
64  * and frees a flag layer if appropriate
65  * TODO: investigate NOT freeing flag
66  * layers.
67  *
68 */
69 void BMO_pop(BMesh *bm)
70 {
71         if(bm->stackdepth > 1)
72                 free_flag_layer(bm);
73
74         bm->stackdepth--;
75 }
76
77 /*
78  * BMESH OPSTACK INIT OP
79  *
80  * Initializes an operator structure  
81  * to a certain type
82  *
83 */
84
85 void BMO_Init_Op(BMOperator *op, int opcode)
86 {
87         int i;
88
89         memset(op, 0, sizeof(BMOperator));
90         op->type = opcode;
91         
92         /*initialize the operator slot types*/
93         for(i = 0; i < opdefines[opcode]->totslot; i++) {
94                 op->slots[i].slottype = opdefines[opcode]->slottypes[i];
95                 op->slots[i].index = i;
96         }
97
98         /*callback*/
99         op->exec = opdefines[opcode]->exec;
100
101         /*memarena, used for operator's slot buffers*/
102         op->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
103         BLI_memarena_use_calloc (op->arena);
104 }
105
106 /*
107  *      BMESH OPSTACK EXEC OP
108  *
109  *  Executes a passed in operator. This handles
110  *  the allocation and freeing of temporary flag
111  *  layers and starting/stopping the modelling
112  *  loop. Can be called from other operators
113  *  exec callbacks as well.
114  * 
115 */
116
117 void BMO_Exec_Op(BMesh *bm, BMOperator *op)
118 {
119         
120         BMO_push(bm, op);
121
122         if(bm->stackdepth == 1)
123                 bmesh_begin_edit(bm);
124         op->exec(bm, op);
125         
126         if(bm->stackdepth == 1)
127                 bmesh_end_edit(bm,0);
128         
129         BMO_pop(bm);    
130 }
131
132 /*
133  *  BMESH OPSTACK FINISH OP
134  *
135  *  Does housekeeping chores related to finishing
136  *  up an operator.
137  *
138 */
139
140 void BMO_Finish_Op(BMesh *bm, BMOperator *op)
141 {
142         BMOpSlot *slot;
143         int i;
144
145         for (i=0; i<opdefines[op->type]->totslot; i++) {
146                 slot = &op->slots[i];
147                 if (slot->slottype == BMOP_OPSLOT_MAPPING) {
148                         if (slot->data.ghash) 
149                                 BLI_ghash_free(slot->data.ghash, NULL, NULL);
150                 }
151         }
152
153         BLI_memarena_free(op->arena);
154 }
155
156 /*
157  * BMESH OPSTACK GET SLOT
158  *
159  * Returns a pointer to the slot of  
160  * type 'slotcode'
161  *
162 */
163
164 BMOpSlot *BMO_GetSlot(BMOperator *op, int slotcode)
165 {
166         return &(op->slots[slotcode]);
167 }
168
169 /*
170  * BMESH OPSTACK COPY SLOT
171  *
172  * Copies data from one slot to another 
173  *
174 */
175
176 void BMO_CopySlot(BMOperator *source_op, BMOperator *dest_op, int src, int dst)
177 {
178         BMOpSlot *source_slot = &source_op->slots[src];
179         BMOpSlot *dest_slot = &dest_op->slots[dst];
180
181         if(source_slot == dest_slot)
182                 return;
183
184         if(source_slot->slottype != dest_slot->slottype)
185                 return;
186         
187         if (dest_slot->slottype > BMOP_OPSLOT_VEC) {
188                 if (dest_slot->slottype != BMOP_OPSLOT_MAPPING) {
189                         /*do buffer copy*/
190                         dest_slot->data.buf = NULL;
191                         dest_slot->len = source_slot->len;
192                         if(dest_slot->len){
193                                 dest_slot->data.buf = BLI_memarena_alloc(dest_op->arena, BMOP_OPSLOT_TYPEINFO[dest_slot->slottype] * dest_slot->len);
194                                 memcpy(dest_slot->data.buf, source_slot->data.buf, BMOP_OPSLOT_TYPEINFO[dest_slot->slottype] * dest_slot->len);
195                         }
196                 } else {
197                         GHashIterator it;
198                         element_mapping *srcmap, *dstmap;
199
200                         /*sanity check*/
201                         if (!source_slot->data.ghash) return;
202                         
203                         if (!dest_slot->data.ghash) {
204                                 dest_slot->data.ghash = 
205                                       BLI_ghash_new(BLI_ghashutil_ptrhash, 
206                                       BLI_ghashutil_ptrcmp);
207                         }
208
209                         BLI_ghashIterator_init(&it, source_slot->data.ghash);
210                         for (;srcmap=BLI_ghashIterator_getValue(&it);
211                               BLI_ghashIterator_step(&it))
212                         {
213                                 dstmap = BLI_memarena_alloc(dest_op->arena, 
214                                             sizeof(*dstmap) + srcmap->len);
215
216                                 dstmap->element = srcmap->element;
217                                 dstmap->len = srcmap->len;
218                                 memcpy(dstmap+1, srcmap+1, srcmap->len);
219                                 
220                                 BLI_ghash_insert(dest_slot->data.ghash, 
221                                                 dstmap->element, dstmap);                               
222                         }
223                 }
224         } else {
225                 dest_slot->data = source_slot->data;
226         }
227 }
228
229 /*
230  * BMESH OPSTACK SET XXX
231  *
232  * Sets the value of a slot depending on it's type
233  *
234 */
235
236
237 void BMO_Set_Float(BMOperator *op, int slotcode, float f)
238 {
239         if( !(op->slots[slotcode].slottype == BMOP_OPSLOT_FLT) )
240                 return;
241         op->slots[slotcode].data.f = f;
242 }
243
244 void BMO_Set_Int(BMOperator *op, int slotcode, int i)
245 {
246         if( !(op->slots[slotcode].slottype == BMOP_OPSLOT_INT) )
247                 return;
248         op->slots[slotcode].data.i = i;
249
250 }
251
252
253 void BMO_Set_Pnt(BMOperator *op, int slotcode, void *p)
254 {
255         if( !(op->slots[slotcode].slottype == BMOP_OPSLOT_PNT) )
256                 return;
257         op->slots[slotcode].data.p = p;
258 }
259
260 void BMO_Set_Vec(BMOperator *op, int slotcode, float *vec)
261 {
262         if( !(op->slots[slotcode].slottype == BMOP_OPSLOT_VEC) )
263                 return;
264
265         VECCOPY(op->slots[slotcode].data.vec, vec);
266 }
267
268 /*
269  * BMO_SETFLAG
270  *
271  * Sets a flag for a certain element
272  *
273 */
274 void BMO_SetFlag(BMesh *bm, void *element, int flag)
275 {
276         BMHeader *head = element;
277         head->flags[bm->stackdepth-1].mask |= flag;
278 }
279
280 /*
281  * BMO_CLEARFLAG
282  *
283  * Clears a specific flag from a given element
284  *
285 */
286
287 void BMO_ClearFlag(BMesh *bm, void *element, int flag)
288 {
289         BMHeader *head = element;
290         head->flags[bm->stackdepth-1].mask &= ~flag;
291 }
292
293 /*
294  * BMO_TESTFLAG
295  *
296  * Tests whether or not a flag is set for a specific element
297  *
298  *
299 */
300
301 int BMO_TestFlag(BMesh *bm, void *element, int flag)
302 {
303         BMHeader *head = element;
304         if(head->flags[bm->stackdepth-1].mask & flag)
305                 return 1;
306         return 0;
307 }
308
309 /*
310  * BMO_COUNTFLAG
311  *
312  * Counts the number of elements of a certain type that
313  * have a specific flag set.
314  *
315 */
316
317 int BMO_CountFlag(BMesh *bm, int flag, int type)
318 {
319         BMIter elements;
320         BMHeader *e;
321         int count = 0;
322
323         if(type & BM_VERT){
324                 for(e = BMIter_New(&elements, bm, BM_VERTS, bm); e; e = BMIter_Step(&elements)){
325                         if(BMO_TestFlag(bm, e, flag))
326                                 count++;
327                 }
328         }
329         if(type & BM_EDGE){
330                 for(e = BMIter_New(&elements, bm, BM_EDGES, bm); e; e = BMIter_Step(&elements)){
331                         if(BMO_TestFlag(bm, e, flag))
332                                 count++;
333                 }
334         }
335         if(type & BM_FACE){
336                 for(e = BMIter_New(&elements, bm, BM_FACES, bm); e; e = BMIter_Step(&elements)){
337                         if(BMO_TestFlag(bm, e, flag))
338                                 count++;
339                 }
340         }
341
342         return count;   
343 }
344
345 int BMO_CountSlotBuf(struct BMesh *bm, struct BMOperator *op, int slotcode)
346 {
347         BMOpSlot *slot = &op->slots[slotcode];
348         
349         /*check if its actually a buffer*/
350         if( !(slot->slottype > BMOP_OPSLOT_VEC) )
351                 return 0;
352
353         return slot->len;
354 }
355
356 #if 0
357 void *BMO_Grow_Array(BMesh *bm, BMOperator *op, int slotcode, int totadd) {
358         BMOpSlot *slot = &op->slots[slotcode];
359         void *tmp;
360         
361         /*check if its actually a buffer*/
362         if( !(slot->slottype > BMOP_OPSLOT_VEC) )
363                 return NULL;
364
365         if (slot->flag & BMOS_DYNAMIC_ARRAY) {
366                 if (slot->len >= slot->size) {
367                         slot->size = (slot->size+1+totadd)*2;
368
369                         tmp = slot->data.buf;
370                         slot->data.buf = MEM_callocN(BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode]] * slot->size, "opslot dynamic array");
371                         memcpy(slot->data.buf, tmp, BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode]] * slot->size);
372                         MEM_freeN(tmp);
373                 }
374
375                 slot->len += totadd;
376         } else {
377                 slot->flag |= BMOS_DYNAMIC_ARRAY;
378                 slot->len += totadd;
379                 slot->size = slot->len+2;
380                 tmp = slot->data.buf;
381                 slot->data.buf = MEM_callocN(BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode]] * slot->len, "opslot dynamic array");
382                 memcpy(slot->data.buf, tmp, BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode]] * slot->len);
383         }
384
385         return slot->data.buf;
386 }
387 #endif
388
389 void BMO_Insert_Mapping(BMesh *bm, BMOperator *op, int slotcode, 
390                         void *element, void *data, int len) {
391         element_mapping *mapping;
392         BMOpSlot *slot = &op->slots[slotcode];
393
394         /*sanity check*/
395         if (slot->slottype != BMOP_OPSLOT_MAPPING) return;
396         
397         mapping = BLI_memarena_alloc(op->arena, sizeof(*mapping) + len);
398
399         mapping->element = element;
400         mapping->len = len;
401         memcpy(mapping+1, data, len);
402
403         if (!slot->data.ghash) {
404                 slot->data.ghash = BLI_ghash_new(BLI_ghashutil_ptrhash, 
405                                                      BLI_ghashutil_ptrcmp);
406         }
407         
408         BLI_ghash_insert(slot->data.ghash, element, mapping);
409 }
410
411 void BMO_Mapping_To_Flag(struct BMesh *bm, struct BMOperator *op, 
412                          int slotcode, int flag)
413 {
414         GHashIterator it;
415         BMOpSlot *slot = &op->slots[slotcode];
416         BMHeader *ele;
417
418         /*sanity check*/
419         if (slot->slottype != BMOP_OPSLOT_MAPPING) return;
420         if (!slot->data.ghash) return;
421
422         BLI_ghashIterator_init(&it, slot->data.ghash);
423         for (;ele=BLI_ghashIterator_getKey(&it);BLI_ghashIterator_step(&it)) {
424                 BMO_SetFlag(bm, ele, flag);
425         }
426 }
427
428 void BMO_Insert_MapFloat(BMesh *bm, BMOperator *op, int slotcode, 
429                         void *element, float val)
430 {
431         BMO_Insert_Mapping(bm, op, slotcode, element, &val, sizeof(float));
432 }
433
434 void BMO_Insert_MapPointer(BMesh *bm, BMOperator *op, int slotcode, 
435                         void *element, void *val)
436 {
437         BMO_Insert_Mapping(bm, op, slotcode, element, &val, sizeof(void*));
438 }
439
440 int BMO_InMap(BMesh *bm, BMOperator *op, int slotcode, void *element)
441 {
442         BMOpSlot *slot = &op->slots[slotcode];
443
444         /*sanity check*/
445         if (slot->slottype != BMOP_OPSLOT_MAPPING) return 0;
446         if (!slot->data.ghash) return 0;
447
448         return BLI_ghash_haskey(slot->data.ghash, element);
449 }
450
451 void *BMO_Get_MapData(BMesh *bm, BMOperator *op, int slotcode,
452                       void *element)
453 {
454         element_mapping *mapping;
455         BMOpSlot *slot = &op->slots[slotcode];
456
457         /*sanity check*/
458         if (slot->slottype != BMOP_OPSLOT_MAPPING) return NULL;
459         if (!slot->data.ghash) return NULL;
460
461         mapping = BLI_ghash_lookup(slot->data.ghash, element);
462         
463         if (!mapping) return NULL;
464
465         return mapping + 1;
466 }
467
468 float BMO_Get_MapFloat(BMesh *bm, BMOperator *op, int slotcode,
469                        void *element)
470 {
471         float *val = BMO_Get_MapData(bm, op, slotcode, element);
472         if (val) return *val;
473
474         return 0.0f;
475 }
476
477 void *BMO_Get_MapPointer(BMesh *bm, BMOperator *op, int slotcode,
478                        void *element)
479 {
480         void **val = BMO_Get_MapData(bm, op, slotcode, element);
481         if (val) return *val;
482
483         return NULL;
484 }
485
486 static void *alloc_slot_buffer(BMOperator *op, int slotcode, int len){
487
488         /*check if its actually a buffer*/
489         if( !(op->slots[slotcode].slottype > BMOP_OPSLOT_VEC) )
490                 return NULL;
491         
492         op->slots[slotcode].len = len;
493         if(len)
494                 op->slots[slotcode].data.buf = BLI_memarena_alloc(op->arena, BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode]] * len);
495         return op->slots[slotcode].data.buf;
496 }
497
498 /*
499  *
500  * BMO_HEADERFLAG_TO_SLOT
501  *
502  * Copies elements of a certain type, which have a certain header flag set 
503  * into an output slot for an operator.
504  *
505 */
506
507 void BMO_HeaderFlag_To_Slot(BMesh *bm, BMOperator *op, int slotcode, int flag, int type)
508 {
509         BMIter elements;
510         BMHeader *e;
511         BMOpSlot *output = BMO_GetSlot(op, slotcode);
512         int totelement=0, i=0;
513         
514         totelement = BM_CountFlag(bm, type, BM_SELECT);
515
516         if(totelement){
517                 alloc_slot_buffer(op, slotcode, totelement);
518
519                 if (type & BM_VERT) {
520                         for (e = BMIter_New(&elements, bm, BM_VERTS, bm); e; e = BMIter_Step(&elements)) {
521                                 if(e->flag & flag) {
522                                         ((BMHeader**)output->data.p)[i] = e;
523                                         i++;
524                                 }
525                         }
526                 }
527
528                 if (type & BM_EDGE) {
529                         for (e = BMIter_New(&elements, bm, BM_EDGES, bm); e; e = BMIter_Step(&elements)) {
530                                 if(e->flag & flag){
531                                         ((BMHeader**)output->data.p)[i] = e;
532                                         i++;
533                                 }
534                         }
535                 }
536
537                 if (type & BM_FACE) {
538                         for (e = BMIter_New(&elements, bm, BM_FACES, bm); e; e = BMIter_Step(&elements)) {
539                                 if(e->flag & flag){
540                                         ((BMHeader**)output->data.p)[i] = e;
541                                         i++;
542                                 }
543                         }
544                 }
545         }
546 }
547
548 /*
549  *
550  * BMO_FLAG_TO_SLOT
551  *
552  * Copies elements of a certain type, which have a certain flag set 
553  * into an output slot for an operator.
554  *
555 */
556 void BMO_Flag_To_Slot(BMesh *bm, BMOperator *op, int slotcode, int flag, int type)
557 {
558         BMIter elements;
559         BMHeader *e;
560         BMOpSlot *output = BMO_GetSlot(op, slotcode);
561         int totelement = BMO_CountFlag(bm, flag, type), i=0;
562
563         if(totelement){
564                 alloc_slot_buffer(op, slotcode, totelement);
565
566                 if (type & BM_VERT) {
567                         for (e = BMIter_New(&elements, bm, BM_VERTS, bm); e; e = BMIter_Step(&elements)) {
568                                 if(BMO_TestFlag(bm, e, flag)){
569                                         ((BMHeader**)output->data.p)[i] = e;
570                                         i++;
571                                 }
572                         }
573                 }
574
575                 if (type & BM_EDGE) {
576                         for (e = BMIter_New(&elements, bm, BM_EDGES, bm); e; e = BMIter_Step(&elements)) {
577                                 if(BMO_TestFlag(bm, e, flag)){
578                                         ((BMHeader**)output->data.p)[i] = e;
579                                         i++;
580                                 }
581                         }
582                 }
583
584                 if (type & BM_FACE) {
585                         for (e = BMIter_New(&elements, bm, BM_FACES, bm); e; e = BMIter_Step(&elements)) {
586                                 if(BMO_TestFlag(bm, e, flag)){
587                                         ((BMHeader**)output->data.p)[i] = e;
588                                         i++;
589                                 }
590                         }
591                 }
592         }
593 }
594
595 /*
596  *
597  * BMO_FLAG_BUFFER
598  *
599  * Flags elements in a slots buffer
600  *
601 */
602
603 void BMO_Flag_Buffer(BMesh *bm, BMOperator *op, int slotcode, int flag)
604 {
605         BMOpSlot *slot = BMO_GetSlot(op, slotcode);
606         BMHeader **data =  slot->data.p;
607         int i;
608         
609         for(i = 0; i < slot->len; i++)
610                 BMO_SetFlag(bm, data[i], flag);
611 }
612
613 /*
614  *
615  * BMO_FLAG_BUFFER
616  *
617  * Removes flags from elements in a slots buffer
618  *
619 */
620
621 void BMO_Unflag_Buffer(BMesh *bm, BMOperator *op, int slotcode, int flag)
622 {
623         BMOpSlot *slot = BMO_GetSlot(op, slotcode);
624         BMHeader **data =  slot->data.p;
625         int i;
626         
627         for(i = 0; i < slot->len; i++)
628                 BMO_ClearFlag(bm, data[i], flag);
629 }
630
631
632 /*
633  *
634  *      ALLOC/FREE FLAG LAYER
635  *
636  *  Used by operator stack to free/allocate 
637  *  private flag data. This is allocated
638  *  using a mempool so the allocation/frees
639  *  should be quite fast.
640  *
641  *  TODO:
642  *      Investigate not freeing flag layers until
643  *  all operators have been executed. This would
644  *  save a lot of realloc potentially.
645  *
646 */
647
648 static void alloc_flag_layer(BMesh *bm)
649 {
650         BMVert *v;
651         BMEdge *e;
652         BMFace *f;
653
654         BMIter verts;
655         BMIter edges;
656         BMIter faces;
657         BLI_mempool *oldpool = bm->flagpool;            /*old flag pool*/
658         void *oldflags;
659         
660         /*allocate new flag pool*/
661         bm->flagpool = BLI_mempool_create(sizeof(BMFlagLayer)*(bm->totflags+1), 512, 512 );
662         
663         /*now go through and memcpy all the flags. Loops don't get a flag layer at this time...*/
664         for(v = BMIter_New(&verts, bm, BM_VERTS, bm); v; v = BMIter_Step(&verts)){
665                 oldflags = v->head.flags;
666                 v->head.flags = BLI_mempool_calloc(bm->flagpool);
667                 memcpy(v->head.flags, oldflags, sizeof(BMFlagLayer)*bm->totflags); /*dont know if this memcpy usage is correct*/
668         }
669         for(e = BMIter_New(&edges, bm, BM_EDGES, bm); e; e = BMIter_Step(&edges)){
670                 oldflags = e->head.flags;
671                 e->head.flags = BLI_mempool_calloc(bm->flagpool);
672                 memcpy(e->head.flags, oldflags, sizeof(BMFlagLayer)*bm->totflags);
673         }
674         for(f = BMIter_New(&faces, bm, BM_FACES, bm); f; f = BMIter_Step(&faces)){
675                 oldflags = f->head.flags;
676                 f->head.flags = BLI_mempool_calloc(bm->flagpool);
677                 memcpy(f->head.flags, oldflags, sizeof(BMFlagLayer)*bm->totflags);
678         }
679         bm->totflags++;
680         BLI_mempool_destroy(oldpool);
681 }
682
683 static void free_flag_layer(BMesh *bm)
684 {
685         BMVert *v;
686         BMEdge *e;
687         BMFace *f;
688
689         BMIter verts;
690         BMIter edges;
691         BMIter faces;
692         BLI_mempool *oldpool = bm->flagpool;
693         void *oldflags;
694         
695         /*de-increment the totflags first...*/
696         bm->totflags--;
697         /*allocate new flag pool*/
698         bm->flagpool = BLI_mempool_create(sizeof(BMFlagLayer)*bm->totflags, 512, 512);
699         
700         /*now go through and memcpy all the flags*/
701         for(v = BMIter_New(&verts, bm, BM_VERTS, bm); v; v = BMIter_Step(&verts)){
702                 oldflags = v->head.flags;
703                 v->head.flags = BLI_mempool_calloc(bm->flagpool);
704                 memcpy(v->head.flags, oldflags, sizeof(BMFlagLayer)*bm->totflags);  /*correct?*/
705         }
706         for(e = BMIter_New(&edges, bm, BM_EDGES, bm); e; e = BMIter_Step(&edges)){
707                 oldflags = e->head.flags;
708                 e->head.flags = BLI_mempool_calloc(bm->flagpool);
709                 memcpy(e->head.flags, oldflags, sizeof(BMFlagLayer)*bm->totflags);
710         }
711         for(f = BMIter_New(&faces, bm, BM_FACES, bm); f; f = BMIter_Step(&faces)){
712                 oldflags = f->head.flags;
713                 f->head.flags = BLI_mempool_calloc(bm->flagpool);
714                 memcpy(f->head.flags, oldflags, sizeof(BMFlagLayer)*bm->totflags);
715         }
716
717         BLI_mempool_destroy(oldpool);
718 }
719
720 static void clear_flag_layer(BMesh *bm)
721 {
722         BMVert *v;
723         BMEdge *e;
724         BMFace *f;
725         
726         BMIter verts;
727         BMIter edges;
728         BMIter faces;
729         
730         /*now go through and memcpy all the flags*/
731         for(v = BMIter_New(&verts, bm, BM_VERTS, bm); v; v = BMIter_Step(&verts)){
732                 memset(v->head.flags+bm->totflags-1, 0, sizeof(BMFlagLayer));
733         }
734         for(e = BMIter_New(&edges, bm, BM_EDGES, bm); e; e = BMIter_Step(&edges)){
735                 memset(e->head.flags+bm->totflags-1, 0, sizeof(BMFlagLayer));
736         }
737         for(f = BMIter_New(&faces, bm, BM_FACES, bm); f; f = BMIter_Step(&faces)){
738                 memset(f->head.flags+bm->totflags-1, 0, sizeof(BMFlagLayer));
739         }
740 }
741
742 void *BMO_IterNew(BMOIter *iter, BMesh *bm, BMOperator *op, 
743                   int slotcode)
744 {
745         BMOpSlot *slot = &op->slots[slotcode];
746
747         iter->slot = slot;
748         iter->cur = 0;
749
750         if (iter->slot->slottype == BMOP_OPSLOT_MAPPING)
751                 if (iter->slot->data.ghash)
752                         BLI_ghashIterator_init(&iter->giter, slot->data.ghash);
753
754         return BMO_IterStep(iter);
755 }
756
757 void *BMO_IterStep(BMOIter *iter)
758 {
759         if (iter->slot->slottype == BMOP_OPSLOT_PNT_BUF) {
760                 if (iter->cur >= iter->slot->len) return NULL;
761
762                 return ((void**)iter->slot->data.buf)[iter->cur++];
763         } else if (iter->slot->slottype == BMOP_OPSLOT_MAPPING) {
764                 struct element_mapping *map; 
765                 void *ret = BLI_ghashIterator_getKey(&iter->giter);
766                 map = BLI_ghashIterator_getValue(&iter->giter);
767                 
768                 iter->val = map + 1;
769
770                 BLI_ghashIterator_step(&iter->giter);
771
772                 return ret;
773         }
774
775         return NULL;
776 }
777
778 /*used for iterating over mappings*/
779 void *BMO_IterMapVal(BMOIter *iter)
780 {
781         return iter->val;
782 }
783
784
785 /*error system*/
786 typedef struct bmop_error {
787        struct bmop_error *next, *prev;
788        int errorcode;
789        BMOperator *op;
790        char *msg;
791 } bmop_error;
792
793 void BMO_ClearStack(BMesh *bm)
794 {
795         while (BMO_PopError(bm, NULL, NULL));
796 }
797
798 void BMO_RaiseError(BMesh *bm, BMOperator *owner, int errcode, char *msg)
799 {
800         bmop_error *err = MEM_callocN(sizeof(bmop_error), "bmop_error");
801         
802         err->errorcode = errcode;
803         if (!msg) msg = bmop_error_messages[errcode];
804         err->msg = msg;
805         err->op = owner;
806         
807         BLI_addhead(&bm->errorstack, err);
808 }
809
810 /*returns error code or 0 if no error*/
811 int BMO_GetError(BMesh *bm, char **msg, BMOperator **op)
812 {
813         bmop_error *err = bm->errorstack.first;
814         if (!err) return 0;
815
816         if (msg) *msg = err->msg;
817         if (op) *op = err->op;
818         
819         return err->errorcode;
820 }
821
822 int BMO_PopError(BMesh *bm, char **msg, BMOperator **op)
823 {
824         int errorcode = BMO_GetError(bm, msg, op);
825         
826         if (errorcode) {
827                 bmop_error *err = bm->errorstack.first;
828                 
829                 BLI_remlink(&bm->errorstack, bm->errorstack.first);
830                 MEM_freeN(err);
831         }
832
833         return errorcode;
834 }