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