remove unused includes
[blender-staging.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)
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 OPERATOR_CANCELLED;
171
172                 EM_add_data_layer(em, &em->fdata, CD_MTFACE);
173                 CustomData_set_layer_active(&em->fdata, CD_MTFACE, layernum);
174         }
175         else {
176                 layernum= CustomData_number_of_layers(&me->fdata, CD_MTFACE);
177                 if(layernum >= MAX_MTFACE)
178                         return OPERATOR_CANCELLED;
179
180                 if(me->mtface)
181                         CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DUPLICATE, me->mtface, me->totface);
182                 else
183                         CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT, NULL, me->totface);
184
185                 CustomData_set_layer_active(&me->fdata, CD_MTFACE, layernum);
186                 mesh_update_customdata_pointers(me);
187         }
188
189         DAG_id_flush_update(&me->id, OB_RECALC_DATA);
190         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
191
192         return 1;
193 }
194
195 int ED_mesh_uv_texture_remove(bContext *C, Object *ob, Mesh *me)
196 {
197         CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
198         CustomDataLayer *cdl;
199         int index;
200
201          index= CustomData_get_active_layer_index(data, CD_MTFACE);
202         cdl= (index == -1) ? NULL: &data->layers[index];
203
204         if(!cdl)
205                 return 0;
206
207         delete_customdata_layer(C, ob, cdl);
208         DAG_id_flush_update(&me->id, OB_RECALC_DATA);
209         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
210
211         return 1;
212 }
213
214 int ED_mesh_color_add(bContext *C, Scene *scene, Object *ob, Mesh *me)
215 {
216         EditMesh *em;
217         MCol *mcol;
218         int layernum;
219
220         if(me->edit_mesh) {
221                 em= me->edit_mesh;
222
223                 layernum= CustomData_number_of_layers(&em->fdata, CD_MCOL);
224                 if(layernum >= MAX_MCOL)
225                         return 0;
226
227                 EM_add_data_layer(em, &em->fdata, CD_MCOL);
228                 CustomData_set_layer_active(&em->fdata, CD_MCOL, layernum);
229         }
230         else {
231                 layernum= CustomData_number_of_layers(&me->fdata, CD_MCOL);
232                 if(layernum >= MAX_MCOL)
233                         return 0;
234
235                 mcol= me->mcol;
236
237                 if(me->mcol)
238                         CustomData_add_layer(&me->fdata, CD_MCOL, CD_DUPLICATE, me->mcol, me->totface);
239                 else
240                         CustomData_add_layer(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface);
241
242                 CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum);
243                 mesh_update_customdata_pointers(me);
244
245                 if(!mcol)
246                         shadeMeshMCol(scene, ob, me);
247         }
248
249         DAG_id_flush_update(&me->id, OB_RECALC_DATA);
250         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
251
252         return 1;
253 }
254
255 int ED_mesh_color_remove(bContext *C, Object *ob, Mesh *me)
256 {
257         CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
258         CustomDataLayer *cdl;
259         int index;
260
261          index= CustomData_get_active_layer_index(data, CD_MCOL);
262         cdl= (index == -1)? NULL: &data->layers[index];
263
264         if(!cdl)
265                 return 0;
266
267         delete_customdata_layer(C, ob, cdl);
268         DAG_id_flush_update(&me->id, OB_RECALC_DATA);
269         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
270
271         return 1;
272 }
273
274 /*********************** UV texture operators ************************/
275
276 static int layers_poll(bContext *C)
277 {
278         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
279         ID *data= (ob)? ob->data: NULL;
280         return (ob && !ob->id.lib && ob->type==OB_MESH && data && !data->lib);
281 }
282
283 static int uv_texture_add_exec(bContext *C, wmOperator *op)
284 {
285         Scene *scene= CTX_data_scene(C);
286         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
287         Mesh *me= ob->data;
288
289         if(!ED_mesh_uv_texture_add(C, scene, ob, me))
290                 return OPERATOR_CANCELLED;
291
292         return OPERATOR_FINISHED;
293 }
294
295 void MESH_OT_uv_texture_add(wmOperatorType *ot)
296 {
297         /* identifiers */
298         ot->name= "Add UV Texture";
299         ot->description= "Add UV texture layer";
300         ot->idname= "MESH_OT_uv_texture_add";
301         
302         /* api callbacks */
303         ot->poll= layers_poll;
304         ot->exec= uv_texture_add_exec;
305
306         /* flags */
307         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
308 }
309
310 static int drop_named_image_invoke(bContext *C, wmOperator *op, wmEvent *event)
311 {
312         Scene *scene= CTX_data_scene(C);
313         Base *base= ED_view3d_give_base_under_cursor(C, event->mval);
314         Image *ima= NULL;
315         Mesh *me;
316         Object *obedit;
317         int exitmode= 0;
318         char name[32];
319         
320         /* Check context */
321         if(base==NULL || base->object->type!=OB_MESH) {
322                 BKE_report(op->reports, RPT_ERROR, "Not an Object or Mesh");
323                 return OPERATOR_CANCELLED;
324         }
325         
326         /* check input variables */
327         if(RNA_property_is_set(op->ptr, "filepath")) {
328                 char path[FILE_MAX];
329                 
330                 RNA_string_get(op->ptr, "filepath", path);
331                 ima= BKE_add_image_file(path, 
332                                                                 scene ? scene->r.cfra : 1);
333         }
334         else {
335                 RNA_string_get(op->ptr, "name", name);
336                 ima= (Image *)find_id("IM", name);
337         }
338         
339         if(!ima) {
340                 BKE_report(op->reports, RPT_ERROR, "Not an Image.");
341                 return OPERATOR_CANCELLED;
342         }
343         
344         /* turn mesh in editmode */
345         /* BKE_mesh_get/end_editmesh: ED_uvedit_assign_image also calls this */
346
347         obedit= base->object;
348         me= obedit->data;
349         if(me->edit_mesh==NULL) {
350                 make_editMesh(scene, obedit);
351                 exitmode= 1;
352         }
353         if(me->edit_mesh==NULL)
354                 return OPERATOR_CANCELLED;
355         
356         ED_uvedit_assign_image(scene, obedit, ima, NULL);
357
358         if(exitmode) {
359                 load_editMesh(scene, obedit);
360                 free_editMesh(me->edit_mesh);
361                 MEM_freeN(me->edit_mesh);
362                 me->edit_mesh= NULL;
363         }
364
365         WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
366         
367         return OPERATOR_FINISHED;
368 }
369
370 void MESH_OT_drop_named_image(wmOperatorType *ot)
371 {
372         /* identifiers */
373         ot->name= "Assign Image to UV Texture";
374         ot->description= "Assigns Image to active UV layer, or creates a UV layer";
375         ot->idname= "MESH_OT_drop_named_image";
376         
377         /* api callbacks */
378         ot->poll= layers_poll;
379         ot->invoke= drop_named_image_invoke;
380         
381         /* flags */
382         ot->flag= OPTYPE_UNDO;
383         
384         /* properties */
385         RNA_def_string(ot->srna, "name", "Image", 24, "Name", "Image name to assign.");
386         RNA_def_string(ot->srna, "filepath", "Path", FILE_MAX, "Filepath", "Path to image file");
387 }
388
389 static int uv_texture_remove_exec(bContext *C, wmOperator *op)
390 {
391         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
392         Mesh *me= ob->data;
393
394         if(!ED_mesh_uv_texture_remove(C, ob, me))
395                 return OPERATOR_CANCELLED;
396
397         return OPERATOR_FINISHED;
398 }
399
400 void MESH_OT_uv_texture_remove(wmOperatorType *ot)
401 {
402         /* identifiers */
403         ot->name= "Remove UV Texture";
404         ot->description= "Remove UV texture layer";
405         ot->idname= "MESH_OT_uv_texture_remove";
406         
407         /* api callbacks */
408         ot->poll= layers_poll;
409         ot->exec= uv_texture_remove_exec;
410
411         /* flags */
412         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
413 }
414
415 /*********************** vertex color operators ************************/
416
417 static int vertex_color_add_exec(bContext *C, wmOperator *op)
418 {
419         Scene *scene= CTX_data_scene(C);
420         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
421         Mesh *me= ob->data;
422
423         if(!ED_mesh_color_add(C, scene, ob, me))
424                 return OPERATOR_CANCELLED;
425
426         return OPERATOR_FINISHED;
427 }
428
429 void MESH_OT_vertex_color_add(wmOperatorType *ot)
430 {
431         /* identifiers */
432         ot->name= "Add Vertex Color";
433         ot->description= "Add vertex color layer";
434         ot->idname= "MESH_OT_vertex_color_add";
435         
436         /* api callbacks */
437         ot->poll= layers_poll;
438         ot->exec= vertex_color_add_exec;
439
440         /* flags */
441         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
442 }
443
444 static int vertex_color_remove_exec(bContext *C, wmOperator *op)
445 {
446         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
447         Mesh *me= ob->data;
448
449         if(!ED_mesh_color_remove(C, ob, me))
450                 return OPERATOR_CANCELLED;
451
452         return OPERATOR_FINISHED;
453 }
454
455 void MESH_OT_vertex_color_remove(wmOperatorType *ot)
456 {
457         /* identifiers */
458         ot->name= "Remove Vertex Color";
459         ot->description= "Remove vertex color layer";
460         ot->idname= "MESH_OT_vertex_color_remove";
461         
462         /* api callbacks */
463         ot->exec= vertex_color_remove_exec;
464         ot->poll= layers_poll;
465
466         /* flags */
467         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
468 }
469
470 /*********************** sticky operators ************************/
471
472 static int sticky_add_exec(bContext *C, wmOperator *op)
473 {
474         Scene *scene= CTX_data_scene(C);
475         View3D *v3d= CTX_wm_view3d(C);
476         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
477         Mesh *me= ob->data;
478
479         /*if(me->msticky)
480                 return OPERATOR_CANCELLED;*/
481
482         RE_make_sticky(scene, v3d);
483
484         DAG_id_flush_update(&me->id, OB_RECALC_DATA);
485         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
486
487         return OPERATOR_FINISHED;
488 }
489
490 void MESH_OT_sticky_add(wmOperatorType *ot)
491 {
492         /* identifiers */
493         ot->name= "Add Sticky";
494         ot->description= "Add sticky UV texture layer";
495         ot->idname= "MESH_OT_sticky_add";
496         
497         /* api callbacks */
498         ot->poll= layers_poll;
499         ot->exec= sticky_add_exec;
500
501         /* flags */
502         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
503 }
504
505 static int sticky_remove_exec(bContext *C, wmOperator *op)
506 {
507         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
508         Mesh *me= ob->data;
509
510         if(!me->msticky)
511                 return OPERATOR_CANCELLED;
512
513         CustomData_free_layer_active(&me->vdata, CD_MSTICKY, me->totvert);
514         me->msticky= NULL;
515
516         DAG_id_flush_update(&me->id, OB_RECALC_DATA);
517         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
518
519         return OPERATOR_FINISHED;
520 }
521
522 void MESH_OT_sticky_remove(wmOperatorType *ot)
523 {
524         /* identifiers */
525         ot->name= "Remove Sticky";
526         ot->description= "Remove sticky UV texture layer";
527         ot->idname= "MESH_OT_sticky_remove";
528         
529         /* api callbacks */
530         ot->poll= layers_poll;
531         ot->exec= sticky_remove_exec;
532
533         /* flags */
534         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
535 }
536
537 /************************** Add Geometry Layers *************************/
538
539 static void mesh_calc_edges(Mesh *mesh, int update)
540 {
541         CustomData edata;
542         EdgeHashIterator *ehi;
543         MFace *mf = mesh->mface;
544         MEdge *med, *med_orig;
545         EdgeHash *eh = BLI_edgehash_new();
546         int i, totedge, totface = mesh->totface;
547
548         if(mesh->totedge==0)
549                 update= 0;
550
551         if(update) {
552                 /* assume existing edges are valid
553                  * useful when adding more faces and generating edges from them */
554                 med= mesh->medge;
555                 for(i= 0; i<mesh->totedge; i++, med++)
556                         BLI_edgehash_insert(eh, med->v1, med->v2, med);
557         }
558
559         for (i = 0; i < totface; i++, mf++) {
560                 if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
561                         BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
562                 if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
563                         BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
564                 
565                 if (mf->v4) {
566                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
567                                 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
568                         if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
569                                 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
570                 } else {
571                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
572                                 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
573                 }
574         }
575
576         totedge = BLI_edgehash_size(eh);
577
578         /* write new edges into a temporary CustomData */
579         memset(&edata, 0, sizeof(edata));
580         CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
581
582         ehi = BLI_edgehashIterator_new(eh);
583         med = CustomData_get_layer(&edata, CD_MEDGE);
584         for(i = 0; !BLI_edgehashIterator_isDone(ehi);
585                 BLI_edgehashIterator_step(ehi), ++i, ++med) {
586
587                 if(update && (med_orig=BLI_edgehashIterator_getValue(ehi))) {
588                         *med= *med_orig; /* copy from the original */
589                 } else {
590                         BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
591                         med->flag = ME_EDGEDRAW|ME_EDGERENDER;
592                 }
593         }
594         BLI_edgehashIterator_free(ehi);
595
596         /* free old CustomData and assign new one */
597         CustomData_free(&mesh->edata, mesh->totedge);
598         mesh->edata = edata;
599         mesh->totedge = totedge;
600
601         mesh->medge = CustomData_get_layer(&mesh->edata, CD_MEDGE);
602
603         BLI_edgehash_free(eh, NULL);
604 }
605
606 void ED_mesh_update(Mesh *mesh, bContext *C, int calc_edges)
607 {
608         if(calc_edges || (mesh->totface && mesh->totedge == 0))
609                 mesh_calc_edges(mesh, calc_edges);
610
611         mesh_calc_normals(mesh->mvert, mesh->totvert, mesh->mface, mesh->totface, NULL);
612
613         DAG_id_flush_update(&mesh->id, OB_RECALC_DATA);
614         WM_event_add_notifier(C, NC_GEOM|ND_DATA, mesh);
615 }
616
617 static void mesh_add_verts(Mesh *mesh, int len)
618 {
619         CustomData vdata;
620         MVert *mvert;
621         int i, totvert;
622
623         if(len == 0)
624                 return;
625
626         totvert= mesh->totvert + len;
627         CustomData_copy(&mesh->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert);
628         CustomData_copy_data(&mesh->vdata, &vdata, 0, 0, mesh->totvert);
629
630         if(!CustomData_has_layer(&vdata, CD_MVERT))
631                 CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
632
633         CustomData_free(&mesh->vdata, mesh->totvert);
634         mesh->vdata= vdata;
635         mesh_update_customdata_pointers(mesh);
636
637         /* scan the input list and insert the new vertices */
638
639         mvert= &mesh->mvert[mesh->totvert];
640         for(i=0; i<len; i++, mvert++)
641                 mvert->flag |= SELECT;
642
643         /* set final vertex list size */
644         mesh->totvert= totvert;
645 }
646
647 void ED_mesh_transform(Mesh *me, float *mat)
648 {
649         int i;
650         MVert *mvert= me->mvert;
651
652         for(i= 0; i < me->totvert; i++, mvert++)
653                 mul_m4_v3((float (*)[4])mat, mvert->co);
654
655         mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
656 }
657
658 static void mesh_add_edges(Mesh *mesh, int len)
659 {
660         CustomData edata;
661         MEdge *medge;
662         int i, totedge;
663
664         if(len == 0)
665                 return;
666
667         totedge= mesh->totedge+len;
668
669         /* update customdata  */
670         CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge);
671         CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge);
672
673         if(!CustomData_has_layer(&edata, CD_MEDGE))
674                 CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
675
676         CustomData_free(&mesh->edata, mesh->totedge);
677         mesh->edata= edata;
678         mesh_update_customdata_pointers(mesh);
679
680         /* set default flags */
681         medge= &mesh->medge[mesh->totedge];
682         for(i=0; i<len; i++, medge++)
683                 medge->flag= ME_EDGEDRAW|ME_EDGERENDER|SELECT;
684
685         mesh->totedge= totedge;
686 }
687
688 static void mesh_add_faces(Mesh *mesh, int len)
689 {
690         CustomData fdata;
691         MFace *mface;
692         int i, totface;
693
694         if(len == 0)
695                 return;
696
697         totface= mesh->totface + len;   /* new face count */
698
699         /* update customdata */
700         CustomData_copy(&mesh->fdata, &fdata, CD_MASK_MESH, CD_DEFAULT, totface);
701         CustomData_copy_data(&mesh->fdata, &fdata, 0, 0, mesh->totface);
702
703         if(!CustomData_has_layer(&fdata, CD_MFACE))
704                 CustomData_add_layer(&fdata, CD_MFACE, CD_CALLOC, NULL, totface);
705
706         CustomData_free(&mesh->fdata, mesh->totface);
707         mesh->fdata= fdata;
708         mesh_update_customdata_pointers(mesh);
709
710         /* set default flags */
711         mface= &mesh->mface[mesh->totface];
712         for(i=0; i<len; i++, mface++)
713                 mface->flag= ME_FACE_SEL;
714
715         mesh->totface= totface;
716 }
717
718 void ED_mesh_geometry_add(Mesh *mesh, ReportList *reports, int verts, int edges, int faces)
719 {
720         if(mesh->edit_mesh) {
721                 BKE_report(reports, RPT_ERROR, "Can't add geometry in edit mode.");
722                 return;
723         }
724
725         if(verts)
726                 mesh_add_verts(mesh, verts);
727         if(edges)
728                 mesh_add_edges(mesh, edges);
729         if(faces)
730                 mesh_add_faces(mesh, faces);
731 }
732
733 void ED_mesh_calc_normals(Mesh *me)
734 {
735         mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
736 }
737
738 void ED_mesh_material_add(Mesh *me, Material *ma)
739 {
740         int i;
741         int totcol = me->totcol + 1;
742         Material **mat;
743
744         /* don't add if mesh already has it */
745         for(i = 0; i < me->totcol; i++)
746                 if(me->mat[i] == ma)
747                         return;
748
749         mat= MEM_callocN(sizeof(void*)*totcol, "newmatar");
750
751         if(me->totcol) memcpy(mat, me->mat, sizeof(void*) * me->totcol);
752         if(me->mat) MEM_freeN(me->mat);
753
754         me->mat = mat;
755         me->mat[me->totcol++] = ma;
756         if(ma)
757                 ma->id.us++;
758
759         test_object_materials((ID*)me);
760 }
761