synched with trunk at revision 34793
[blender.git] / source / blender / editors / mesh / mesh_data.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2009 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include <math.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include "MEM_guardedalloc.h"
34
35 #include "DNA_material_types.h"
36 #include "DNA_meshdata_types.h"
37 #include "DNA_object_types.h"
38 #include "DNA_scene_types.h"
39 #include "DNA_view3d_types.h"
40
41 #include "BKE_context.h"
42 #include "BKE_depsgraph.h"
43 #include "BKE_displist.h"
44 #include "BKE_image.h"
45 #include "BKE_library.h"
46 #include "BKE_material.h"
47 #include "BKE_mesh.h"
48 #include "BKE_report.h"
49
50 #include "BLI_math.h"
51 #include "BLI_editVert.h"
52 #include "BLI_edgehash.h"
53
54 #include "RNA_access.h"
55 #include "RNA_define.h"
56
57 #include "WM_api.h"
58 #include "WM_types.h"
59
60 #include "ED_mesh.h"
61 #include "ED_object.h"
62 #include "ED_uvedit.h"
63 #include "ED_view3d.h"
64
65 #include "RE_render_ext.h"
66
67 #include "mesh_intern.h"
68
69 static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *layer)
70 {
71         Mesh *me = ob->data;
72         CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
73         void *actlayerdata, *rndlayerdata, *clonelayerdata, *stencillayerdata, *layerdata=layer->data;
74         int type= layer->type;
75         int index= CustomData_get_layer_index(data, type);
76         int i, actindex, rndindex, cloneindex, stencilindex;
77         
78         /* ok, deleting a non-active layer needs to preserve the active layer indices.
79           to do this, we store a pointer to the .data member of both layer and the active layer,
80           (to detect if we're deleting the active layer or not), then use the active
81           layer data pointer to find where the active layer has ended up.
82           
83           this is necassary because the deletion functions only support deleting the active
84           layer. */
85         actlayerdata = data->layers[CustomData_get_active_layer_index(data, type)].data;
86         rndlayerdata = data->layers[CustomData_get_render_layer_index(data, type)].data;
87         clonelayerdata = data->layers[CustomData_get_clone_layer_index(data, type)].data;
88         stencillayerdata = data->layers[CustomData_get_stencil_layer_index(data, type)].data;
89         CustomData_set_layer_active(data, type, layer - &data->layers[index]);
90
91         if(me->edit_mesh) {
92                 EM_free_data_layer(me->edit_mesh, data, type);
93         }
94         else {
95                 CustomData_free_layer_active(data, type, me->totface);
96                 mesh_update_customdata_pointers(me);
97         }
98
99         if(!CustomData_has_layer(data, type) && (type == CD_MCOL && (ob->mode & OB_MODE_VERTEX_PAINT)))
100                 ED_object_toggle_modes(C, OB_MODE_VERTEX_PAINT);
101
102         /* reconstruct active layer */
103         if (actlayerdata != layerdata) {
104                 /* find index */
105                 actindex = CustomData_get_layer_index(data, type);
106                 for (i=actindex; i<data->totlayer; i++) {
107                         if (data->layers[i].data == actlayerdata) {
108                                 actindex = i - actindex;
109                                 break;
110                         }
111                 }
112                 
113                 /* set index */
114                 CustomData_set_layer_active(data, type, actindex);
115         }
116         
117         if (rndlayerdata != layerdata) {
118                 /* find index */
119                 rndindex = CustomData_get_layer_index(data, type);
120                 for (i=rndindex; i<data->totlayer; i++) {
121                         if (data->layers[i].data == rndlayerdata) {
122                                 rndindex = i - rndindex;
123                                 break;
124                         }
125                 }
126                 
127                 /* set index */
128                 CustomData_set_layer_render(data, type, rndindex);
129         }
130         
131         if (clonelayerdata != layerdata) {
132                 /* find index */
133                 cloneindex = CustomData_get_layer_index(data, type);
134                 for (i=cloneindex; i<data->totlayer; i++) {
135                         if (data->layers[i].data == clonelayerdata) {
136                                 cloneindex = i - cloneindex;
137                                 break;
138                         }
139                 }
140                 
141                 /* set index */
142                 CustomData_set_layer_clone(data, type, cloneindex);
143         }
144         
145         if (stencillayerdata != layerdata) {
146                 /* find index */
147                 stencilindex = CustomData_get_layer_index(data, type);
148                 for (i=stencilindex; i<data->totlayer; i++) {
149                         if (data->layers[i].data == stencillayerdata) {
150                                 stencilindex = i - stencilindex;
151                                 break;
152                         }
153                 }
154                 
155                 /* set index */
156                 CustomData_set_layer_stencil(data, type, stencilindex);
157         }
158 }
159
160 int ED_mesh_uv_texture_add(bContext *C, Scene *scene, Object *ob, Mesh *me, const char *name, int active_set)
161 {
162         EditMesh *em;
163         int layernum;
164
165         if(me->edit_mesh) {
166                 em= me->edit_mesh;
167
168                 layernum= CustomData_number_of_layers(&em->fdata, CD_MTFACE);
169                 if(layernum >= MAX_MTFACE)
170                         return 0;
171
172                 EM_add_data_layer(em, &em->fdata, CD_MTFACE, name);
173                 if(active_set || layernum==0)
174                         CustomData_set_layer_active(&em->fdata, CD_MTFACE, layernum);
175         }
176         else {
177                 layernum= CustomData_number_of_layers(&me->fdata, CD_MTFACE);
178                 if(layernum >= MAX_MTFACE)
179                         return 0;
180
181                 if(me->mtface)
182                         CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_DUPLICATE, me->mtface, me->totface, name);
183                 else
184                         CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_DEFAULT, NULL, me->totface, name);
185
186                 if(active_set || layernum==0)
187                         CustomData_set_layer_active(&me->fdata, CD_MTFACE, layernum);
188
189                 mesh_update_customdata_pointers(me);
190         }
191
192         DAG_id_flush_update(&me->id, OB_RECALC_DATA);
193         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
194
195         return 1;
196 }
197
198 int ED_mesh_uv_texture_remove(bContext *C, Object *ob, Mesh *me)
199 {
200         CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
201         CustomDataLayer *cdl;
202         int index;
203
204         index= CustomData_get_active_layer_index(data, CD_MTFACE);
205         cdl= (index == -1) ? NULL: &data->layers[index];
206
207         if(!cdl)
208                 return 0;
209
210         delete_customdata_layer(C, ob, cdl);
211         DAG_id_flush_update(&me->id, OB_RECALC_DATA);
212         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
213
214         return 1;
215 }
216
217 int ED_mesh_color_add(bContext *C, Scene *scene, Object *ob, Mesh *me, const char *name, int active_set)
218 {
219         EditMesh *em;
220         MCol *mcol;
221         int layernum;
222
223         if(me->edit_mesh) {
224                 em= me->edit_mesh;
225
226                 layernum= CustomData_number_of_layers(&em->fdata, CD_MCOL);
227                 if(layernum >= MAX_MCOL)
228                         return 0;
229
230                 EM_add_data_layer(em, &em->fdata, CD_MCOL, name);
231                 if(active_set || layernum==0)
232                         CustomData_set_layer_active(&em->fdata, CD_MCOL, layernum);
233         }
234         else {
235                 layernum= CustomData_number_of_layers(&me->fdata, CD_MCOL);
236                 if(layernum >= MAX_MCOL)
237                         return 0;
238
239                 mcol= me->mcol;
240
241                 if(me->mcol)
242                         CustomData_add_layer_named(&me->fdata, CD_MCOL, CD_DUPLICATE, me->mcol, me->totface, name);
243                 else
244                         CustomData_add_layer_named(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface, name);
245
246                 if(active_set || layernum==0)
247                         CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum);
248
249                 mesh_update_customdata_pointers(me);
250
251                 if(!mcol)
252                         shadeMeshMCol(scene, ob, me);
253         }
254
255         DAG_id_flush_update(&me->id, OB_RECALC_DATA);
256         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
257
258         return 1;
259 }
260
261 int ED_mesh_color_remove(bContext *C, Object *ob, Mesh *me)
262 {
263         CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
264         CustomDataLayer *cdl;
265         int index;
266
267          index= CustomData_get_active_layer_index(data, CD_MCOL);
268         cdl= (index == -1)? NULL: &data->layers[index];
269
270         if(!cdl)
271                 return 0;
272
273         delete_customdata_layer(C, ob, cdl);
274         DAG_id_flush_update(&me->id, OB_RECALC_DATA);
275         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
276
277         return 1;
278 }
279
280 /*********************** UV texture operators ************************/
281
282 static int layers_poll(bContext *C)
283 {
284         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
285         ID *data= (ob)? ob->data: NULL;
286         return (ob && !ob->id.lib && ob->type==OB_MESH && data && !data->lib);
287 }
288
289 static int uv_texture_add_exec(bContext *C, wmOperator *op)
290 {
291         Scene *scene= CTX_data_scene(C);
292         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
293         Mesh *me= ob->data;
294
295         if(!ED_mesh_uv_texture_add(C, scene, ob, me, NULL, TRUE))
296                 return OPERATOR_CANCELLED;
297
298         return OPERATOR_FINISHED;
299 }
300
301 void MESH_OT_uv_texture_add(wmOperatorType *ot)
302 {
303         /* identifiers */
304         ot->name= "Add UV Texture";
305         ot->description= "Add UV texture layer";
306         ot->idname= "MESH_OT_uv_texture_add";
307         
308         /* api callbacks */
309         ot->poll= layers_poll;
310         ot->exec= uv_texture_add_exec;
311
312         /* flags */
313         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
314 }
315
316 static int drop_named_image_invoke(bContext *C, wmOperator *op, wmEvent *event)
317 {
318         Scene *scene= CTX_data_scene(C);
319         Base *base= ED_view3d_give_base_under_cursor(C, event->mval);
320         Image *ima= NULL;
321         Mesh *me;
322         Object *obedit;
323         int exitmode= 0;
324         char name[32];
325         
326         /* Check context */
327         if(base==NULL || base->object->type!=OB_MESH) {
328                 BKE_report(op->reports, RPT_ERROR, "Not an Object or Mesh");
329                 return OPERATOR_CANCELLED;
330         }
331         
332         /* check input variables */
333         if(RNA_property_is_set(op->ptr, "filepath")) {
334                 char path[FILE_MAX];
335                 
336                 RNA_string_get(op->ptr, "filepath", path);
337                 ima= BKE_add_image_file(path, 
338                                                                 scene ? scene->r.cfra : 1);
339         }
340         else {
341                 RNA_string_get(op->ptr, "name", name);
342                 ima= (Image *)find_id("IM", name);
343         }
344         
345         if(!ima) {
346                 BKE_report(op->reports, RPT_ERROR, "Not an Image.");
347                 return OPERATOR_CANCELLED;
348         }
349         
350         /* turn mesh in editmode */
351         /* BKE_mesh_get/end_editmesh: ED_uvedit_assign_image also calls this */
352
353         obedit= base->object;
354         me= obedit->data;
355         if(me->edit_mesh==NULL) {
356                 make_editMesh(scene, obedit);
357                 exitmode= 1;
358         }
359         if(me->edit_mesh==NULL)
360                 return OPERATOR_CANCELLED;
361         
362         ED_uvedit_assign_image(scene, obedit, ima, NULL);
363
364         if(exitmode) {
365                 load_editMesh(scene, obedit);
366                 free_editMesh(me->edit_mesh);
367                 MEM_freeN(me->edit_mesh);
368                 me->edit_mesh= NULL;
369         }
370
371         WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
372         
373         return OPERATOR_FINISHED;
374 }
375
376 void MESH_OT_drop_named_image(wmOperatorType *ot)
377 {
378         /* identifiers */
379         ot->name= "Assign Image to UV Texture";
380         ot->description= "Assigns Image to active UV layer, or creates a UV layer";
381         ot->idname= "MESH_OT_drop_named_image";
382         
383         /* api callbacks */
384         ot->poll= layers_poll;
385         ot->invoke= drop_named_image_invoke;
386         
387         /* flags */
388         ot->flag= OPTYPE_UNDO;
389         
390         /* properties */
391         RNA_def_string(ot->srna, "name", "Image", 24, "Name", "Image name to assign.");
392         RNA_def_string(ot->srna, "filepath", "Path", FILE_MAX, "Filepath", "Path to image file");
393 }
394
395 static int uv_texture_remove_exec(bContext *C, wmOperator *op)
396 {
397         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
398         Mesh *me= ob->data;
399
400         if(!ED_mesh_uv_texture_remove(C, ob, me))
401                 return OPERATOR_CANCELLED;
402
403         return OPERATOR_FINISHED;
404 }
405
406 void MESH_OT_uv_texture_remove(wmOperatorType *ot)
407 {
408         /* identifiers */
409         ot->name= "Remove UV Texture";
410         ot->description= "Remove UV texture layer";
411         ot->idname= "MESH_OT_uv_texture_remove";
412         
413         /* api callbacks */
414         ot->poll= layers_poll;
415         ot->exec= uv_texture_remove_exec;
416
417         /* flags */
418         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
419 }
420
421 /*********************** vertex color operators ************************/
422
423 static int vertex_color_add_exec(bContext *C, wmOperator *op)
424 {
425         Scene *scene= CTX_data_scene(C);
426         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
427         Mesh *me= ob->data;
428
429         if(!ED_mesh_color_add(C, scene, ob, me, NULL, TRUE))
430                 return OPERATOR_CANCELLED;
431
432         return OPERATOR_FINISHED;
433 }
434
435 void MESH_OT_vertex_color_add(wmOperatorType *ot)
436 {
437         /* identifiers */
438         ot->name= "Add Vertex Color";
439         ot->description= "Add vertex color layer";
440         ot->idname= "MESH_OT_vertex_color_add";
441         
442         /* api callbacks */
443         ot->poll= layers_poll;
444         ot->exec= vertex_color_add_exec;
445
446         /* flags */
447         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
448 }
449
450 static int vertex_color_remove_exec(bContext *C, wmOperator *op)
451 {
452         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
453         Mesh *me= ob->data;
454
455         if(!ED_mesh_color_remove(C, ob, me))
456                 return OPERATOR_CANCELLED;
457
458         return OPERATOR_FINISHED;
459 }
460
461 void MESH_OT_vertex_color_remove(wmOperatorType *ot)
462 {
463         /* identifiers */
464         ot->name= "Remove Vertex Color";
465         ot->description= "Remove vertex color layer";
466         ot->idname= "MESH_OT_vertex_color_remove";
467         
468         /* api callbacks */
469         ot->exec= vertex_color_remove_exec;
470         ot->poll= layers_poll;
471
472         /* flags */
473         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
474 }
475
476 /*********************** sticky operators ************************/
477
478 static int sticky_add_exec(bContext *C, wmOperator *op)
479 {
480         Scene *scene= CTX_data_scene(C);
481         View3D *v3d= CTX_wm_view3d(C);
482         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
483         Mesh *me= ob->data;
484
485         /*if(me->msticky)
486                 return OPERATOR_CANCELLED;*/
487
488         RE_make_sticky(scene, v3d);
489
490         DAG_id_flush_update(&me->id, OB_RECALC_DATA);
491         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
492
493         return OPERATOR_FINISHED;
494 }
495
496 void MESH_OT_sticky_add(wmOperatorType *ot)
497 {
498         /* identifiers */
499         ot->name= "Add Sticky";
500         ot->description= "Add sticky UV texture layer";
501         ot->idname= "MESH_OT_sticky_add";
502         
503         /* api callbacks */
504         ot->poll= layers_poll;
505         ot->exec= sticky_add_exec;
506
507         /* flags */
508         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
509 }
510
511 static int sticky_remove_exec(bContext *C, wmOperator *op)
512 {
513         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
514         Mesh *me= ob->data;
515
516         if(!me->msticky)
517                 return OPERATOR_CANCELLED;
518
519         CustomData_free_layer_active(&me->vdata, CD_MSTICKY, me->totvert);
520         me->msticky= NULL;
521
522         DAG_id_flush_update(&me->id, OB_RECALC_DATA);
523         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
524
525         return OPERATOR_FINISHED;
526 }
527
528 void MESH_OT_sticky_remove(wmOperatorType *ot)
529 {
530         /* identifiers */
531         ot->name= "Remove Sticky";
532         ot->description= "Remove sticky UV texture layer";
533         ot->idname= "MESH_OT_sticky_remove";
534         
535         /* api callbacks */
536         ot->poll= layers_poll;
537         ot->exec= sticky_remove_exec;
538
539         /* flags */
540         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
541 }
542
543 /************************** Add Geometry Layers *************************/
544
545 static void mesh_calc_edges(Mesh *mesh, int update)
546 {
547         CustomData edata;
548         EdgeHashIterator *ehi;
549         MFace *mf = mesh->mface;
550         MEdge *med, *med_orig;
551         EdgeHash *eh = BLI_edgehash_new();
552         int i, totedge, totface = mesh->totface;
553
554         if(mesh->totedge==0)
555                 update= 0;
556
557         if(update) {
558                 /* assume existing edges are valid
559                  * useful when adding more faces and generating edges from them */
560                 med= mesh->medge;
561                 for(i= 0; i<mesh->totedge; i++, med++)
562                         BLI_edgehash_insert(eh, med->v1, med->v2, med);
563         }
564
565         for (i = 0; i < totface; i++, mf++) {
566                 if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
567                         BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
568                 if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
569                         BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
570                 
571                 if (mf->v4) {
572                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
573                                 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
574                         if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
575                                 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
576                 } else {
577                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
578                                 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
579                 }
580         }
581
582         totedge = BLI_edgehash_size(eh);
583
584         /* write new edges into a temporary CustomData */
585         memset(&edata, 0, sizeof(edata));
586         CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
587
588         ehi = BLI_edgehashIterator_new(eh);
589         med = CustomData_get_layer(&edata, CD_MEDGE);
590         for(i = 0; !BLI_edgehashIterator_isDone(ehi);
591                 BLI_edgehashIterator_step(ehi), ++i, ++med) {
592
593                 if(update && (med_orig=BLI_edgehashIterator_getValue(ehi))) {
594                         *med= *med_orig; /* copy from the original */
595                 } else {
596                         BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
597                         med->flag = ME_EDGEDRAW|ME_EDGERENDER;
598                 }
599         }
600         BLI_edgehashIterator_free(ehi);
601
602         /* free old CustomData and assign new one */
603         CustomData_free(&mesh->edata, mesh->totedge);
604         mesh->edata = edata;
605         mesh->totedge = totedge;
606
607         mesh->medge = CustomData_get_layer(&mesh->edata, CD_MEDGE);
608
609         BLI_edgehash_free(eh, NULL);
610 }
611
612 void ED_mesh_update(Mesh *mesh, bContext *C, int calc_edges)
613 {
614         if(calc_edges || (mesh->totface && mesh->totedge == 0))
615                 mesh_calc_edges(mesh, calc_edges);
616
617         mesh_calc_normals(mesh->mvert, mesh->totvert, mesh->mface, mesh->totface, NULL);
618
619         DAG_id_flush_update(&mesh->id, OB_RECALC_DATA);
620         WM_event_add_notifier(C, NC_GEOM|ND_DATA, mesh);
621 }
622
623 static void mesh_add_verts(Mesh *mesh, int len)
624 {
625         CustomData vdata;
626         MVert *mvert;
627         int i, totvert;
628
629         if(len == 0)
630                 return;
631
632         totvert= mesh->totvert + len;
633         CustomData_copy(&mesh->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert);
634         CustomData_copy_data(&mesh->vdata, &vdata, 0, 0, mesh->totvert);
635
636         if(!CustomData_has_layer(&vdata, CD_MVERT))
637                 CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
638
639         CustomData_free(&mesh->vdata, mesh->totvert);
640         mesh->vdata= vdata;
641         mesh_update_customdata_pointers(mesh);
642
643         /* scan the input list and insert the new vertices */
644
645         mvert= &mesh->mvert[mesh->totvert];
646         for(i=0; i<len; i++, mvert++)
647                 mvert->flag |= SELECT;
648
649         /* set final vertex list size */
650         mesh->totvert= totvert;
651 }
652
653 void ED_mesh_transform(Mesh *me, float *mat)
654 {
655         int i;
656         MVert *mvert= me->mvert;
657
658         for(i= 0; i < me->totvert; i++, mvert++)
659                 mul_m4_v3((float (*)[4])mat, mvert->co);
660
661         mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
662 }
663
664 static void mesh_add_edges(Mesh *mesh, int len)
665 {
666         CustomData edata;
667         MEdge *medge;
668         int i, totedge;
669
670         if(len == 0)
671                 return;
672
673         totedge= mesh->totedge+len;
674
675         /* update customdata  */
676         CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge);
677         CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge);
678
679         if(!CustomData_has_layer(&edata, CD_MEDGE))
680                 CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
681
682         CustomData_free(&mesh->edata, mesh->totedge);
683         mesh->edata= edata;
684         mesh_update_customdata_pointers(mesh);
685
686         /* set default flags */
687         medge= &mesh->medge[mesh->totedge];
688         for(i=0; i<len; i++, medge++)
689                 medge->flag= ME_EDGEDRAW|ME_EDGERENDER|SELECT;
690
691         mesh->totedge= totedge;
692 }
693
694 static void mesh_add_faces(Mesh *mesh, int len)
695 {
696         CustomData fdata;
697         MFace *mface;
698         int i, totface;
699
700         if(len == 0)
701                 return;
702
703         totface= mesh->totface + len;   /* new face count */
704
705         /* update customdata */
706         CustomData_copy(&mesh->fdata, &fdata, CD_MASK_MESH, CD_DEFAULT, totface);
707         CustomData_copy_data(&mesh->fdata, &fdata, 0, 0, mesh->totface);
708
709         if(!CustomData_has_layer(&fdata, CD_MFACE))
710                 CustomData_add_layer(&fdata, CD_MFACE, CD_CALLOC, NULL, totface);
711
712         CustomData_free(&mesh->fdata, mesh->totface);
713         mesh->fdata= fdata;
714         mesh_update_customdata_pointers(mesh);
715
716         /* set default flags */
717         mface= &mesh->mface[mesh->totface];
718         for(i=0; i<len; i++, mface++)
719                 mface->flag= ME_FACE_SEL;
720
721         mesh->totface= totface;
722 }
723
724 /*
725 void ED_mesh_geometry_add(Mesh *mesh, ReportList *reports, int verts, int edges, int faces)
726 {
727         if(mesh->edit_mesh) {
728                 BKE_report(reports, RPT_ERROR, "Can't add geometry in edit mode.");
729                 return;
730         }
731
732         if(verts)
733                 mesh_add_verts(mesh, verts);
734         if(edges)
735                 mesh_add_edges(mesh, edges);
736         if(faces)
737                 mesh_add_faces(mesh, faces);
738 }
739 */
740
741 void ED_mesh_faces_add(Mesh *mesh, ReportList *reports, int count)
742 {
743         if(mesh->edit_mesh) {
744                 BKE_report(reports, RPT_ERROR, "Can't add faces in edit mode.");
745                 return;
746         }
747
748         mesh_add_faces(mesh, count);
749 }
750
751 void ED_mesh_edges_add(Mesh *mesh, ReportList *reports, int count)
752 {
753         if(mesh->edit_mesh) {
754                 BKE_report(reports, RPT_ERROR, "Can't add edges in edit mode.");
755                 return;
756         }
757
758         mesh_add_edges(mesh, count);
759 }
760
761 void ED_mesh_vertices_add(Mesh *mesh, ReportList *reports, int count)
762 {
763         if(mesh->edit_mesh) {
764                 BKE_report(reports, RPT_ERROR, "Can't add vertices in edit mode.");
765                 return;
766         }
767
768         mesh_add_verts(mesh, count);
769 }
770
771 void ED_mesh_calc_normals(Mesh *me)
772 {
773         mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
774 }