split BKE_utildefines.h, now it only has blender specific defines like GS() MAKE_ID...
[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 "BLI_math.h"
42 #include "BLI_editVert.h"
43 #include "BLI_edgehash.h"
44 #include "BLI_utildefines.h"
45
46 #include "BKE_context.h"
47 #include "BKE_depsgraph.h"
48 #include "BKE_displist.h"
49 #include "BKE_image.h"
50 #include "BKE_library.h"
51 #include "BKE_material.h"
52 #include "BKE_mesh.h"
53 #include "BKE_report.h"
54
55 #include "RNA_access.h"
56 #include "RNA_define.h"
57
58 #include "WM_api.h"
59 #include "WM_types.h"
60
61 #include "ED_mesh.h"
62 #include "ED_object.h"
63 #include "ED_uvedit.h"
64 #include "ED_view3d.h"
65
66 #include "RE_render_ext.h"
67
68 #include "mesh_intern.h"
69
70 static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *layer)
71 {
72         Mesh *me = ob->data;
73         CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
74         void *actlayerdata, *rndlayerdata, *clonelayerdata, *stencillayerdata, *layerdata=layer->data;
75         int type= layer->type;
76         int index= CustomData_get_layer_index(data, type);
77         int i, actindex, rndindex, cloneindex, stencilindex;
78         
79         /* ok, deleting a non-active layer needs to preserve the active layer indices.
80           to do this, we store a pointer to the .data member of both layer and the active layer,
81           (to detect if we're deleting the active layer or not), then use the active
82           layer data pointer to find where the active layer has ended up.
83           
84           this is necassary because the deletion functions only support deleting the active
85           layer. */
86         actlayerdata = data->layers[CustomData_get_active_layer_index(data, type)].data;
87         rndlayerdata = data->layers[CustomData_get_render_layer_index(data, type)].data;
88         clonelayerdata = data->layers[CustomData_get_clone_layer_index(data, type)].data;
89         stencillayerdata = data->layers[CustomData_get_stencil_layer_index(data, type)].data;
90         CustomData_set_layer_active(data, type, layer - &data->layers[index]);
91
92         if(me->edit_mesh) {
93                 EM_free_data_layer(me->edit_mesh, data, type);
94         }
95         else {
96                 CustomData_free_layer_active(data, type, me->totface);
97                 mesh_update_customdata_pointers(me);
98         }
99
100         if(!CustomData_has_layer(data, type) && (type == CD_MCOL && (ob->mode & OB_MODE_VERTEX_PAINT)))
101                 ED_object_toggle_modes(C, OB_MODE_VERTEX_PAINT);
102
103         /* reconstruct active layer */
104         if (actlayerdata != layerdata) {
105                 /* find index */
106                 actindex = CustomData_get_layer_index(data, type);
107                 for (i=actindex; i<data->totlayer; i++) {
108                         if (data->layers[i].data == actlayerdata) {
109                                 actindex = i - actindex;
110                                 break;
111                         }
112                 }
113                 
114                 /* set index */
115                 CustomData_set_layer_active(data, type, actindex);
116         }
117         
118         if (rndlayerdata != layerdata) {
119                 /* find index */
120                 rndindex = CustomData_get_layer_index(data, type);
121                 for (i=rndindex; i<data->totlayer; i++) {
122                         if (data->layers[i].data == rndlayerdata) {
123                                 rndindex = i - rndindex;
124                                 break;
125                         }
126                 }
127                 
128                 /* set index */
129                 CustomData_set_layer_render(data, type, rndindex);
130         }
131         
132         if (clonelayerdata != layerdata) {
133                 /* find index */
134                 cloneindex = CustomData_get_layer_index(data, type);
135                 for (i=cloneindex; i<data->totlayer; i++) {
136                         if (data->layers[i].data == clonelayerdata) {
137                                 cloneindex = i - cloneindex;
138                                 break;
139                         }
140                 }
141                 
142                 /* set index */
143                 CustomData_set_layer_clone(data, type, cloneindex);
144         }
145         
146         if (stencillayerdata != layerdata) {
147                 /* find index */
148                 stencilindex = CustomData_get_layer_index(data, type);
149                 for (i=stencilindex; i<data->totlayer; i++) {
150                         if (data->layers[i].data == stencillayerdata) {
151                                 stencilindex = i - stencilindex;
152                                 break;
153                         }
154                 }
155                 
156                 /* set index */
157                 CustomData_set_layer_stencil(data, type, stencilindex);
158         }
159 }
160
161 int ED_mesh_uv_texture_add(bContext *C, Mesh *me, const char *name, int active_set)
162 {
163         EditMesh *em;
164         int layernum;
165
166         if(me->edit_mesh) {
167                 em= me->edit_mesh;
168
169                 layernum= CustomData_number_of_layers(&em->fdata, CD_MTFACE);
170                 if(layernum >= MAX_MTFACE)
171                         return 0;
172
173                 EM_add_data_layer(em, &em->fdata, CD_MTFACE, name);
174                 if(active_set || layernum==0)
175                         CustomData_set_layer_active(&em->fdata, CD_MTFACE, layernum);
176         }
177         else {
178                 layernum= CustomData_number_of_layers(&me->fdata, CD_MTFACE);
179                 if(layernum >= MAX_MTFACE)
180                         return 0;
181
182                 if(me->mtface)
183                         CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_DUPLICATE, me->mtface, me->totface, name);
184                 else
185                         CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_DEFAULT, NULL, me->totface, name);
186
187                 if(active_set || layernum==0)
188                         CustomData_set_layer_active(&me->fdata, CD_MTFACE, layernum);
189
190                 mesh_update_customdata_pointers(me);
191         }
192
193         DAG_id_tag_update(&me->id, 0);
194         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
195
196         return 1;
197 }
198
199 int ED_mesh_uv_texture_remove(bContext *C, Object *ob, Mesh *me)
200 {
201         CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
202         CustomDataLayer *cdl;
203         int index;
204
205         index= CustomData_get_active_layer_index(data, CD_MTFACE);
206         cdl= (index == -1) ? NULL: &data->layers[index];
207
208         if(!cdl)
209                 return 0;
210
211         delete_customdata_layer(C, ob, cdl);
212         DAG_id_tag_update(&me->id, 0);
213         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
214
215         return 1;
216 }
217
218 int ED_mesh_color_add(bContext *C, Scene *scene, Object *ob, Mesh *me, const char *name, int active_set)
219 {
220         EditMesh *em;
221         MCol *mcol;
222         int layernum;
223
224         if(me->edit_mesh) {
225                 em= me->edit_mesh;
226
227                 layernum= CustomData_number_of_layers(&em->fdata, CD_MCOL);
228                 if(layernum >= MAX_MCOL)
229                         return 0;
230
231                 EM_add_data_layer(em, &em->fdata, CD_MCOL, name);
232                 if(active_set || layernum==0)
233                         CustomData_set_layer_active(&em->fdata, CD_MCOL, layernum);
234         }
235         else {
236                 layernum= CustomData_number_of_layers(&me->fdata, CD_MCOL);
237                 if(layernum >= MAX_MCOL)
238                         return 0;
239
240                 mcol= me->mcol;
241
242                 if(me->mcol)
243                         CustomData_add_layer_named(&me->fdata, CD_MCOL, CD_DUPLICATE, me->mcol, me->totface, name);
244                 else
245                         CustomData_add_layer_named(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface, name);
246
247                 if(active_set || layernum==0)
248                         CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum);
249
250                 mesh_update_customdata_pointers(me);
251
252                 if(!mcol)
253                         shadeMeshMCol(scene, ob, me);
254         }
255
256         DAG_id_tag_update(&me->id, 0);
257         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
258
259         return 1;
260 }
261
262 int ED_mesh_color_remove(bContext *C, Object *ob, Mesh *me)
263 {
264         CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
265         CustomDataLayer *cdl;
266         int index;
267
268          index= CustomData_get_active_layer_index(data, CD_MCOL);
269         cdl= (index == -1)? NULL: &data->layers[index];
270
271         if(!cdl)
272                 return 0;
273
274         delete_customdata_layer(C, ob, cdl);
275         DAG_id_tag_update(&me->id, 0);
276         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
277
278         return 1;
279 }
280
281 /*********************** UV texture operators ************************/
282
283 static int layers_poll(bContext *C)
284 {
285         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
286         ID *data= (ob)? ob->data: NULL;
287         return (ob && !ob->id.lib && ob->type==OB_MESH && data && !data->lib);
288 }
289
290 static int uv_texture_add_exec(bContext *C, wmOperator *UNUSED(op))
291 {
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, 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_tag_update(&me->id, 0);
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_tag_update(&me->id, 0);
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_tag_update(&mesh->id, 0);
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 }