f02bc7553d95ff06bf35b40fcd5b319ec983a4cc
[blender.git] / source / blender / bmesh / operators / bmesh_dupeops.c
1 #include "MEM_guardedalloc.h"
2
3 #include "BKE_utildefines.h"
4
5 #include "BLI_ghash.h"
6 #include "BLI_memarena.h"
7 #include "BLI_blenlib.h"
8 #include "BLI_arithb.h"
9
10 #include "bmesh.h"
11 #include "bmesh_operators_private.h"
12
13 /*local flag defines*/
14 #define DUPE_INPUT              1 /*input from operator*/
15 #define DUPE_NEW                2
16 #define DUPE_DONE               4
17 #define DUPE_MAPPED             8
18
19 /*
20  *  COPY VERTEX
21  *
22  *   Copy an existing vertex from one bmesh to another.
23  *
24 */
25 static BMVert *copy_vertex(BMesh *source_mesh, BMVert *source_vertex, BMesh *target_mesh, GHash *vhash)
26 {
27         BMVert *target_vertex = NULL;
28
29         /*Create a new vertex*/
30         target_vertex = BM_Make_Vert(target_mesh, source_vertex->co,  NULL);
31         
32         /*Insert new vertex into the vert hash*/
33         BLI_ghash_insert(vhash, source_vertex, target_vertex);  
34         
35         /*Copy attributes*/
36         BM_Copy_Attributes(source_mesh, target_mesh, source_vertex, target_vertex);
37         
38         /*Set internal op flags*/
39         BMO_SetFlag(target_mesh, (BMHeader*)target_vertex, DUPE_NEW);
40         
41         return target_vertex;
42 }
43
44 /*
45  * COPY EDGE
46  *
47  * Copy an existing edge from one bmesh to another.
48  *
49 */
50 static BMEdge *copy_edge(BMOperator *op, BMesh *source_mesh,
51                          BMEdge *source_edge, BMesh *target_mesh,
52                          GHash *vhash, GHash *ehash)
53 {
54         BMEdge *target_edge = NULL;
55         BMVert *target_vert1, *target_vert2;
56         BMFace *face;
57         BMIter fiter;
58         int rlen;
59
60         /*see if any of the neighboring faces are
61           not being duplicated.  in that case,
62           add it to the new/old map.*/
63         rlen = 0;
64         for (face=BMIter_New(&fiter,source_mesh, BM_FACES_OF_EDGE,source_edge);
65                 face; face=BMIter_Step(&fiter)) {
66                 if (BMO_TestFlag(source_mesh, face, DUPE_INPUT)) {
67                         rlen++;
68                 }
69         }
70
71         /*Lookup v1 and v2*/
72         target_vert1 = BLI_ghash_lookup(vhash, source_edge->v1);
73         target_vert2 = BLI_ghash_lookup(vhash, source_edge->v2);
74         
75         /*Create a new edge*/
76         target_edge = BM_Make_Edge(target_mesh, target_vert1, target_vert2, NULL, 0);
77         
78         /*add to new/old edge map if necassary*/
79         if (rlen < 2) {
80                 /*not sure what non-manifold cases of greater then three
81                   radial should do.*/
82                 BMO_Insert_MapPointer(source_mesh,op, "boundarymap",
83                         source_edge, target_edge);
84         }
85
86         /*Insert new edge into the edge hash*/
87         BLI_ghash_insert(ehash, source_edge, target_edge);      
88         
89         /*Copy attributes*/
90         BM_Copy_Attributes(source_mesh, target_mesh, source_edge, target_edge);
91         
92         /*Set internal op flags*/
93         BMO_SetFlag(target_mesh, (BMHeader*)target_edge, DUPE_NEW);
94         
95         return target_edge;
96 }
97
98 /*
99  * COPY FACE
100  *
101  *  Copy an existing face from one bmesh to another.
102  *
103 */
104 static BMFace *copy_face(BMOperator *op, BMesh *source_mesh,
105                          BMFace *source_face, BMesh *target_mesh, 
106                          BMEdge **edar, GHash *vhash, GHash *ehash)
107 {
108         BMVert *target_vert1, *target_vert2;
109         BMLoop *source_loop, *target_loop;
110         BMFace *target_face = NULL;
111         BMIter iter, iter2;
112         int i;
113         
114         /*lookup the first and second verts*/
115         target_vert1 = BLI_ghash_lookup(vhash, BMIter_New(&iter, source_mesh, BM_VERTS_OF_FACE, source_face));
116         target_vert2 = BLI_ghash_lookup(vhash, BMIter_Step(&iter));
117         
118         /*lookup edges*/
119         for (i=0,source_loop=BMIter_New(&iter, source_mesh, BM_LOOPS_OF_FACE, source_face); 
120                      source_loop; source_loop=BMIter_Step(&iter), i++) {
121                 edar[i] = BLI_ghash_lookup(ehash, source_loop->e);
122         }
123         
124         /*create new face*/
125         target_face = BM_Make_Ngon(target_mesh, target_vert1, target_vert2, edar, source_face->len, 0); 
126         BMO_Insert_MapPointer(source_mesh, op, 
127                  "facemap", source_face, target_face);
128         BMO_Insert_MapPointer(source_mesh, op, 
129                  "facemap", target_face, source_face);
130
131         BM_Copy_Attributes(source_mesh, target_mesh, source_face, target_face);
132
133         /*mark the face for output*/
134         BMO_SetFlag(target_mesh, (BMHeader*)target_face, DUPE_NEW);
135         
136         /*copy per-loop custom data*/
137         for (i=0,source_loop=BMIter_New(&iter, source_mesh, BM_LOOPS_OF_FACE, source_face),
138           target_loop=BMIter_New(&iter2, target_mesh, BM_LOOPS_OF_FACE, target_face);
139           source_loop && target_loop; source_loop=BMIter_Step(&iter), target_loop=BMIter_Step(&iter2),
140           i++) {
141                 BM_Copy_Attributes(source_mesh, target_mesh, source_loop, target_loop);         
142         }
143
144
145         return target_face;
146 }
147         /*
148  * COPY MESH
149  *
150  * Internal Copy function.
151 */
152
153 static void copy_mesh(BMOperator *op, BMesh *source, BMesh *target)
154 {
155
156         BMVert *v = NULL, *v2;
157         BMEdge *e = NULL, **edar = NULL;
158         BMLoop *l = NULL;
159         BMFace *f = NULL;
160         
161         BMIter verts;
162         BMIter edges;
163         BMIter faces;
164         
165         GHash *vhash;
166         GHash *ehash;
167         
168         int maxlength = 0;
169
170         /*initialize pointer hashes*/
171         vhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); 
172         ehash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
173         
174         /*initialize edge pointer array*/
175         for(f = BMIter_New(&faces, source, BM_FACES_OF_MESH, source); f; f = BMIter_Step(&faces)){
176                 if(f->len > maxlength) maxlength = f->len;
177         }
178         edar = MEM_callocN(sizeof(BMEdge*) * maxlength, "BM copy mesh edge pointer array");
179         
180         for(v = BMIter_New(&verts, source, BM_VERTS_OF_MESH, source); v; v = BMIter_Step(&verts)){
181                 if(BMO_TestFlag(source, (BMHeader*)v, DUPE_INPUT) && (!BMO_TestFlag(source, (BMHeader*)v, DUPE_DONE))){
182                         BMIter iter;
183                         int iso = 1;
184
185                         v2 = copy_vertex(source, v, target, vhash);
186
187                         BM_ITER(f, &iter, source, BM_FACES_OF_VERT, v) {
188                                 if (BMO_TestFlag(source, f, DUPE_INPUT)) {
189                                         iso = 0;
190                                         break;
191                                 }
192                         }
193
194                         if (iso) {
195                                 BM_ITER(e, &iter, source, BM_EDGES_OF_VERT, v) {
196                                         if (BMO_TestFlag(source, e, DUPE_INPUT)) {
197                                                 iso = 0;
198                                                 break;
199                                         }
200                                 }
201                         }
202                         
203                         if (iso) 
204                                 BMO_Insert_MapPointer(source, op, "isovertmap", v, v2);
205
206                         BMO_SetFlag(source, (BMHeader*)v, DUPE_DONE);
207                 }
208         }
209
210         /*now we dupe all the edges*/
211         for(e = BMIter_New(&edges, source, BM_EDGES_OF_MESH, source); e; e = BMIter_Step(&edges)){
212                 if(BMO_TestFlag(source, (BMHeader*)e, DUPE_INPUT) && (!BMO_TestFlag(source, (BMHeader*)e, DUPE_DONE))){
213                         /*make sure that verts are copied*/
214                         if(!BMO_TestFlag(source, (BMHeader*)e->v1, DUPE_DONE)) {
215                                 copy_vertex(source, e->v1, target, vhash);
216                                 BMO_SetFlag(source, (BMHeader*)e->v1, DUPE_DONE);
217                         }
218                         if(!BMO_TestFlag(source, (BMHeader*)e->v2, DUPE_DONE)) {
219                                 copy_vertex(source, e->v2, target, vhash);
220                                 BMO_SetFlag(source, (BMHeader*)e->v2, DUPE_DONE);
221                         }
222                         /*now copy the actual edge*/
223                         copy_edge(op, source, e, target,  vhash,  ehash);                       
224                         BMO_SetFlag(source, (BMHeader*)e, DUPE_DONE); 
225                 }
226         }
227
228         /*first we dupe all flagged faces and their elements from source*/
229         for(f = BMIter_New(&faces, source, BM_FACES_OF_MESH, source); f; f= BMIter_Step(&faces)){
230                 if(BMO_TestFlag(source, (BMHeader*)f, DUPE_INPUT)){
231                         /*vertex pass*/
232                         for(v = BMIter_New(&verts, source, BM_VERTS_OF_FACE, f); v; v = BMIter_Step(&verts)){
233                                 if(!BMO_TestFlag(source, (BMHeader*)v, DUPE_DONE)){ 
234                                         copy_vertex(source,v, target, vhash);
235                                         BMO_SetFlag(source, (BMHeader*)v, DUPE_DONE);
236                                 }
237                         }
238
239                         /*edge pass*/
240                         for(e = BMIter_New(&edges, source, BM_EDGES_OF_FACE, f); e; e = BMIter_Step(&edges)){
241                                 if(!BMO_TestFlag(source, (BMHeader*)e, DUPE_DONE)){
242                                         copy_edge(op, source, e, target,  vhash,  ehash);
243                                         BMO_SetFlag(source, (BMHeader*)e, DUPE_DONE);
244                                 }
245                         }
246                         copy_face(op, source, f, target, edar, vhash, ehash);
247                         BMO_SetFlag(source, (BMHeader*)f, DUPE_DONE);
248                 }
249         }
250         
251         /*free pointer hashes*/
252         BLI_ghash_free(vhash, NULL, NULL);
253         BLI_ghash_free(ehash, NULL, NULL);      
254
255         /*free edge pointer array*/
256         if(edar)
257                 MEM_freeN(edar);
258 }
259
260 /*
261 BMesh *bmesh_make_mesh_from_mesh(BMesh *bm, int allocsize[4])
262 {
263         BMesh *target = NULL;
264         target = bmesh_make_mesh(allocsize);
265         
266
267         CustomData_copy(&bm->vdata, &target->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
268         CustomData_copy(&bm->edata, &target->edata, CD_MASK_BMESH, CD_CALLOC, 0);
269         CustomData_copy(&bm->ldata, &target->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
270         CustomData_copy(&bm->pdata, &target->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
271         
272
273         CustomData_bmesh_init_pool(&target->vdata, allocsize[0]);
274         CustomData_bmesh_init_pool(&target->edata, allocsize[1]);
275         CustomData_bmesh_init_pool(&target->ldata, allocsize[2]);
276         CustomData_bmesh_init_pool(&target->pdata, allocsize[3]);
277         
278         bmesh_begin_edit(bm);
279         bmesh_begin_edit(target);
280         
281         bmesh_copy_mesh(bm, target, 0);
282
283         bmesh_end_edit(bm);
284         bmesh_end_edit(target);
285         
286         return target;
287
288 }
289 */
290
291 /*
292  * Duplicate Operator
293  *
294  * Duplicates verts, edges and faces of a mesh.
295  *
296  * INPUT SLOTS:
297  *
298  * BMOP_DUPE_VINPUT: Buffer containing pointers to mesh vertices to be duplicated
299  * BMOP_DUPE_EINPUT: Buffer containing pointers to mesh edges to be duplicated
300  * BMOP_DUPE_FINPUT: Buffer containing pointers to mesh faces to be duplicated
301  *
302  * OUTPUT SLOTS:
303  * 
304  * BMOP_DUPE_VORIGINAL: Buffer containing pointers to the original mesh vertices
305  * BMOP_DUPE_EORIGINAL: Buffer containing pointers to the original mesh edges
306  * BMOP_DUPE_FORIGINAL: Buffer containing pointers to the original mesh faces
307  * BMOP_DUPE_VNEW: Buffer containing pointers to the new mesh vertices
308  * BMOP_DUPE_ENEW: Buffer containing pointers to the new mesh edges
309  * BMOP_DUPE_FNEW: Buffer containing pointers to the new mesh faces
310  *
311 */
312
313 void dupeop_exec(BMesh *bm, BMOperator *op)
314 {
315         BMOperator *dupeop = op;
316         
317         /*flag input*/
318         BMO_Flag_Buffer(bm, dupeop, "geom", DUPE_INPUT, BM_ALL);
319
320         /*use the internal copy function*/
321         copy_mesh(dupeop, bm, bm);
322         
323         /*Output*/
324         /*First copy the input buffers to output buffers - original data*/
325         BMO_CopySlot(dupeop, dupeop, "geom", "origout");
326
327         /*Now alloc the new output buffers*/
328         BMO_Flag_To_Slot(bm, dupeop, "newout", DUPE_NEW, BM_ALL);
329 }
330
331 /*executes the duplicate operation, feeding elements of 
332   type flag etypeflag and header flag flag to it.  note,
333   to get more useful information (such as the mapping from
334   original to new elements) you should run the dupe op manually.*/
335 void BMOP_DupeFromFlag(BMesh *bm, int etypeflag, int flag)
336 {
337         BMOperator dupeop;
338
339         BMO_Init_Op(&dupeop, "dupe");
340         BMO_HeaderFlag_To_Slot(bm, &dupeop, "geom", flag, etypeflag);
341
342         BMO_Exec_Op(bm, &dupeop);
343         BMO_Finish_Op(bm, &dupeop);
344 }
345
346 /*
347  * Split Operator
348  *
349  * Duplicates verts, edges and faces of a mesh but also deletes the originals.
350  *
351  * INPUT SLOTS:
352  *
353  * BMOP_DUPE_VINPUT: Buffer containing pointers to mesh vertices to be split
354  * BMOP_DUPE_EINPUT: Buffer containing pointers to mesh edges to be split
355  * BMOP_DUPE_FINPUT: Buffer containing pointers to mesh faces to be split
356  *
357  * OUTPUT SLOTS:
358  * 
359  * BMOP_DUPE_VOUTPUT: Buffer containing pointers to the split mesh vertices
360  * BMOP_DUPE_EOUTPUT: Buffer containing pointers to the split mesh edges
361  * BMOP_DUPE_FOUTPUT: Buffer containing pointers to the split mesh faces
362  *
363 */
364
365 #define SPLIT_INPUT     1
366 void splitop_exec(BMesh *bm, BMOperator *op)
367 {
368         BMOperator *splitop = op;
369         BMOperator dupeop;
370         BMOperator delop;
371         BMVert *v;
372         BMEdge *e;
373         BMFace *f;
374         BMIter iter, iter2;
375         int found;
376
377         /*initialize our sub-operators*/
378         BMO_Init_Op(&dupeop, "dupe");
379         BMO_Init_Op(&delop, "del");
380         
381         BMO_CopySlot(splitop, &dupeop, "geom", "geom");
382         BMO_Exec_Op(bm, &dupeop);
383         
384         BMO_Flag_Buffer(bm, splitop, "geom", SPLIT_INPUT, BM_ALL);
385
386         /*make sure to remove edges and verts we don't need.*/
387         for (e= BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);e;e=BMIter_Step(&iter)) {
388                 found = 0;
389                 f = BMIter_New(&iter2, bm, BM_FACES_OF_EDGE, e);
390                 for (; f; f=BMIter_Step(&iter2)) {
391                         if (!BMO_TestFlag(bm, f, SPLIT_INPUT)) {
392                                 found = 1;
393                                 break;
394                         }
395                 }
396                 if (!found) BMO_SetFlag(bm, e, SPLIT_INPUT);
397         }
398         
399         for (v= BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);v;v=BMIter_Step(&iter)) {
400                 found = 0;
401                 e = BMIter_New(&iter2, bm, BM_EDGES_OF_VERT, v);
402                 for (; e; e=BMIter_Step(&iter2)) {
403                         if (!BMO_TestFlag(bm, e, SPLIT_INPUT)) {
404                                 found = 1;
405                                 break;
406                         }
407                 }
408                 if (!found) BMO_SetFlag(bm, v, SPLIT_INPUT);
409
410         }
411
412         /*connect outputs of dupe to delete, exluding keep geometry*/
413         BMO_Set_Int(&delop, "context", DEL_FACES);
414         BMO_Flag_To_Slot(bm, &delop, "geom", SPLIT_INPUT, BM_ALL);
415         
416         BMO_Exec_Op(bm, &delop);
417
418         /*now we make our outputs by copying the dupe outputs*/
419         BMO_CopySlot(&dupeop, splitop, "newout", "geom");
420         BMO_CopySlot(&dupeop, splitop, "boundarymap",
421                      "boundarymap");
422         BMO_CopySlot(&dupeop, splitop, "isovertmap",
423                      "isovertmap");
424         
425         /*cleanup*/
426         BMO_Finish_Op(bm, &delop);
427         BMO_Finish_Op(bm, &dupeop);
428 }
429
430 #define DEL_INPUT               1
431 #define DEL_WIREVERT    2
432
433 static void delete_verts(BMesh *bm);
434 static void delete_context(BMesh *bm, int type);
435
436 void delop_exec(BMesh *bm, BMOperator *op)
437 {
438         BMOperator *delop = op;
439
440         /*Mark Buffers*/
441         BMO_Flag_Buffer(bm, delop, "geom", DEL_INPUT, BM_ALL);
442
443         delete_context(bm, BMO_Get_Int(op, "context"));
444 }
445
446 static void delete_verts(BMesh *bm)
447 {
448         BMVert *v;
449         BMEdge *e;
450         BMLoop *f;
451         
452         BMIter verts;
453         BMIter edges;
454         BMIter faces;
455         
456         for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts)){
457                 if(BMO_TestFlag(bm, (BMHeader*)v, DEL_INPUT)) {
458                         /*Visit edges*/
459                         for(e = BMIter_New(&edges, bm, BM_EDGES_OF_VERT, v); e; e = BMIter_Step(&edges))
460                                 BMO_SetFlag(bm, (BMHeader*)e, DEL_INPUT);
461                         /*Visit faces*/
462                         for(f = BMIter_New(&faces, bm, BM_FACES_OF_VERT, v); f; f = BMIter_Step(&faces))
463                                 BMO_SetFlag(bm, (BMHeader*)f, DEL_INPUT);
464                 }
465         }
466
467         BM_remove_tagged_faces(bm, DEL_INPUT);
468         BM_remove_tagged_edges(bm, DEL_INPUT);
469         BM_remove_tagged_verts(bm, DEL_INPUT);
470 }
471
472 static void delete_edges(BMesh *bm){
473         BMEdge *e;
474         BMFace *f;
475         
476         BMIter edges;
477         BMIter faces;
478
479         for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges)){
480                 if(BMO_TestFlag(bm, (BMHeader*)e, DEL_INPUT)) {
481                         for(f = BMIter_New(&faces, bm, BM_FACES_OF_EDGE, e); f; f = BMIter_Step(&faces)){
482                                         BMO_SetFlag(bm, (BMHeader*)f, DEL_INPUT);
483                         }
484                 }
485         }
486         BM_remove_tagged_faces(bm, DEL_INPUT);
487         BM_remove_tagged_edges(bm, DEL_INPUT);
488 }
489
490 /*you need to make remove tagged verts/edges/faces
491         api functions that take a filter callback.....
492         and this new filter type will be for opstack flags.
493         This is because the BM_remove_taggedXXX functions bypass iterator API.
494                  -Ops dont care about 'UI' considerations like selection state, hide state, ect. If you want to work on unhidden selections for instance,
495                  copy output from a 'select context' operator to another operator....
496 */
497
498 /*Break this into smaller functions*/
499
500 static void delete_context(BMesh *bm, int type){
501         BMVert *v;
502         BMEdge *e;
503         BMFace *f;
504
505         BMIter verts;
506         BMIter edges;
507         BMIter faces;
508         
509         if(type == DEL_VERTS) delete_verts(bm);
510         else if(type == DEL_EDGES){
511                 /*flush down to verts*/
512                 for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges)){
513                         if(BMO_TestFlag(bm, (BMHeader*)e, DEL_INPUT)){
514                                 BMO_SetFlag(bm, (BMHeader*)(e->v1), DEL_INPUT);
515                                 BMO_SetFlag(bm, (BMHeader*)(e->v2), DEL_INPUT);
516                         }
517                 }
518                 delete_edges(bm);
519                 /*remove loose vertices*/
520                 for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts)){
521                         if(BMO_TestFlag(bm, (BMHeader*)v, DEL_INPUT) && (!(v->edge)))
522                                 BMO_SetFlag(bm, (BMHeader*)v, DEL_WIREVERT);
523                 }
524                 BM_remove_tagged_verts(bm, DEL_WIREVERT);
525         }
526         else if(type == DEL_EDGESFACES) delete_edges(bm);
527         else if(type == DEL_ONLYFACES) BM_remove_tagged_faces(bm, DEL_INPUT);
528         else if (type == DEL_ONLYTAGGED) {
529                 BM_remove_tagged_faces(bm, DEL_INPUT);
530                 BM_remove_tagged_edges(bm, DEL_INPUT);
531                 BM_remove_tagged_verts(bm, DEL_INPUT);
532         } else if(type == DEL_FACES){
533                 /*go through and mark all edges and all verts of all faces for delete*/
534                 for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces)){
535                         if(BMO_TestFlag(bm, (BMHeader*)f, DEL_INPUT)){
536                                 for(e = BMIter_New(&edges, bm, BM_EDGES_OF_FACE, f); e; e = BMIter_Step(&edges))
537                                         BMO_SetFlag(bm, (BMHeader*)e, DEL_INPUT);
538                                 for(v = BMIter_New(&verts, bm, BM_VERTS_OF_FACE, f); v; v = BMIter_Step(&verts))
539                                         BMO_SetFlag(bm, (BMHeader*)v, DEL_INPUT);
540                         }
541                 }
542                 /*now go through and mark all remaining faces all edges for keeping.*/
543                 for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces)){
544                         if(!BMO_TestFlag(bm, (BMHeader*)f, DEL_INPUT)){
545                                 for(e = BMIter_New(&edges, bm, BM_EDGES_OF_FACE, f); e; e= BMIter_Step(&edges))
546                                         BMO_ClearFlag(bm, (BMHeader*)e, DEL_INPUT);
547                                 for(v = BMIter_New(&verts, bm, BM_VERTS_OF_FACE, f); v; v= BMIter_Step(&verts))
548                                         BMO_ClearFlag(bm, (BMHeader*)v, DEL_INPUT);
549                         }
550                 }
551                 /*now delete marked faces*/
552                 BM_remove_tagged_faces(bm, DEL_INPUT);
553                 /*delete marked edges*/
554                 BM_remove_tagged_edges(bm, DEL_INPUT);
555                 /*remove loose vertices*/
556                 BM_remove_tagged_verts(bm, DEL_INPUT);
557         }
558         /*does this option even belong in here?*/
559         else if(type == DEL_ALL){
560                 for(f = BMIter_New(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BMIter_Step(&faces))
561                         BMO_SetFlag(bm, (BMHeader*)f, DEL_INPUT);
562                 for(e = BMIter_New(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BMIter_Step(&edges))
563                         BMO_SetFlag(bm, (BMHeader*)e, DEL_INPUT);
564                 for(v = BMIter_New(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BMIter_Step(&verts))
565                         BMO_SetFlag(bm, (BMHeader*)v, DEL_INPUT);
566                 
567                 BM_remove_tagged_faces(bm, DEL_INPUT);
568                 BM_remove_tagged_edges(bm, DEL_INPUT);
569                 BM_remove_tagged_verts(bm, DEL_INPUT);
570         }
571 }