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