remove/tag unused args for view*.c, gpu*.c & image*.c
[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 *UNUSED(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         }
339         else {
340                 RNA_string_get(op->ptr, "name", name);
341                 ima= (Image *)find_id("IM", name);
342         }
343         
344         if(!ima) {
345                 BKE_report(op->reports, RPT_ERROR, "Not an Image.");
346                 return OPERATOR_CANCELLED;
347         }
348         
349         /* turn mesh in editmode */
350         /* BKE_mesh_get/end_editmesh: ED_uvedit_assign_image also calls this */
351
352         obedit= base->object;
353         me= obedit->data;
354         if(me->edit_mesh==NULL) {
355                 make_editMesh(scene, obedit);
356                 exitmode= 1;
357         }
358         if(me->edit_mesh==NULL)
359                 return OPERATOR_CANCELLED;
360         
361         ED_uvedit_assign_image(scene, obedit, ima, NULL);
362
363         if(exitmode) {
364                 load_editMesh(scene, obedit);
365                 free_editMesh(me->edit_mesh);
366                 MEM_freeN(me->edit_mesh);
367                 me->edit_mesh= NULL;
368         }
369
370         WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
371         
372         return OPERATOR_FINISHED;
373 }
374
375 void MESH_OT_drop_named_image(wmOperatorType *ot)
376 {
377         /* identifiers */
378         ot->name= "Assign Image to UV Texture";
379         ot->description= "Assigns Image to active UV layer, or creates a UV layer";
380         ot->idname= "MESH_OT_drop_named_image";
381         
382         /* api callbacks */
383         ot->poll= layers_poll;
384         ot->invoke= drop_named_image_invoke;
385         
386         /* flags */
387         ot->flag= OPTYPE_UNDO;
388         
389         /* properties */
390         RNA_def_string(ot->srna, "name", "Image", 24, "Name", "Image name to assign.");
391         RNA_def_string(ot->srna, "filepath", "Path", FILE_MAX, "Filepath", "Path to image file");
392 }
393
394 static int uv_texture_remove_exec(bContext *C, wmOperator *UNUSED(op))
395 {
396         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
397         Mesh *me= ob->data;
398
399         if(!ED_mesh_uv_texture_remove(C, ob, me))
400                 return OPERATOR_CANCELLED;
401
402         return OPERATOR_FINISHED;
403 }
404
405 void MESH_OT_uv_texture_remove(wmOperatorType *ot)
406 {
407         /* identifiers */
408         ot->name= "Remove UV Texture";
409         ot->description= "Remove UV texture layer";
410         ot->idname= "MESH_OT_uv_texture_remove";
411         
412         /* api callbacks */
413         ot->poll= layers_poll;
414         ot->exec= uv_texture_remove_exec;
415
416         /* flags */
417         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
418 }
419
420 /*********************** vertex color operators ************************/
421
422 static int vertex_color_add_exec(bContext *C, wmOperator *UNUSED(op))
423 {
424         Scene *scene= CTX_data_scene(C);
425         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
426         Mesh *me= ob->data;
427
428         if(!ED_mesh_color_add(C, scene, ob, me, NULL, TRUE))
429                 return OPERATOR_CANCELLED;
430
431         return OPERATOR_FINISHED;
432 }
433
434 void MESH_OT_vertex_color_add(wmOperatorType *ot)
435 {
436         /* identifiers */
437         ot->name= "Add Vertex Color";
438         ot->description= "Add vertex color layer";
439         ot->idname= "MESH_OT_vertex_color_add";
440         
441         /* api callbacks */
442         ot->poll= layers_poll;
443         ot->exec= vertex_color_add_exec;
444
445         /* flags */
446         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
447 }
448
449 static int vertex_color_remove_exec(bContext *C, wmOperator *UNUSED(op))
450 {
451         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
452         Mesh *me= ob->data;
453
454         if(!ED_mesh_color_remove(C, ob, me))
455                 return OPERATOR_CANCELLED;
456
457         return OPERATOR_FINISHED;
458 }
459
460 void MESH_OT_vertex_color_remove(wmOperatorType *ot)
461 {
462         /* identifiers */
463         ot->name= "Remove Vertex Color";
464         ot->description= "Remove vertex color layer";
465         ot->idname= "MESH_OT_vertex_color_remove";
466         
467         /* api callbacks */
468         ot->exec= vertex_color_remove_exec;
469         ot->poll= layers_poll;
470
471         /* flags */
472         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
473 }
474
475 /*********************** sticky operators ************************/
476
477 static int sticky_add_exec(bContext *C, wmOperator *UNUSED(op))
478 {
479         Scene *scene= CTX_data_scene(C);
480         View3D *v3d= CTX_wm_view3d(C);
481         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
482         Mesh *me= ob->data;
483
484         /*if(me->msticky)
485                 return OPERATOR_CANCELLED;*/
486
487         RE_make_sticky(scene, v3d);
488
489         DAG_id_flush_update(&me->id, OB_RECALC_DATA);
490         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
491
492         return OPERATOR_FINISHED;
493 }
494
495 void MESH_OT_sticky_add(wmOperatorType *ot)
496 {
497         /* identifiers */
498         ot->name= "Add Sticky";
499         ot->description= "Add sticky UV texture layer";
500         ot->idname= "MESH_OT_sticky_add";
501         
502         /* api callbacks */
503         ot->poll= layers_poll;
504         ot->exec= sticky_add_exec;
505
506         /* flags */
507         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
508 }
509
510 static int sticky_remove_exec(bContext *C, wmOperator *UNUSED(op))
511 {
512         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
513         Mesh *me= ob->data;
514
515         if(!me->msticky)
516                 return OPERATOR_CANCELLED;
517
518         CustomData_free_layer_active(&me->vdata, CD_MSTICKY, me->totvert);
519         me->msticky= NULL;
520
521         DAG_id_flush_update(&me->id, OB_RECALC_DATA);
522         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
523
524         return OPERATOR_FINISHED;
525 }
526
527 void MESH_OT_sticky_remove(wmOperatorType *ot)
528 {
529         /* identifiers */
530         ot->name= "Remove Sticky";
531         ot->description= "Remove sticky UV texture layer";
532         ot->idname= "MESH_OT_sticky_remove";
533         
534         /* api callbacks */
535         ot->poll= layers_poll;
536         ot->exec= sticky_remove_exec;
537
538         /* flags */
539         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
540 }
541
542 /************************** Add Geometry Layers *************************/
543
544 static void mesh_calc_edges(Mesh *mesh, int update)
545 {
546         CustomData edata;
547         EdgeHashIterator *ehi;
548         MFace *mf = mesh->mface;
549         MEdge *med, *med_orig;
550         EdgeHash *eh = BLI_edgehash_new();
551         int i, totedge, totface = mesh->totface;
552
553         if(mesh->totedge==0)
554                 update= 0;
555
556         if(update) {
557                 /* assume existing edges are valid
558                  * useful when adding more faces and generating edges from them */
559                 med= mesh->medge;
560                 for(i= 0; i<mesh->totedge; i++, med++)
561                         BLI_edgehash_insert(eh, med->v1, med->v2, med);
562         }
563
564         for (i = 0; i < totface; i++, mf++) {
565                 if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
566                         BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
567                 if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
568                         BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
569                 
570                 if (mf->v4) {
571                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
572                                 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
573                         if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
574                                 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
575                 } else {
576                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
577                                 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
578                 }
579         }
580
581         totedge = BLI_edgehash_size(eh);
582
583         /* write new edges into a temporary CustomData */
584         memset(&edata, 0, sizeof(edata));
585         CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
586
587         ehi = BLI_edgehashIterator_new(eh);
588         med = CustomData_get_layer(&edata, CD_MEDGE);
589         for(i = 0; !BLI_edgehashIterator_isDone(ehi);
590                 BLI_edgehashIterator_step(ehi), ++i, ++med) {
591
592                 if(update && (med_orig=BLI_edgehashIterator_getValue(ehi))) {
593                         *med= *med_orig; /* copy from the original */
594                 } else {
595                         BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
596                         med->flag = ME_EDGEDRAW|ME_EDGERENDER;
597                 }
598         }
599         BLI_edgehashIterator_free(ehi);
600
601         /* free old CustomData and assign new one */
602         CustomData_free(&mesh->edata, mesh->totedge);
603         mesh->edata = edata;
604         mesh->totedge = totedge;
605
606         mesh->medge = CustomData_get_layer(&mesh->edata, CD_MEDGE);
607
608         BLI_edgehash_free(eh, NULL);
609 }
610
611 void ED_mesh_update(Mesh *mesh, bContext *C, int calc_edges)
612 {
613         if(calc_edges || (mesh->totface && mesh->totedge == 0))
614                 mesh_calc_edges(mesh, calc_edges);
615
616         mesh_calc_normals(mesh->mvert, mesh->totvert, mesh->mface, mesh->totface, NULL);
617
618         DAG_id_flush_update(&mesh->id, OB_RECALC_DATA);
619         WM_event_add_notifier(C, NC_GEOM|ND_DATA, mesh);
620 }
621
622 static void mesh_add_verts(Mesh *mesh, int len)
623 {
624         CustomData vdata;
625         MVert *mvert;
626         int i, totvert;
627
628         if(len == 0)
629                 return;
630
631         totvert= mesh->totvert + len;
632         CustomData_copy(&mesh->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert);
633         CustomData_copy_data(&mesh->vdata, &vdata, 0, 0, mesh->totvert);
634
635         if(!CustomData_has_layer(&vdata, CD_MVERT))
636                 CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
637
638         CustomData_free(&mesh->vdata, mesh->totvert);
639         mesh->vdata= vdata;
640         mesh_update_customdata_pointers(mesh);
641
642         /* scan the input list and insert the new vertices */
643
644         mvert= &mesh->mvert[mesh->totvert];
645         for(i=0; i<len; i++, mvert++)
646                 mvert->flag |= SELECT;
647
648         /* set final vertex list size */
649         mesh->totvert= totvert;
650 }
651
652 void ED_mesh_transform(Mesh *me, float *mat)
653 {
654         int i;
655         MVert *mvert= me->mvert;
656
657         for(i= 0; i < me->totvert; i++, mvert++)
658                 mul_m4_v3((float (*)[4])mat, mvert->co);
659
660         mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
661 }
662
663 static void mesh_add_edges(Mesh *mesh, int len)
664 {
665         CustomData edata;
666         MEdge *medge;
667         int i, totedge;
668
669         if(len == 0)
670                 return;
671
672         totedge= mesh->totedge+len;
673
674         /* update customdata  */
675         CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge);
676         CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge);
677
678         if(!CustomData_has_layer(&edata, CD_MEDGE))
679                 CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
680
681         CustomData_free(&mesh->edata, mesh->totedge);
682         mesh->edata= edata;
683         mesh_update_customdata_pointers(mesh);
684
685         /* set default flags */
686         medge= &mesh->medge[mesh->totedge];
687         for(i=0; i<len; i++, medge++)
688                 medge->flag= ME_EDGEDRAW|ME_EDGERENDER|SELECT;
689
690         mesh->totedge= totedge;
691 }
692
693 static void mesh_add_faces(Mesh *mesh, int len)
694 {
695         CustomData fdata;
696         MFace *mface;
697         int i, totface;
698
699         if(len == 0)
700                 return;
701
702         totface= mesh->totface + len;   /* new face count */
703
704         /* update customdata */
705         CustomData_copy(&mesh->fdata, &fdata, CD_MASK_MESH, CD_DEFAULT, totface);
706         CustomData_copy_data(&mesh->fdata, &fdata, 0, 0, mesh->totface);
707
708         if(!CustomData_has_layer(&fdata, CD_MFACE))
709                 CustomData_add_layer(&fdata, CD_MFACE, CD_CALLOC, NULL, totface);
710
711         CustomData_free(&mesh->fdata, mesh->totface);
712         mesh->fdata= fdata;
713         mesh_update_customdata_pointers(mesh);
714
715         /* set default flags */
716         mface= &mesh->mface[mesh->totface];
717         for(i=0; i<len; i++, mface++)
718                 mface->flag= ME_FACE_SEL;
719
720         mesh->totface= totface;
721 }
722
723 /*
724 void ED_mesh_geometry_add(Mesh *mesh, ReportList *reports, int verts, int edges, int faces)
725 {
726         if(mesh->edit_mesh) {
727                 BKE_report(reports, RPT_ERROR, "Can't add geometry in edit mode.");
728                 return;
729         }
730
731         if(verts)
732                 mesh_add_verts(mesh, verts);
733         if(edges)
734                 mesh_add_edges(mesh, edges);
735         if(faces)
736                 mesh_add_faces(mesh, faces);
737 }
738 */
739
740 void ED_mesh_faces_add(Mesh *mesh, ReportList *reports, int count)
741 {
742         if(mesh->edit_mesh) {
743                 BKE_report(reports, RPT_ERROR, "Can't add faces in edit mode.");
744                 return;
745         }
746
747         mesh_add_faces(mesh, count);
748 }
749
750 void ED_mesh_edges_add(Mesh *mesh, ReportList *reports, int count)
751 {
752         if(mesh->edit_mesh) {
753                 BKE_report(reports, RPT_ERROR, "Can't add edges in edit mode.");
754                 return;
755         }
756
757         mesh_add_edges(mesh, count);
758 }
759
760 void ED_mesh_vertices_add(Mesh *mesh, ReportList *reports, int count)
761 {
762         if(mesh->edit_mesh) {
763                 BKE_report(reports, RPT_ERROR, "Can't add vertices in edit mode.");
764                 return;
765         }
766
767         mesh_add_verts(mesh, count);
768 }
769
770 void ED_mesh_calc_normals(Mesh *me)
771 {
772         mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
773 }