bmesh minor refactor
[blender.git] / source / blender / bmesh / intern / bmesh_construct.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  * The Original Code is Copyright (C) 2007 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Geoffrey Bantle.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/bmesh/intern/bmesh_construct.c
29  *  \ingroup bmesh
30  *
31  * BM construction functions.
32  */
33
34 #include "MEM_guardedalloc.h"
35
36 #include "BLI_array.h"
37 #include "BLI_math.h"
38
39 #include "BKE_customdata.h"
40
41 #include "DNA_meshdata_types.h"
42
43 #include "bmesh.h"
44 #include "bmesh_private.h"
45
46 #define SELECT 1
47
48 /* prototypes */
49 static void bm_copy_loop_attributes(BMesh *source_mesh, BMesh *target_mesh,
50                                     const BMLoop *source_loop, BMLoop *target_loop);
51 #if 0
52
53 /*
54  * BM_CONSTRUCT.C
55  *
56  * This file contains functions for making and destroying
57  * individual elements like verts, edges and faces.
58  *
59  */
60
61 /*
62  * BMESH MAKE VERT
63  *
64  * Creates a new vertex and returns a pointer
65  * to it. If a pointer to an example vertex is
66  * passed in, it's custom data and properties
67  * will be copied to the new vertex.
68  *
69  */
70
71 BMVert *BM_vert_create(BMesh *bm, float co[3], BMVert *example)
72 {
73         BMVert *v = NULL;
74         v = bmesh_mv(bm, co);
75         if (example)
76                 CustomData_bmesh_copy_data(&bm->vdata, &bm->vdata, example->head.data, &v->head.data);
77         return v;
78 }
79
80 /*
81  * BMESH MAKE EDGE
82  *
83  * Creates a new edge betweeen two vertices and returns a
84  * pointer to it. If 'nodouble' equals 1, then a check is
85  * is done to make sure that an edge between those two vertices
86  * does not already exist. If it does, that edge is returned instead
87  * of creating a new one.
88  *
89  * If a new edge is created, and a pointer to an example edge is
90  * provided, it's custom data and properties will be copied to the
91  * new edge.
92  *
93  */
94
95 BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge *example, int nodouble)
96 {
97         BMEdge *e = NULL;
98         
99         if (nodouble) /* test if edge already exists. */
100                 e = BM_edge_exists(v1, v2);
101
102         if (!e) {
103                 e = bmesh_me(bm, v1, v2);
104
105                 if (example)
106                         CustomData_bmesh_copy_data(&bm->edata, &bm->edata, example->head.data, &e->head.data);
107         }
108         
109         return e;
110         
111 }
112 #endif
113
114 /*
115  * BMESH MAKE QUADTRIANGLE
116  *
117  * Creates a new quad or triangle from
118  * a list of 3 or 4 vertices. If nodouble
119  * equals 1, then a check is done to see
120  * if a face with these vertices already
121  * exists and returns it instead. If a pointer
122  * to an example face is provided, it's custom
123  * data and properties will be copied to the new
124  * face.
125  *
126  * Note that the winding of the face is determined
127  * by the order of the vertices in the vertex array
128  */
129
130 BMFace *BM_face_create_quad_tri(BMesh *bm,
131                                 BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
132                                 const BMFace *example, const int nodouble)
133 {
134         BMVert *vtar[4] = {v1, v2, v3, v4};
135         return BM_face_create_quad_tri_v(bm, vtar, v4 ? 4 : 3, example, nodouble);
136 }
137
138 /* remove the edge array bits from this. Its not really needed? */
139 BMFace *BM_face_create_quad_tri_v(BMesh *bm, BMVert **verts, int len, const BMFace *example, const int nodouble)
140 {
141         BMEdge *edar[4] = {NULL};
142         BMFace *f = NULL;
143         int overlap = 0;
144
145         edar[0] = BM_edge_exists(verts[0], verts[1]);
146         edar[1] = BM_edge_exists(verts[1], verts[2]);
147         if (len == 4) {
148                 edar[2] = BM_edge_exists(verts[2], verts[3]);
149                 edar[3] = BM_edge_exists(verts[3], verts[0]);
150         }
151         else {
152                 edar[2] = BM_edge_exists(verts[2], verts[0]);
153         }
154
155         if (nodouble) {
156                 /* check if face exists or overlaps */
157                 if (len == 4) {
158                         overlap = BM_face_exists_overlap(bm, verts, len, &f);
159                 }
160                 else {
161                         overlap = BM_face_exists_overlap(bm, verts, len, &f);
162                 }
163         }
164
165         /* make new face */
166         if ((!f) && (!overlap)) {
167                 if (!edar[0]) edar[0] = BM_edge_create(bm, verts[0], verts[1], NULL, FALSE);
168                 if (!edar[1]) edar[1] = BM_edge_create(bm, verts[1], verts[2], NULL, FALSE);
169                 if (len == 4) {
170                         if (!edar[2]) edar[2] = BM_edge_create(bm, verts[2], verts[3], NULL, FALSE);
171                         if (!edar[3]) edar[3] = BM_edge_create(bm, verts[3], verts[0], NULL, FALSE);
172                 }
173                 else {
174                         if (!edar[2]) edar[2] = BM_edge_create(bm, verts[2], verts[0], NULL, FALSE);
175                 }
176
177                 f = BM_face_create(bm, verts, edar, len, FALSE);
178
179                 if (example && f) {
180                         BM_elem_copy_attrs(bm, bm, example, f);
181                 }
182         }
183
184         return f;
185 }
186
187
188 /* copies face data from shared adjacent faces */
189 void BM_face_copy_shared(BMesh *bm, BMFace *f)
190 {
191         BMIter iter;
192         BMLoop *l, *l2;
193
194         if (!f) return;
195
196         l = BM_iter_new(&iter, bm, BM_LOOPS_OF_FACE, f);
197         for ( ; l; l = BM_iter_step(&iter)) {
198                 l2 = l->radial_next;
199                 
200                 if (l2 && l2 != l) {
201                         if (l2->v == l->v) {
202                                 bm_copy_loop_attributes(bm, bm, l2, l);
203                         }
204                         else {
205                                 l2 = l2->next;
206                                 bm_copy_loop_attributes(bm, bm, l2, l);
207                         }
208                 }
209         }
210 }
211
212 /*
213  * BMESH MAKE NGON
214  *
215  * Attempts to make a new Ngon from a list of edges.
216  * If nodouble equals one, a check for overlaps or existing
217  *
218  * The edges are not required to be ordered, simply to to form
219  * a single closed loop as a whole
220  *
221  * Note that while this function will work fine when the edges
222  * are already sorted, if the edges are always going to be sorted,
223  * BM_face_create should be considered over this function as it
224  * avoids some unnecessary work.
225  */
226 BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, int nodouble)
227 {
228         BMEdge **edges2 = NULL;
229         BLI_array_staticdeclare(edges2, BM_NGON_STACK_SIZE);
230         BMVert **verts = NULL, *v;
231         BLI_array_staticdeclare(verts, BM_NGON_STACK_SIZE);
232         BMFace *f = NULL;
233         BMEdge *e;
234         BMVert *ev1, *ev2;
235         int i, /* j, */ v1found, reverse;
236
237         /* this code is hideous, yeek.  I'll have to think about ways of
238          *  cleaning it up.  basically, it now combines the old BM_face_create_ngon
239          *  _and_ the old bmesh_mf functions, so its kindof smashed together
240          * - joeedh */
241
242         if (!len || !v1 || !v2 || !edges || !bm)
243                 return NULL;
244
245         /* put edges in correct order */
246         for (i = 0; i < len; i++) {
247                 bmesh_api_setflag(edges[i], _FLAG_MF);
248         }
249
250         ev1 = edges[0]->v1;
251         ev2 = edges[0]->v2;
252
253         if (v1 == ev2) {
254                 /* Swapping here improves performance and consistency of face
255                  * structure in the special case that the edges are already in
256                  * the correct order and winding */
257                 SWAP(BMVert *, ev1, ev2);
258         }
259
260         BLI_array_append(verts, ev1);
261         v = ev2;
262         e = edges[0];
263         do {
264                 BMEdge *e2 = e;
265
266                 BLI_array_append(verts, v);
267                 BLI_array_append(edges2, e);
268
269                 do {
270                         e2 = bmesh_disk_nextedge(e2, v);
271                         if (e2 != e && bmesh_api_getflag(e2, _FLAG_MF)) {
272                                 v = BM_edge_other_vert(e2, v);
273                                 break;
274                         }
275                 } while (e2 != e);
276
277                 if (e2 == e)
278                         goto err; /* the edges do not form a closed loop */
279
280                 e = e2;
281         } while (e != edges[0]);
282
283         if (BLI_array_count(edges2) != len) {
284                 goto err; /* we didn't use all edges in forming the boundary loop */
285         }
286
287         /* ok, edges are in correct order, now ensure they are going
288          * in the correct direction */
289         v1found = reverse = FALSE;
290         for (i = 0; i < len; i++) {
291                 if (BM_vert_in_edge(edges2[i], v1)) {
292                         /* see if v1 and v2 are in the same edge */
293                         if (BM_vert_in_edge(edges2[i], v2)) {
294                                 /* if v1 is shared by the *next* edge, then the winding
295                                  * is incorrect */
296                                 if (BM_vert_in_edge(edges2[(i + 1) % len], v1)) {
297                                         reverse = TRUE;
298                                         break;
299                                 }
300                         }
301
302                         v1found = TRUE;
303                 }
304
305                 if ((v1found == FALSE) && BM_vert_in_edge(edges2[i], v2)) {
306                         reverse = TRUE;
307                         break;
308                 }
309         }
310
311         if (reverse) {
312                 for (i = 0; i < len / 2; i++) {
313                         v = verts[i];
314                         verts[i] = verts[len - i - 1];
315                         verts[len - i - 1] = v;
316                 }
317         }
318
319         for (i = 0; i < len; i++) {
320                 edges2[i] = BM_edge_exists(verts[i], verts[(i + 1) % len]);
321                 if (!edges2[i]) {
322                         goto err;
323                 }
324         }
325
326         f = BM_face_create(bm, verts, edges2, len, nodouble);
327
328         /* clean up flags */
329         for (i = 0; i < len; i++) {
330                 bmesh_api_clearflag(edges2[i], _FLAG_MF);
331         }
332
333         BLI_array_free(verts);
334         BLI_array_free(edges2);
335
336         return f;
337
338 err:
339         for (i = 0; i < len; i++) {
340                 bmesh_api_clearflag(edges[i], _FLAG_MF);
341         }
342
343         BLI_array_free(verts);
344         BLI_array_free(edges2);
345
346         return NULL;
347 }
348
349
350 /* bmesh_make_face_from_face(BMesh *bm, BMFace *source, BMFace *target) */
351
352
353 /*
354  * REMOVE TAGGED XXX
355  *
356  * Called by operators to remove elements that they have marked for
357  * removal.
358  *
359  */
360
361 void BMO_remove_tagged_faces(BMesh *bm, const short oflag)
362 {
363         BMFace *f;
364         BMIter iter;
365
366         BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
367                 if (BMO_elem_flag_test(bm, f, oflag)) {
368                         BM_face_kill(bm, f);
369                 }
370         }
371 }
372
373 void BMO_remove_tagged_edges(BMesh *bm, const short oflag)
374 {
375         BMEdge *e;
376         BMIter iter;
377
378         BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
379                 if (BMO_elem_flag_test(bm, e, oflag)) {
380                         BM_edge_kill(bm, e);
381                 }
382         }
383 }
384
385 void BMO_remove_tagged_verts(BMesh *bm, const short oflag)
386 {
387         BMVert *v;
388         BMIter iter;
389
390         BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
391                 if (BMO_elem_flag_test(bm, v, oflag)) {
392                         BM_vert_kill(bm, v);
393                 }
394         }
395 }
396
397 /*************************************************************/
398 /* you need to make remove tagged verts/edges/faces
399  * api functions that take a filter callback.....
400  * and this new filter type will be for opstack flags.
401  * This is because the BM_remove_taggedXXX functions bypass iterator API.
402  *  - Ops dont care about 'UI' considerations like selection state, hide state, ect.
403  *    If you want to work on unhidden selections for instance,
404  *    copy output from a 'select context' operator to another operator....
405  */
406
407 static void bmo_remove_tagged_context_verts(BMesh *bm, const short oflag)
408 {
409         BMVert *v;
410         BMEdge *e;
411         BMLoop *f;
412
413         BMIter verts;
414         BMIter edges;
415         BMIter faces;
416
417         for (v = BM_iter_new(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BM_iter_step(&verts)) {
418                 if (BMO_elem_flag_test(bm, (BMHeader *)v, oflag)) {
419                         /* Visit edge */
420                         for (e = BM_iter_new(&edges, bm, BM_EDGES_OF_VERT, v); e; e = BM_iter_step(&edges))
421                                 BMO_elem_flag_set(bm, (BMHeader *)e, oflag);
422                         /* Visit face */
423                         for (f = BM_iter_new(&faces, bm, BM_FACES_OF_VERT, v); f; f = BM_iter_step(&faces))
424                                 BMO_elem_flag_set(bm, (BMHeader *)f, oflag);
425                 }
426         }
427
428         BMO_remove_tagged_faces(bm, oflag);
429         BMO_remove_tagged_edges(bm, oflag);
430         BMO_remove_tagged_verts(bm, oflag);
431 }
432
433 static void bmo_remove_tagged_context_edges(BMesh *bm, const short oflag)
434 {
435         BMEdge *e;
436         BMFace *f;
437
438         BMIter edges;
439         BMIter faces;
440
441         for (e = BM_iter_new(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BM_iter_step(&edges)) {
442                 if (BMO_elem_flag_test(bm, (BMHeader *)e, oflag)) {
443                         for (f = BM_iter_new(&faces, bm, BM_FACES_OF_EDGE, e); f; f = BM_iter_step(&faces)) {
444                                 BMO_elem_flag_set(bm, (BMHeader *)f, oflag);
445                         }
446                 }
447         }
448         BMO_remove_tagged_faces(bm, oflag);
449         BMO_remove_tagged_edges(bm, oflag);
450 }
451
452 #define DEL_WIREVERT    (1 << 10)
453
454 /* warning, oflag applies to different types in some contexts,
455  * not just the type being removed */
456 void BMO_remove_tagged_context(BMesh *bm, const short oflag, const int type)
457 {
458         BMVert *v;
459         BMEdge *e;
460         BMFace *f;
461
462         BMIter verts;
463         BMIter edges;
464         BMIter faces;
465
466         switch (type) {
467                 case DEL_VERTS:
468                 {
469                         bmo_remove_tagged_context_verts(bm, oflag);
470
471                         break;
472                 }
473                 case DEL_EDGES:
474                 {
475                         /* flush down to vert */
476                         for (e = BM_iter_new(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BM_iter_step(&edges)) {
477                                 if (BMO_elem_flag_test(bm, (BMHeader *)e, oflag)) {
478                                         BMO_elem_flag_set(bm, (BMHeader *)(e->v1), oflag);
479                                         BMO_elem_flag_set(bm, (BMHeader *)(e->v2), oflag);
480                                 }
481                         }
482                         bmo_remove_tagged_context_edges(bm, oflag);
483                         /* remove loose vertice */
484                         for (v = BM_iter_new(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BM_iter_step(&verts)) {
485                                 if (BMO_elem_flag_test(bm, (BMHeader *)v, oflag) && (!(v->e)))
486                                         BMO_elem_flag_set(bm, (BMHeader *)v, DEL_WIREVERT);
487                         }
488                         BMO_remove_tagged_verts(bm, DEL_WIREVERT);
489
490                         break;
491                 }
492                 case DEL_EDGESFACES:
493                 {
494                         bmo_remove_tagged_context_edges(bm, oflag);
495
496                         break;
497                 }
498                 case DEL_ONLYFACES:
499                 {
500                         BMO_remove_tagged_faces(bm, oflag);
501
502                         break;
503                 }
504                 case DEL_ONLYTAGGED:
505                 {
506                         BMO_remove_tagged_faces(bm, oflag);
507                         BMO_remove_tagged_edges(bm, oflag);
508                         BMO_remove_tagged_verts(bm, oflag);
509
510                         break;
511                 }
512                 case DEL_FACES:
513                 {
514                         /* go through and mark all edges and all verts of all faces for delet */
515                         for (f = BM_iter_new(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BM_iter_step(&faces)) {
516                                 if (BMO_elem_flag_test(bm, (BMHeader *)f, oflag)) {
517                                         for (e = BM_iter_new(&edges, bm, BM_EDGES_OF_FACE, f); e; e = BM_iter_step(&edges))
518                                                 BMO_elem_flag_set(bm, (BMHeader *)e, oflag);
519                                         for (v = BM_iter_new(&verts, bm, BM_VERTS_OF_FACE, f); v; v = BM_iter_step(&verts))
520                                                 BMO_elem_flag_set(bm, (BMHeader *)v, oflag);
521                                 }
522                         }
523                         /* now go through and mark all remaining faces all edges for keeping */
524                         for (f = BM_iter_new(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BM_iter_step(&faces)) {
525                                 if (!BMO_elem_flag_test(bm, (BMHeader *)f, oflag)) {
526                                         for (e = BM_iter_new(&edges, bm, BM_EDGES_OF_FACE, f); e; e = BM_iter_step(&edges)) {
527                                                 BMO_elem_flag_clear(bm, (BMHeader *)e, oflag);
528                                         }
529                                         for (v = BM_iter_new(&verts, bm, BM_VERTS_OF_FACE, f); v; v = BM_iter_step(&verts)) {
530                                                 BMO_elem_flag_clear(bm, (BMHeader *)v, oflag);
531                                         }
532                                 }
533                         }
534                         /* also mark all the vertices of remaining edges for keeping */
535                         for (e = BM_iter_new(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BM_iter_step(&edges)) {
536                                 if (!BMO_elem_flag_test(bm, (BMHeader *)e, oflag)) {
537                                         BMO_elem_flag_clear(bm, (BMHeader *)e->v1, oflag);
538                                         BMO_elem_flag_clear(bm, (BMHeader *)e->v2, oflag);
539                                 }
540                         }
541                         /* now delete marked face */
542                         BMO_remove_tagged_faces(bm, oflag);
543                         /* delete marked edge */
544                         BMO_remove_tagged_edges(bm, oflag);
545                         /* remove loose vertice */
546                         BMO_remove_tagged_verts(bm, oflag);
547
548                         break;
549                 }
550                 case DEL_ALL:
551                 {
552                         /* does this option even belong in here? */
553                         for (f = BM_iter_new(&faces, bm, BM_FACES_OF_MESH, bm); f; f = BM_iter_step(&faces))
554                                 BMO_elem_flag_set(bm, (BMHeader *)f, oflag);
555                         for (e = BM_iter_new(&edges, bm, BM_EDGES_OF_MESH, bm); e; e = BM_iter_step(&edges))
556                                 BMO_elem_flag_set(bm, (BMHeader *)e, oflag);
557                         for (v = BM_iter_new(&verts, bm, BM_VERTS_OF_MESH, bm); v; v = BM_iter_step(&verts))
558                                 BMO_elem_flag_set(bm, (BMHeader *)v, oflag);
559
560                         BMO_remove_tagged_faces(bm, oflag);
561                         BMO_remove_tagged_edges(bm, oflag);
562                         BMO_remove_tagged_verts(bm, oflag);
563
564                         break;
565                 }
566         }
567 }
568 /*************************************************************/
569
570
571
572
573
574
575
576 static void bm_copy_vert_attributes(BMesh *source_mesh, BMesh *target_mesh,
577                                     const BMVert *source_vertex, BMVert *target_vertex)
578 {
579         if ((source_mesh == target_mesh) && (source_vertex == target_vertex)) {
580                 return;
581         }
582         copy_v3_v3(target_vertex->no, source_vertex->no);
583         CustomData_bmesh_free_block(&target_mesh->vdata, &target_vertex->head.data);
584         CustomData_bmesh_copy_data(&source_mesh->vdata, &target_mesh->vdata,
585                                    source_vertex->head.data, &target_vertex->head.data);
586 }
587
588 static void bm_copy_edge_attributes(BMesh *source_mesh, BMesh *target_mesh,
589                                     const BMEdge *source_edge, BMEdge *target_edge)
590 {
591         if ((source_mesh == target_mesh) && (source_edge == target_edge)) {
592                 return;
593         }
594         CustomData_bmesh_free_block(&target_mesh->edata, &target_edge->head.data);
595         CustomData_bmesh_copy_data(&source_mesh->edata, &target_mesh->edata,
596                                    source_edge->head.data, &target_edge->head.data);
597 }
598
599 static void bm_copy_loop_attributes(BMesh *source_mesh, BMesh *target_mesh,
600                                     const BMLoop *source_loop, BMLoop *target_loop)
601 {
602         if ((source_mesh == target_mesh) && (source_loop == target_loop)) {
603                 return;
604         }
605         CustomData_bmesh_free_block(&target_mesh->ldata, &target_loop->head.data);
606         CustomData_bmesh_copy_data(&source_mesh->ldata, &target_mesh->ldata,
607                                    source_loop->head.data, &target_loop->head.data);
608 }
609
610 static void bm_copy_face_attributes(BMesh *source_mesh, BMesh *target_mesh,
611                                     const BMFace *source_face, BMFace *target_face)
612 {
613         if ((source_mesh == target_mesh) && (source_face == target_face)) {
614                 return;
615         }
616         copy_v3_v3(target_face->no, source_face->no);
617         CustomData_bmesh_free_block(&target_mesh->pdata, &target_face->head.data);
618         CustomData_bmesh_copy_data(&source_mesh->pdata, &target_mesh->pdata,
619                                    source_face->head.data, &target_face->head.data);
620         target_face->mat_nr = source_face->mat_nr;
621 }
622
623 /* BMESH_TODO: Special handling for hide flags? */
624
625 void BM_elem_copy_attrs(BMesh *source_mesh, BMesh *target_mesh, const void *source, void *target)
626 {
627         const BMHeader *sheader = source;
628         BMHeader *theader = target;
629         
630         if (sheader->htype != theader->htype)
631                 return;
632
633         /* First we copy select */
634         if (BM_elem_select_test(source_mesh, source)) BM_elem_select_set(target_mesh, target, TRUE);
635         
636         /* Now we copy flags */
637         theader->hflag = sheader->hflag;
638         
639         /* Copy specific attributes */
640         if (theader->htype == BM_VERT)
641                 bm_copy_vert_attributes(source_mesh, target_mesh, (const BMVert *)source, (BMVert *)target);
642         else if (theader->htype == BM_EDGE)
643                 bm_copy_edge_attributes(source_mesh, target_mesh, (const BMEdge *)source, (BMEdge *)target);
644         else if (theader->htype == BM_LOOP)
645                 bm_copy_loop_attributes(source_mesh, target_mesh, (const BMLoop *)source, (BMLoop *)target);
646         else if (theader->htype == BM_FACE)
647                 bm_copy_face_attributes(source_mesh, target_mesh, (const BMFace *)source, (BMFace *)target);
648 }
649
650 BMesh *BM_mesh_copy(BMesh *bmold)
651 {
652         BMesh *bm;
653         BMVert *v, *v2, **vtable = NULL;
654         BMEdge *e, *e2, **edges = NULL, **etable = NULL;
655         BLI_array_declare(edges);
656         BMLoop *l, /* *l2, */ **loops = NULL;
657         BLI_array_declare(loops);
658         BMFace *f, *f2, **ftable = NULL;
659         BMEditSelection *ese;
660         BMIter iter, liter;
661         int i, j;
662
663         /* allocate a bmesh */
664         bm = BM_mesh_create(bmold->ob, bm_mesh_allocsize_default);
665
666         CustomData_copy(&bmold->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
667         CustomData_copy(&bmold->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
668         CustomData_copy(&bmold->ldata, &bm->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
669         CustomData_copy(&bmold->pdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
670
671         CustomData_bmesh_init_pool(&bm->vdata, bm_mesh_allocsize_default[0]);
672         CustomData_bmesh_init_pool(&bm->edata, bm_mesh_allocsize_default[1]);
673         CustomData_bmesh_init_pool(&bm->ldata, bm_mesh_allocsize_default[2]);
674         CustomData_bmesh_init_pool(&bm->pdata, bm_mesh_allocsize_default[3]);
675
676         vtable = MEM_mallocN(sizeof(BMVert *) * bmold->totvert, "BM_mesh_copy vtable");
677         etable = MEM_mallocN(sizeof(BMEdge *) * bmold->totedge, "BM_mesh_copy etable");
678         ftable = MEM_mallocN(sizeof(BMFace *) * bmold->totface, "BM_mesh_copy ftable");
679
680         v = BM_iter_new(&iter, bmold, BM_VERTS_OF_MESH, NULL);
681         for (i = 0; v; v = BM_iter_step(&iter), i++) {
682                 v2 = BM_vert_create(bm, v->co, NULL); /* copy between meshes so cant use 'example' argument */
683                 BM_elem_copy_attrs(bmold, bm, v, v2);
684                 vtable[i] = v2;
685                 BM_elem_index_set(v, i); /* set_inline */
686                 BM_elem_index_set(v2, i); /* set_inline */
687         }
688         bmold->elem_index_dirty &= ~BM_VERT;
689         bm->elem_index_dirty &= ~BM_VERT;
690
691         /* safety check */
692         BLI_assert(i == bmold->totvert);
693         
694         e = BM_iter_new(&iter, bmold, BM_EDGES_OF_MESH, NULL);
695         for (i = 0; e; e = BM_iter_step(&iter), i++) {
696                 e2 = BM_edge_create(bm,
697                                     vtable[BM_elem_index_get(e->v1)],
698                                     vtable[BM_elem_index_get(e->v2)],
699                                     e, FALSE);
700
701                 BM_elem_copy_attrs(bmold, bm, e, e2);
702                 etable[i] = e2;
703                 BM_elem_index_set(e, i); /* set_inline */
704                 BM_elem_index_set(e2, i); /* set_inline */
705         }
706         bmold->elem_index_dirty &= ~BM_EDGE;
707         bm->elem_index_dirty &= ~BM_EDGE;
708
709         /* safety check */
710         BLI_assert(i == bmold->totedge);
711         
712         f = BM_iter_new(&iter, bmold, BM_FACES_OF_MESH, NULL);
713         for (i = 0; f; f = BM_iter_step(&iter), i++) {
714                 BM_elem_index_set(f, i); /* set_inline */
715
716                 BLI_array_empty(loops);
717                 BLI_array_empty(edges);
718                 BLI_array_growitems(loops, f->len);
719                 BLI_array_growitems(edges, f->len);
720
721                 l = BM_iter_new(&liter, bmold, BM_LOOPS_OF_FACE, f);
722                 for (j = 0; j < f->len; j++, l = BM_iter_step(&liter)) {
723                         loops[j] = l;
724                         edges[j] = etable[BM_elem_index_get(l->e)];
725                 }
726
727                 v = vtable[BM_elem_index_get(loops[0]->v)];
728                 v2 = vtable[BM_elem_index_get(loops[1]->v)];
729
730                 if (!bmesh_verts_in_edge(v, v2, edges[0])) {
731                         v = vtable[BM_elem_index_get(loops[BLI_array_count(loops) - 1]->v)];
732                         v2 = vtable[BM_elem_index_get(loops[0]->v)];
733                 }
734
735                 f2 = BM_face_create_ngon(bm, v, v2, edges, f->len, FALSE);
736                 if (!f2)
737                         continue;
738                 /* use totface incase adding some faces fails */
739                 BM_elem_index_set(f2, (bm->totface - 1)); /* set_inline */
740
741                 ftable[i] = f2;
742
743                 BM_elem_copy_attrs(bmold, bm, f, f2);
744                 copy_v3_v3(f2->no, f->no);
745
746                 l = BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, f2);
747                 for (j = 0; j < f->len; j++, l = BM_iter_step(&liter)) {
748                         BM_elem_copy_attrs(bmold, bm, loops[j], l);
749                 }
750
751                 if (f == bmold->act_face) bm->act_face = f2;
752         }
753         bmold->elem_index_dirty &= ~BM_FACE;
754         bm->elem_index_dirty &= ~BM_FACE;
755
756         /* safety check */
757         BLI_assert(i == bmold->totface);
758
759         /* copy over edit selection history */
760         for (ese = bmold->selected.first; ese; ese = ese->next) {
761                 void *ele = NULL;
762
763                 if (ese->htype == BM_VERT)
764                         ele = vtable[BM_elem_index_get(ese->data)];
765                 else if (ese->htype == BM_EDGE)
766                         ele = etable[BM_elem_index_get(ese->data)];
767                 else if (ese->htype == BM_FACE) {
768                         ele = ftable[BM_elem_index_get(ese->data)];
769                 }
770                 else {
771                         BLI_assert(0);
772                 }
773                 
774                 if (ele)
775                         BM_select_history_store(bm, ele);
776         }
777
778         MEM_freeN(etable);
779         MEM_freeN(vtable);
780         MEM_freeN(ftable);
781
782         BLI_array_free(loops);
783         BLI_array_free(edges);
784
785         return bm;
786 }
787
788 /* ME -> BM */
789 char BM_vert_flag_from_mflag(const char  meflag)
790 {
791         return ( ((meflag & SELECT)       ? BM_ELEM_SELECT : 0) |
792                  ((meflag & ME_HIDE)      ? BM_ELEM_HIDDEN : 0)
793                  );
794 }
795 char BM_edge_flag_from_mflag(const short meflag)
796 {
797         return ( ((meflag & SELECT)       ? BM_ELEM_SELECT : 0) |
798                  ((meflag & ME_SEAM)      ? BM_ELEM_SEAM   : 0) |
799                  ((meflag & ME_SHARP)     ? BM_ELEM_SHARP  : 0) |
800                  ((meflag & ME_HIDE)      ? BM_ELEM_HIDDEN : 0)
801                  );
802 }
803 char BM_face_flag_from_mflag(const char  meflag)
804 {
805         return ( ((meflag & ME_FACE_SEL)  ? BM_ELEM_SELECT : 0) |
806                  ((meflag & ME_SMOOTH)    ? BM_ELEM_SMOOTH : 0) |
807                  ((meflag & ME_HIDE)      ? BM_ELEM_HIDDEN : 0)
808                  );
809 }
810
811 /* BM -> ME */
812 char  BM_vert_flag_to_mflag(BMVert *eve)
813 {
814         const char hflag = eve->head.hflag;
815
816         return ( ((hflag & BM_ELEM_SELECT)  ? SELECT  : 0) |
817                  ((hflag & BM_ELEM_HIDDEN)  ? ME_HIDE : 0)
818                  );
819 }
820 short BM_edge_flag_to_mflag(BMEdge *eed)
821 {
822         const char hflag = eed->head.hflag;
823
824         return ( ((hflag & BM_ELEM_SELECT)       ? SELECT    : 0) |
825                  ((hflag & BM_ELEM_SEAM)         ? ME_SEAM   : 0) |
826                  ((hflag & BM_ELEM_SHARP)        ? ME_SHARP  : 0) |
827                  ((hflag & BM_ELEM_HIDDEN)       ? ME_HIDE   : 0) |
828                  ((BM_edge_is_wire(NULL, eed)) ? ME_LOOSEEDGE : 0) | /* not typical */
829                  (ME_EDGEDRAW | ME_EDGERENDER)
830                  );
831 }
832 char  BM_face_flag_to_mflag(BMFace *efa)
833 {
834         const char hflag = efa->head.hflag;
835
836         return ( ((hflag & BM_ELEM_SELECT) ? ME_FACE_SEL : 0) |
837                  ((hflag & BM_ELEM_SMOOTH) ? ME_SMOOTH   : 0) |
838                  ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE     : 0)
839                  );
840 }