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