=bmesh= merge from trunk at r36529
[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 /** \file blender/editors/mesh/mesh_data.c
30  *  \ingroup edmesh
31  */
32
33
34 #include <math.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 #include "MEM_guardedalloc.h"
39
40 #include "DNA_material_types.h"
41 #include "DNA_meshdata_types.h"
42 #include "DNA_object_types.h"
43 #include "DNA_scene_types.h"
44 #include "DNA_view3d_types.h"
45
46 #include "BLI_math.h"
47 #include "BLI_editVert.h"
48 #include "BLI_edgehash.h"
49 #include "BLI_utildefines.h"
50
51 #include "BKE_context.h"
52 #include "BKE_depsgraph.h"
53 #include "BKE_displist.h"
54 #include "BKE_image.h"
55 #include "BKE_library.h"
56 #include "BKE_material.h"
57 #include "BKE_mesh.h"
58 #include "BKE_report.h"
59 #include "BKE_tessmesh.h"
60
61 #include "RNA_access.h"
62 #include "RNA_define.h"
63
64 #include "WM_api.h"
65 #include "WM_types.h"
66
67 #include "ED_mesh.h"
68 #include "ED_object.h"
69 #include "ED_uvedit.h"
70 #include "ED_view3d.h"
71
72 #include "RE_render_ext.h"
73
74 #include "mesh_intern.h"
75
76 #define GET_CD_DATA(me, data) (me->edit_btmesh ? &me->edit_btmesh->bm->data : &me->data)
77
78 static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *layer)
79 {
80         Mesh *me = ob->data;
81         CustomData *data;
82         void *actlayerdata, *rndlayerdata, *clonelayerdata, *stencillayerdata, *layerdata=layer->data;
83         int type= layer->type;
84         int index;
85         int i, actindex, rndindex, cloneindex, stencilindex, tot;
86         
87         if (layer->type == CD_MLOOPCOL || layer->type == CD_MLOOPUV) {
88                 data = (me->edit_btmesh)? &me->edit_btmesh->bm->ldata: &me->ldata;
89                 tot = me->totloop;
90         } else {
91                 data = (me->edit_btmesh)? &me->edit_btmesh->bm->pdata: &me->pdata;
92                 tot = me->totpoly;
93         }
94         
95         index = CustomData_get_layer_index(data, type);
96
97         /* ok, deleting a non-active layer needs to preserve the active layer indices.
98           to do this, we store a pointer to the .data member of both layer and the active layer,
99           (to detect if we're deleting the active layer or not), then use the active
100           layer data pointer to find where the active layer has ended up.
101           
102           this is necassary because the deletion functions only support deleting the active
103           layer. */
104         actlayerdata = data->layers[CustomData_get_active_layer_index(data, type)].data;
105         rndlayerdata = data->layers[CustomData_get_render_layer_index(data, type)].data;
106         clonelayerdata = data->layers[CustomData_get_clone_layer_index(data, type)].data;
107         stencillayerdata = data->layers[CustomData_get_stencil_layer_index(data, type)].data;
108         CustomData_set_layer_active(data, type, layer - &data->layers[index]);
109
110         if(me->edit_btmesh) {
111                 BM_free_data_layer(me->edit_btmesh->bm, data, type);
112         }
113         else {
114                 CustomData_free_layer_active(data, type, tot);
115                 mesh_update_customdata_pointers(me);
116         }
117
118         if(!CustomData_has_layer(data, type) && (type == CD_MLOOPCOL && (ob->mode & OB_MODE_VERTEX_PAINT)))
119                 ED_object_toggle_modes(C, OB_MODE_VERTEX_PAINT);
120
121         /* reconstruct active layer */
122         if (actlayerdata != layerdata) {
123                 /* find index */
124                 actindex = CustomData_get_layer_index(data, type);
125                 for (i=actindex; i<data->totlayer; i++) {
126                         if (data->layers[i].data == actlayerdata) {
127                                 actindex = i - actindex;
128                                 break;
129                         }
130                 }
131                 
132                 /* set index */
133                 CustomData_set_layer_active(data, type, actindex);
134         }
135         
136         if (rndlayerdata != layerdata) {
137                 /* find index */
138                 rndindex = CustomData_get_layer_index(data, type);
139                 for (i=rndindex; i<data->totlayer; i++) {
140                         if (data->layers[i].data == rndlayerdata) {
141                                 rndindex = i - rndindex;
142                                 break;
143                         }
144                 }
145                 
146                 /* set index */
147                 CustomData_set_layer_render(data, type, rndindex);
148         }
149         
150         if (clonelayerdata != layerdata) {
151                 /* find index */
152                 cloneindex = CustomData_get_layer_index(data, type);
153                 for (i=cloneindex; i<data->totlayer; i++) {
154                         if (data->layers[i].data == clonelayerdata) {
155                                 cloneindex = i - cloneindex;
156                                 break;
157                         }
158                 }
159                 
160                 /* set index */
161                 CustomData_set_layer_clone(data, type, cloneindex);
162         }
163         
164         if (stencillayerdata != layerdata) {
165                 /* find index */
166                 stencilindex = CustomData_get_layer_index(data, type);
167                 for (i=stencilindex; i<data->totlayer; i++) {
168                         if (data->layers[i].data == stencillayerdata) {
169                                 stencilindex = i - stencilindex;
170                                 break;
171                         }
172                 }
173                 
174                 /* set index */
175                 CustomData_set_layer_stencil(data, type, stencilindex);
176         }
177 }
178
179 static void copy_editface_active_customdata(EditMesh *em, int type, int index)
180 {
181         EditFace *efa;
182         int n= CustomData_get_active_layer(&em->fdata, type);
183
184         for(efa= em->faces.first; efa; efa= efa->next) {
185                 void *data= CustomData_em_get_n(&em->fdata, efa->data, type, n);
186                 CustomData_em_set_n(&em->fdata, efa->data, type, index, data);
187         }
188 }
189
190 int ED_mesh_uv_texture_add(bContext *C, Mesh *me, const char *name, int active_set)
191 {
192         BMEditMesh *em;
193         int layernum;
194
195         if(me->edit_btmesh) {
196                 em= me->edit_btmesh;
197
198                 layernum= CustomData_number_of_layers(&em->bm->pdata, CD_MTEXPOLY);
199                 if(layernum >= MAX_MTFACE)
200                         return 0;
201
202                 BM_add_data_layer(em->bm, &em->bm->pdata, CD_MTEXPOLY);
203                 CustomData_set_layer_active(&em->bm->pdata, CD_MTEXPOLY, layernum);
204
205                 if(layernum) /* copy data from active UV */
206                         copy_editface_active_customdata(em, CD_MTFACE, layernum);
207
208                 if(active_set || layernum==0)
209                         CustomData_set_layer_active(&em->bm->pdata, CD_MTEXPOLY, layernum);
210
211                 BM_add_data_layer(em->bm, &em->bm->ldata, CD_MLOOPUV);
212                 CustomData_set_layer_active(&em->bm->ldata, CD_MLOOPUV, layernum);
213                 if(active_set || layernum==0)
214                         CustomData_set_layer_active(&em->bm->ldata, CD_MLOOPUV, layernum);
215         }
216         else {
217                 layernum= CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY);
218                 if(layernum >= MAX_MTFACE)
219                         return 0;
220
221                 if(me->mtpoly) {
222                         CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DUPLICATE, me->mtpoly, me->totpoly, name);
223                         CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DUPLICATE, me->mloopuv, me->totloop, name);
224                 } else {
225                         CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, name);
226                         CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, name);
227                 }
228                 
229                 if(active_set || layernum==0) {
230                         CustomData_set_layer_active(&me->pdata, CD_MTEXPOLY, layernum);
231                         CustomData_set_layer_active(&me->ldata, CD_MLOOPUV, layernum);
232                 }
233                 
234                 mesh_update_customdata_pointers(me);
235         }
236
237         DAG_id_tag_update(&me->id, 0);
238         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
239
240         return 1;
241 }
242
243 int ED_mesh_uv_texture_remove(bContext *C, Object *ob, Mesh *me)
244 {
245         CustomData *pdata = GET_CD_DATA(me, pdata), *ldata = GET_CD_DATA(me, ldata);
246         CustomDataLayer *cdlp, *cdlu;
247         int index;
248
249         index= CustomData_get_active_layer_index(pdata, CD_MTEXPOLY);
250         cdlp= (index == -1)? NULL: &pdata->layers[index];
251
252         index= CustomData_get_active_layer_index(ldata, CD_MLOOPUV);
253         cdlu= (index == -1)? NULL: &ldata->layers[index];
254         
255         if (!cdlp || !cdlu)
256                 return 0;
257
258         delete_customdata_layer(C, ob, cdlp);
259         delete_customdata_layer(C, ob, cdlu);
260         
261         DAG_id_tag_update(&me->id, 0);
262         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
263
264         return 1;
265 }
266
267 int ED_mesh_color_add(bContext *C, Scene *UNUSED(scene), Object *UNUSED(ob), Mesh *me, const char *name, int active_set)
268 {
269         BMEditMesh *em;
270         MLoopCol *mcol;
271         int layernum;
272
273         if(me->edit_btmesh) {
274                 em= me->edit_btmesh;
275
276                 layernum= CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPCOL);
277                 if(layernum >= MAX_MCOL)
278                         return 0;
279
280                 BM_add_data_layer(em->bm, &em->bm->pdata, CD_MLOOPCOL);
281                 CustomData_set_layer_active(&em->bm->ldata, CD_MLOOPCOL, layernum);
282
283
284                 if(layernum) /* copy data from active vertex color layer */
285                         copy_editface_active_customdata(em, CD_MCOL, layernum);
286
287                 if(active_set || layernum==0)
288                         CustomData_set_layer_active(&em->bm->ldata, CD_MLOOPCOL, layernum);
289
290         }
291         else {
292                 layernum= CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
293                 if(layernum >= CD_MLOOPCOL)
294                         return 0;
295
296                 mcol= me->mloopcol;
297
298                 if(me->mloopcol)
299                         CustomData_add_layer_named(&me->ldata, CD_MLOOPCOL, CD_DUPLICATE, me->mloopcol, me->totloop, name);
300                 else
301                         CustomData_add_layer_named(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop, name);
302
303                 if(active_set || layernum==0)
304                         CustomData_set_layer_active(&me->ldata, CD_MLOOPCOL, layernum);
305
306                 mesh_update_customdata_pointers(me);
307
308                 /*BMESH_TODO
309                 if(!mcol)
310                         shadeMeshMCol(scene, ob, me);
311                 */
312         }
313
314         DAG_id_tag_update(&me->id, 0);
315         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
316
317         return 1;
318 }
319
320 int ED_mesh_color_remove(bContext *C, Object *ob, Mesh *me)
321 {
322         CustomDataLayer *cdl;
323         int index;
324
325         index= CustomData_get_active_layer_index(&me->ldata, CD_MLOOPCOL);
326         cdl= (index == -1)? NULL: &me->ldata.layers[index];
327
328         if(!cdl)
329                 return 0;
330
331         delete_customdata_layer(C, ob, cdl);
332         DAG_id_tag_update(&me->id, 0);
333         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
334
335         return 1;
336 }
337
338 /*********************** UV texture operators ************************/
339
340 static int layers_poll(bContext *C)
341 {
342         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
343         ID *data= (ob)? ob->data: NULL;
344         return (ob && !ob->id.lib && ob->type==OB_MESH && data && !data->lib);
345 }
346
347 static int uv_texture_add_exec(bContext *C, wmOperator *UNUSED(op))
348 {
349         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
350         Mesh *me= ob->data;
351
352         if(!ED_mesh_uv_texture_add(C, me, NULL, TRUE))
353                 return OPERATOR_CANCELLED;
354
355         return OPERATOR_FINISHED;
356 }
357
358 void MESH_OT_uv_texture_add(wmOperatorType *ot)
359 {
360         /* identifiers */
361         ot->name= "Add UV Texture";
362         ot->description= "Add UV texture layer";
363         ot->idname= "MESH_OT_uv_texture_add";
364         
365         /* api callbacks */
366         ot->poll= layers_poll;
367         ot->exec= uv_texture_add_exec;
368
369         /* flags */
370         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
371 }
372
373 static int drop_named_image_invoke(bContext *C, wmOperator *op, wmEvent *event)
374 {
375         Scene *scene= CTX_data_scene(C);
376         View3D *v3d= CTX_wm_view3d(C);
377         Base *base= ED_view3d_give_base_under_cursor(C, event->mval);
378         Image *ima= NULL;
379         Mesh *me;
380         Object *obedit;
381         int exitmode= 0;
382         char name[32];
383         
384         /* Check context */
385         if(base==NULL || base->object->type!=OB_MESH) {
386                 BKE_report(op->reports, RPT_ERROR, "Not an Object or Mesh");
387                 return OPERATOR_CANCELLED;
388         }
389         
390         /* check input variables */
391         if(RNA_property_is_set(op->ptr, "filepath")) {
392                 char path[FILE_MAX];
393                 
394                 RNA_string_get(op->ptr, "filepath", path);
395                 ima= BKE_add_image_file(path);
396         }
397         else {
398                 RNA_string_get(op->ptr, "name", name);
399                 ima= (Image *)find_id("IM", name);
400         }
401         
402         if(!ima) {
403                 BKE_report(op->reports, RPT_ERROR, "Not an Image.");
404                 return OPERATOR_CANCELLED;
405         }
406         
407         /* put mesh in editmode */
408
409         obedit= base->object;
410         me= obedit->data;
411         if(me->edit_btmesh==NULL) {
412                 EDBM_MakeEditBMesh(scene->toolsettings, scene, obedit);
413                 exitmode= 1;
414         }
415
416         if(me->edit_btmesh==NULL)
417                 return OPERATOR_CANCELLED;
418         
419         ED_uvedit_assign_image(scene, obedit, ima, NULL);
420
421         if(exitmode) {
422                 EDBM_LoadEditBMesh(scene, obedit);
423                 EDBM_FreeEditBMesh(me->edit_btmesh);
424                 MEM_freeN(me->edit_btmesh);
425                 me->edit_btmesh= NULL;
426         }
427
428         /* dummie drop support; ensure view shows a result :) */
429         if(v3d)
430                 v3d->flag2 |= V3D_SOLID_TEX;
431         
432         WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
433         
434         return OPERATOR_FINISHED;
435 }
436
437 void MESH_OT_drop_named_image(wmOperatorType *ot)
438 {
439         /* identifiers */
440         ot->name= "Assign Image to UV Texture";
441         ot->description= "Assigns Image to active UV layer, or creates a UV layer";
442         ot->idname= "MESH_OT_drop_named_image";
443         
444         /* api callbacks */
445         ot->poll= layers_poll;
446         ot->invoke= drop_named_image_invoke;
447         
448         /* flags */
449         ot->flag= OPTYPE_UNDO;
450         
451         /* properties */
452         RNA_def_string(ot->srna, "name", "Image", 24, "Name", "Image name to assign.");
453         RNA_def_string(ot->srna, "filepath", "Path", FILE_MAX, "Filepath", "Path to image file");
454 }
455
456 static int uv_texture_remove_exec(bContext *C, wmOperator *UNUSED(op))
457 {
458         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
459         Mesh *me= ob->data;
460
461         if(!ED_mesh_uv_texture_remove(C, ob, me))
462                 return OPERATOR_CANCELLED;
463
464         return OPERATOR_FINISHED;
465 }
466
467 void MESH_OT_uv_texture_remove(wmOperatorType *ot)
468 {
469         /* identifiers */
470         ot->name= "Remove UV Texture";
471         ot->description= "Remove UV texture layer";
472         ot->idname= "MESH_OT_uv_texture_remove";
473         
474         /* api callbacks */
475         ot->poll= layers_poll;
476         ot->exec= uv_texture_remove_exec;
477
478         /* flags */
479         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
480 }
481
482 /*********************** vertex color operators ************************/
483
484 static int vertex_color_add_exec(bContext *C, wmOperator *UNUSED(op))
485 {
486         Scene *scene= CTX_data_scene(C);
487         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
488         Mesh *me= ob->data;
489
490         if(!ED_mesh_color_add(C, scene, ob, me, NULL, TRUE))
491                 return OPERATOR_CANCELLED;
492
493         return OPERATOR_FINISHED;
494 }
495
496 void MESH_OT_vertex_color_add(wmOperatorType *ot)
497 {
498         /* identifiers */
499         ot->name= "Add Vertex Color";
500         ot->description= "Add vertex color layer";
501         ot->idname= "MESH_OT_vertex_color_add";
502         
503         /* api callbacks */
504         ot->poll= layers_poll;
505         ot->exec= vertex_color_add_exec;
506
507         /* flags */
508         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
509 }
510
511 static int vertex_color_remove_exec(bContext *C, wmOperator *UNUSED(op))
512 {
513         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
514         Mesh *me= ob->data;
515
516         if(!ED_mesh_color_remove(C, ob, me))
517                 return OPERATOR_CANCELLED;
518
519         return OPERATOR_FINISHED;
520 }
521
522 void MESH_OT_vertex_color_remove(wmOperatorType *ot)
523 {
524         /* identifiers */
525         ot->name= "Remove Vertex Color";
526         ot->description= "Remove vertex color layer";
527         ot->idname= "MESH_OT_vertex_color_remove";
528         
529         /* api callbacks */
530         ot->exec= vertex_color_remove_exec;
531         ot->poll= layers_poll;
532
533         /* flags */
534         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
535 }
536
537 /*********************** sticky operators ************************/
538
539 static int sticky_add_exec(bContext *C, wmOperator *UNUSED(op))
540 {
541         Scene *scene= CTX_data_scene(C);
542         View3D *v3d= CTX_wm_view3d(C);
543         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
544         Mesh *me= ob->data;
545
546         /*if(me->msticky)
547                 return OPERATOR_CANCELLED;*/
548
549         RE_make_sticky(scene, v3d);
550
551         DAG_id_tag_update(&me->id, 0);
552         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
553
554         return OPERATOR_FINISHED;
555 }
556
557 void MESH_OT_sticky_add(wmOperatorType *ot)
558 {
559         /* identifiers */
560         ot->name= "Add Sticky";
561         ot->description= "Add sticky UV texture layer";
562         ot->idname= "MESH_OT_sticky_add";
563         
564         /* api callbacks */
565         ot->poll= layers_poll;
566         ot->exec= sticky_add_exec;
567
568         /* flags */
569         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
570 }
571
572 static int sticky_remove_exec(bContext *C, wmOperator *UNUSED(op))
573 {
574         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
575         Mesh *me= ob->data;
576
577         if(!me->msticky)
578                 return OPERATOR_CANCELLED;
579
580         CustomData_free_layer_active(&me->vdata, CD_MSTICKY, me->totvert);
581         me->msticky= NULL;
582
583         DAG_id_tag_update(&me->id, 0);
584         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
585
586         return OPERATOR_FINISHED;
587 }
588
589 void MESH_OT_sticky_remove(wmOperatorType *ot)
590 {
591         /* identifiers */
592         ot->name= "Remove Sticky";
593         ot->description= "Remove sticky UV texture layer";
594         ot->idname= "MESH_OT_sticky_remove";
595         
596         /* api callbacks */
597         ot->poll= layers_poll;
598         ot->exec= sticky_remove_exec;
599
600         /* flags */
601         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
602 }
603
604 /************************** Add Geometry Layers *************************/
605
606 void ED_mesh_update(Mesh *mesh, bContext *C, int calc_edges)
607 {
608         if(calc_edges || (mesh->totface && mesh->totedge == 0))
609                 BKE_mesh_calc_edges(mesh, calc_edges);
610
611         mesh_calc_normals(mesh->mvert, mesh->totvert, mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly, NULL, NULL, 0, NULL, NULL);
612
613         DAG_id_tag_update(&mesh->id, 0);
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 *mesh, float *mat)
648 {
649         int i;
650         MVert *mvert= mesh->mvert;
651
652         for(i= 0; i < mesh->totvert; i++, mvert++)
653                 mul_m4_v3((float (*)[4])mat, mvert->co);
654
655         mesh_calc_normals(mesh->mvert, mesh->totvert, mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly, NULL, NULL, 0, NULL, 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 /*
719 void ED_mesh_geometry_add(Mesh *mesh, ReportList *reports, int verts, int edges, int faces)
720 {
721         if(mesh->edit_btmesh) {
722                 BKE_report(reports, RPT_ERROR, "Can't add geometry in edit mode.");
723                 return;
724         }
725
726         if(verts)
727                 mesh_add_verts(mesh, verts);
728         if(edges)
729                 mesh_add_edges(mesh, edges);
730         if(faces)
731                 mesh_add_faces(mesh, faces);
732 }
733 */
734
735 void ED_mesh_faces_add(Mesh *mesh, ReportList *reports, int count)
736 {
737         if(mesh->edit_btmesh) {
738                 BKE_report(reports, RPT_ERROR, "Can't add faces in edit mode.");
739                 return;
740         }
741         mesh_add_faces(mesh, count);
742 }
743
744 void ED_mesh_edges_add(Mesh *mesh, ReportList *reports, int count)
745 {
746         if(mesh->edit_btmesh) {
747                 BKE_report(reports, RPT_ERROR, "Can't add edges in edit mode.");
748                         return;
749         }
750
751         mesh_add_edges(mesh, count);
752 }
753
754 void ED_mesh_vertices_add(Mesh *mesh, ReportList *reports, int count)
755 {
756         if(mesh->edit_btmesh) {
757                 BKE_report(reports, RPT_ERROR, "Can't add vertices in edit mode.");
758                 return;
759         }
760
761         mesh_add_verts(mesh, count);
762 }
763
764 void ED_mesh_calc_normals(Mesh *mesh)
765 {
766         mesh_calc_normals(mesh->mvert, mesh->totvert, mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly, NULL, NULL, 0, NULL, NULL);
767 }
768