Fixed typo in tracking context creation. Wasn't harmful because because of definition...
[blender.git] / source / blender / editors / mesh / mesh_data.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2009 Blender Foundation.
19  * All rights reserved.
20  *
21  * 
22  * Contributor(s): Blender Foundation
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/editors/mesh/mesh_data.c
28  *  \ingroup edmesh
29  */
30
31
32 #include <math.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #include "MEM_guardedalloc.h"
37
38 #include "DNA_material_types.h"
39 #include "DNA_meshdata_types.h"
40 #include "DNA_object_types.h"
41 #include "DNA_scene_types.h"
42 #include "DNA_view3d_types.h"
43
44 #include "BLI_math.h"
45 #include "BLI_editVert.h"
46 #include "BLI_edgehash.h"
47 #include "BLI_utildefines.h"
48
49 #include "BKE_context.h"
50 #include "BKE_depsgraph.h"
51 #include "BKE_displist.h"
52 #include "BKE_image.h"
53 #include "BKE_library.h"
54 #include "BKE_main.h"
55 #include "BKE_material.h"
56 #include "BKE_mesh.h"
57 #include "BKE_report.h"
58
59 #include "RNA_access.h"
60 #include "RNA_define.h"
61
62 #include "WM_api.h"
63 #include "WM_types.h"
64
65 #include "ED_mesh.h"
66 #include "ED_object.h"
67 #include "ED_uvedit.h"
68 #include "ED_view3d.h"
69
70 #include "RE_render_ext.h"
71
72 #include "mesh_intern.h"
73
74 static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *layer)
75 {
76         Mesh *me = ob->data;
77         CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
78         void *actlayerdata, *rndlayerdata, *clonelayerdata, *stencillayerdata, *layerdata=layer->data;
79         int type= layer->type;
80         int index= CustomData_get_layer_index(data, type);
81         int i, actindex, rndindex, cloneindex, stencilindex;
82         
83         /* ok, deleting a non-active layer needs to preserve the active layer indices.
84           to do this, we store a pointer to the .data member of both layer and the active layer,
85           (to detect if we're deleting the active layer or not), then use the active
86           layer data pointer to find where the active layer has ended up.
87           
88           this is necassary because the deletion functions only support deleting the active
89           layer. */
90         actlayerdata = data->layers[CustomData_get_active_layer_index(data, type)].data;
91         rndlayerdata = data->layers[CustomData_get_render_layer_index(data, type)].data;
92         clonelayerdata = data->layers[CustomData_get_clone_layer_index(data, type)].data;
93         stencillayerdata = data->layers[CustomData_get_stencil_layer_index(data, type)].data;
94         CustomData_set_layer_active(data, type, layer - &data->layers[index]);
95
96         if(me->edit_mesh) {
97                 EM_free_data_layer(me->edit_mesh, data, type);
98         }
99         else {
100                 CustomData_free_layer_active(data, type, me->totface);
101                 mesh_update_customdata_pointers(me);
102         }
103
104         if(!CustomData_has_layer(data, type) && (type == CD_MCOL && (ob->mode & OB_MODE_VERTEX_PAINT)))
105                 ED_object_toggle_modes(C, OB_MODE_VERTEX_PAINT);
106
107         /* reconstruct active layer */
108         if (actlayerdata != layerdata) {
109                 /* find index */
110                 actindex = CustomData_get_layer_index(data, type);
111                 for (i=actindex; i<data->totlayer; i++) {
112                         if (data->layers[i].data == actlayerdata) {
113                                 actindex = i - actindex;
114                                 break;
115                         }
116                 }
117                 
118                 /* set index */
119                 CustomData_set_layer_active(data, type, actindex);
120         }
121         
122         if (rndlayerdata != layerdata) {
123                 /* find index */
124                 rndindex = CustomData_get_layer_index(data, type);
125                 for (i=rndindex; i<data->totlayer; i++) {
126                         if (data->layers[i].data == rndlayerdata) {
127                                 rndindex = i - rndindex;
128                                 break;
129                         }
130                 }
131                 
132                 /* set index */
133                 CustomData_set_layer_render(data, type, rndindex);
134         }
135         
136         if (clonelayerdata != layerdata) {
137                 /* find index */
138                 cloneindex = CustomData_get_layer_index(data, type);
139                 for (i=cloneindex; i<data->totlayer; i++) {
140                         if (data->layers[i].data == clonelayerdata) {
141                                 cloneindex = i - cloneindex;
142                                 break;
143                         }
144                 }
145                 
146                 /* set index */
147                 CustomData_set_layer_clone(data, type, cloneindex);
148         }
149         
150         if (stencillayerdata != layerdata) {
151                 /* find index */
152                 stencilindex = CustomData_get_layer_index(data, type);
153                 for (i=stencilindex; i<data->totlayer; i++) {
154                         if (data->layers[i].data == stencillayerdata) {
155                                 stencilindex = i - stencilindex;
156                                 break;
157                         }
158                 }
159                 
160                 /* set index */
161                 CustomData_set_layer_stencil(data, type, stencilindex);
162         }
163 }
164
165 static void copy_editface_active_customdata(EditMesh *em, int type, int index)
166 {
167         EditFace *efa;
168         int n= CustomData_get_active_layer(&em->fdata, type);
169
170         for(efa= em->faces.first; efa; efa= efa->next) {
171                 void *data= CustomData_em_get_n(&em->fdata, efa->data, type, n);
172                 CustomData_em_set_n(&em->fdata, efa->data, type, index, data);
173         }
174 }
175
176 int ED_mesh_uv_texture_add(bContext *C, Mesh *me, const char *name, int active_set)
177 {
178         EditMesh *em;
179         int layernum;
180
181         if(me->edit_mesh) {
182                 em= me->edit_mesh;
183
184                 layernum= CustomData_number_of_layers(&em->fdata, CD_MTFACE);
185                 if(layernum >= MAX_MTFACE)
186                         return -1;
187
188                 EM_add_data_layer(em, &em->fdata, CD_MTFACE, name);
189
190                 if(layernum) /* copy data from active UV */
191                         copy_editface_active_customdata(em, CD_MTFACE, layernum);
192
193                 if(active_set || layernum==0)
194                         CustomData_set_layer_active(&em->fdata, CD_MTFACE, layernum);
195         }
196         else {
197                 layernum= CustomData_number_of_layers(&me->fdata, CD_MTFACE);
198                 if(layernum >= MAX_MTFACE)
199                         return -1;
200
201                 if(me->mtface)
202                         CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_DUPLICATE, me->mtface, me->totface, name);
203                 else
204                         CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_DEFAULT, NULL, me->totface, name);
205
206                 if(active_set || layernum==0)
207                         CustomData_set_layer_active(&me->fdata, CD_MTFACE, layernum);
208
209                 mesh_update_customdata_pointers(me);
210         }
211
212         DAG_id_tag_update(&me->id, 0);
213         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
214
215         return layernum;
216 }
217
218 int ED_mesh_uv_texture_remove(bContext *C, Object *ob, Mesh *me)
219 {
220         CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
221         CustomDataLayer *cdl;
222         int index;
223
224         index= CustomData_get_active_layer_index(data, CD_MTFACE);
225         cdl= (index == -1) ? NULL: &data->layers[index];
226
227         if(!cdl)
228                 return 0;
229
230         delete_customdata_layer(C, ob, cdl);
231         DAG_id_tag_update(&me->id, 0);
232         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
233
234         return 1;
235 }
236
237 int ED_mesh_color_add(bContext *C, Scene *UNUSED(scene), Object *UNUSED(ob), Mesh *me, const char *name, int active_set)
238 {
239         EditMesh *em;
240         int layernum;
241
242         if(me->edit_mesh) {
243                 em= me->edit_mesh;
244
245                 layernum= CustomData_number_of_layers(&em->fdata, CD_MCOL);
246                 if(layernum >= MAX_MCOL)
247                         return -1;
248
249                 EM_add_data_layer(em, &em->fdata, CD_MCOL, name);
250
251                 if(layernum) /* copy data from active vertex color layer */
252                         copy_editface_active_customdata(em, CD_MCOL, layernum);
253
254                 if(active_set || layernum==0)
255                         CustomData_set_layer_active(&em->fdata, CD_MCOL, layernum);
256         }
257         else {
258                 layernum= CustomData_number_of_layers(&me->fdata, CD_MCOL);
259                 if(layernum >= MAX_MCOL)
260                         return -1;
261
262                 if(me->mcol)
263                         CustomData_add_layer_named(&me->fdata, CD_MCOL, CD_DUPLICATE, me->mcol, me->totface, name);
264                 else
265                         CustomData_add_layer_named(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface, name);
266
267                 if(active_set || layernum==0)
268                         CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum);
269
270                 mesh_update_customdata_pointers(me);
271         }
272
273         DAG_id_tag_update(&me->id, 0);
274         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
275
276         return layernum;
277 }
278
279 int ED_mesh_color_remove(bContext *C, Object *ob, Mesh *me)
280 {
281         CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
282         CustomDataLayer *cdl;
283         int index;
284
285         index= CustomData_get_active_layer_index(data, CD_MCOL);
286         cdl= (index == -1)? NULL: &data->layers[index];
287
288         if(!cdl)
289                 return 0;
290
291         delete_customdata_layer(C, ob, cdl);
292         DAG_id_tag_update(&me->id, 0);
293         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
294
295         return 1;
296 }
297
298 int ED_mesh_color_remove_named(bContext *C, Object *ob, Mesh *me, const char *name)
299 {
300         CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
301         CustomDataLayer *cdl;
302         int index;
303
304         index= CustomData_get_named_layer_index(data, CD_MCOL, name);
305         cdl= (index == -1)? NULL: &data->layers[index];
306
307         if(!cdl)
308                 return 0;
309
310         delete_customdata_layer(C, ob, cdl);
311         DAG_id_tag_update(&me->id, 0);
312         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
313
314         return 1;
315 }
316
317 /*********************** UV texture operators ************************/
318
319 static int layers_poll(bContext *C)
320 {
321         Object *ob= ED_object_context(C);
322         ID *data= (ob)? ob->data: NULL;
323         return (ob && !ob->id.lib && ob->type==OB_MESH && data && !data->lib);
324 }
325
326 static int uv_texture_add_exec(bContext *C, wmOperator *UNUSED(op))
327 {
328         Object *ob= ED_object_context(C);
329         Mesh *me= ob->data;
330
331         if(ED_mesh_uv_texture_add(C, me, NULL, TRUE) == -1)
332                 return OPERATOR_CANCELLED;
333
334         return OPERATOR_FINISHED;
335 }
336
337 void MESH_OT_uv_texture_add(wmOperatorType *ot)
338 {
339         /* identifiers */
340         ot->name= "Add UV Map";
341         ot->description= "Add UV Map";
342         ot->idname= "MESH_OT_uv_texture_add";
343         
344         /* api callbacks */
345         ot->poll= layers_poll;
346         ot->exec= uv_texture_add_exec;
347
348         /* flags */
349         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
350 }
351
352 static int drop_named_image_invoke(bContext *C, wmOperator *op, wmEvent *event)
353 {
354         Main *bmain= CTX_data_main(C);
355         Scene *scene= CTX_data_scene(C);
356         View3D *v3d= CTX_wm_view3d(C);
357         Base *base= ED_view3d_give_base_under_cursor(C, event->mval);
358         Image *ima= NULL;
359         Mesh *me;
360         Object *obedit;
361         int exitmode= 0;
362         char name[MAX_ID_NAME-2];
363         
364         /* Check context */
365         if(base==NULL || base->object->type!=OB_MESH) {
366                 BKE_report(op->reports, RPT_ERROR, "Not an Object or Mesh");
367                 return OPERATOR_CANCELLED;
368         }
369         
370         /* check input variables */
371         if(RNA_struct_property_is_set(op->ptr, "filepath")) {
372                 char path[FILE_MAX];
373                 
374                 RNA_string_get(op->ptr, "filepath", path);
375                 ima= BKE_add_image_file(path);
376         }
377         else {
378                 RNA_string_get(op->ptr, "name", name);
379                 ima= (Image *)find_id("IM", name);
380         }
381         
382         if(!ima) {
383                 BKE_report(op->reports, RPT_ERROR, "Not an Image");
384                 return OPERATOR_CANCELLED;
385         }
386         
387         /* turn mesh in editmode */
388         /* BKE_mesh_get/end_editmesh: ED_uvedit_assign_image also calls this */
389
390         obedit= base->object;
391         me= obedit->data;
392         if(me->edit_mesh==NULL) {
393                 make_editMesh(scene, obedit);
394                 exitmode= 1;
395         }
396         if(me->edit_mesh==NULL)
397                 return OPERATOR_CANCELLED;
398         
399         ED_uvedit_assign_image(bmain, scene, obedit, ima, NULL);
400
401         if(exitmode) {
402                 load_editMesh(scene, obedit);
403                 free_editMesh(me->edit_mesh);
404                 MEM_freeN(me->edit_mesh);
405                 me->edit_mesh= NULL;
406         }
407
408         /* dummie drop support; ensure view shows a result :) */
409         if(v3d)
410                 v3d->flag2 |= V3D_SOLID_TEX;
411         
412         WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
413         
414         return OPERATOR_FINISHED;
415 }
416
417 void MESH_OT_drop_named_image(wmOperatorType *ot)
418 {
419         /* identifiers */
420         ot->name= "Assign Image to UV Map";
421         ot->description= "Assign Image to active UV Map, or create an UV Map";
422         ot->idname= "MESH_OT_drop_named_image";
423         
424         /* api callbacks */
425         ot->poll= layers_poll;
426         ot->invoke= drop_named_image_invoke;
427         
428         /* flags */
429         ot->flag= OPTYPE_UNDO;
430         
431         /* properties */
432         RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME-2, "Name", "Image name to assign");
433         RNA_def_string(ot->srna, "filepath", "Path", FILE_MAX, "Filepath", "Path to image file");
434 }
435
436 static int uv_texture_remove_exec(bContext *C, wmOperator *UNUSED(op))
437 {
438         Object *ob= ED_object_context(C);
439         Mesh *me= ob->data;
440
441         if(!ED_mesh_uv_texture_remove(C, ob, me))
442                 return OPERATOR_CANCELLED;
443
444         return OPERATOR_FINISHED;
445 }
446
447 void MESH_OT_uv_texture_remove(wmOperatorType *ot)
448 {
449         /* identifiers */
450         ot->name= "Remove UV Map";
451         ot->description= "Remove UV Map";
452         ot->idname= "MESH_OT_uv_texture_remove";
453         
454         /* api callbacks */
455         ot->poll= layers_poll;
456         ot->exec= uv_texture_remove_exec;
457
458         /* flags */
459         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
460 }
461
462 /*********************** vertex color operators ************************/
463
464 static int vertex_color_add_exec(bContext *C, wmOperator *UNUSED(op))
465 {
466         Scene *scene= CTX_data_scene(C);
467         Object *ob= ED_object_context(C);
468         Mesh *me= ob->data;
469
470         if(ED_mesh_color_add(C, scene, ob, me, NULL, TRUE) == -1)
471                 return OPERATOR_CANCELLED;
472
473         return OPERATOR_FINISHED;
474 }
475
476 void MESH_OT_vertex_color_add(wmOperatorType *ot)
477 {
478         /* identifiers */
479         ot->name= "Add Vertex Color";
480         ot->description= "Add vertex color layer";
481         ot->idname= "MESH_OT_vertex_color_add";
482         
483         /* api callbacks */
484         ot->poll= layers_poll;
485         ot->exec= vertex_color_add_exec;
486
487         /* flags */
488         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
489 }
490
491 static int vertex_color_remove_exec(bContext *C, wmOperator *UNUSED(op))
492 {
493         Object *ob= ED_object_context(C);
494         Mesh *me= ob->data;
495
496         if(!ED_mesh_color_remove(C, ob, me))
497                 return OPERATOR_CANCELLED;
498
499         return OPERATOR_FINISHED;
500 }
501
502 void MESH_OT_vertex_color_remove(wmOperatorType *ot)
503 {
504         /* identifiers */
505         ot->name= "Remove Vertex Color";
506         ot->description= "Remove vertex color layer";
507         ot->idname= "MESH_OT_vertex_color_remove";
508         
509         /* api callbacks */
510         ot->exec= vertex_color_remove_exec;
511         ot->poll= layers_poll;
512
513         /* flags */
514         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
515 }
516
517 /*********************** sticky operators ************************/
518
519 static int sticky_add_exec(bContext *C, wmOperator *UNUSED(op))
520 {
521         Scene *scene= CTX_data_scene(C);
522         View3D *v3d= CTX_wm_view3d(C);
523         Object *ob= ED_object_context(C);
524         Mesh *me= ob->data;
525
526         /*if(me->msticky)
527                 return OPERATOR_CANCELLED;*/
528
529         RE_make_sticky(scene, v3d);
530
531         DAG_id_tag_update(&me->id, 0);
532         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
533
534         return OPERATOR_FINISHED;
535 }
536
537 void MESH_OT_sticky_add(wmOperatorType *ot)
538 {
539         /* identifiers */
540         ot->name= "Add Sticky";
541         ot->description= "Add sticky UV texture layer";
542         ot->idname= "MESH_OT_sticky_add";
543         
544         /* api callbacks */
545         ot->poll= layers_poll;
546         ot->exec= sticky_add_exec;
547
548         /* flags */
549         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
550 }
551
552 static int sticky_remove_exec(bContext *C, wmOperator *UNUSED(op))
553 {
554         Object *ob= ED_object_context(C);
555         Mesh *me= ob->data;
556
557         if(!me->msticky)
558                 return OPERATOR_CANCELLED;
559
560         CustomData_free_layer_active(&me->vdata, CD_MSTICKY, me->totvert);
561         me->msticky= NULL;
562
563         DAG_id_tag_update(&me->id, 0);
564         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
565
566         return OPERATOR_FINISHED;
567 }
568
569 void MESH_OT_sticky_remove(wmOperatorType *ot)
570 {
571         /* identifiers */
572         ot->name= "Remove Sticky";
573         ot->description= "Remove sticky UV texture layer";
574         ot->idname= "MESH_OT_sticky_remove";
575         
576         /* api callbacks */
577         ot->poll= layers_poll;
578         ot->exec= sticky_remove_exec;
579
580         /* flags */
581         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
582 }
583
584 /************************** Add Geometry Layers *************************/
585
586 void ED_mesh_update(Mesh *mesh, bContext *C, int calc_edges)
587 {
588         if(calc_edges || (mesh->totface && mesh->totedge == 0))
589                 BKE_mesh_calc_edges(mesh, calc_edges);
590
591         mesh_calc_normals(mesh->mvert, mesh->totvert, mesh->mface, mesh->totface, NULL);
592
593         DAG_id_tag_update(&mesh->id, 0);
594         WM_event_add_notifier(C, NC_GEOM|ND_DATA, mesh);
595 }
596
597 static void mesh_add_verts(Mesh *mesh, int len)
598 {
599         CustomData vdata;
600         MVert *mvert;
601         int i, totvert;
602
603         if(len == 0)
604                 return;
605
606         totvert= mesh->totvert + len;
607         CustomData_copy(&mesh->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert);
608         CustomData_copy_data(&mesh->vdata, &vdata, 0, 0, mesh->totvert);
609
610         if(!CustomData_has_layer(&vdata, CD_MVERT))
611                 CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
612
613         CustomData_free(&mesh->vdata, mesh->totvert);
614         mesh->vdata= vdata;
615         mesh_update_customdata_pointers(mesh);
616
617         /* scan the input list and insert the new vertices */
618
619         mvert= &mesh->mvert[mesh->totvert];
620         for(i=0; i<len; i++, mvert++)
621                 mvert->flag |= SELECT;
622
623         /* set final vertex list size */
624         mesh->totvert= totvert;
625 }
626
627 void ED_mesh_transform(Mesh *me, float *mat)
628 {
629         int i;
630         MVert *mvert= me->mvert;
631
632         for(i= 0; i < me->totvert; i++, mvert++)
633                 mul_m4_v3((float (*)[4])mat, mvert->co);
634
635         mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
636 }
637
638 static void mesh_add_edges(Mesh *mesh, int len)
639 {
640         CustomData edata;
641         MEdge *medge;
642         int i, totedge;
643
644         if(len == 0)
645                 return;
646
647         totedge= mesh->totedge+len;
648
649         /* update customdata  */
650         CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge);
651         CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge);
652
653         if(!CustomData_has_layer(&edata, CD_MEDGE))
654                 CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
655
656         CustomData_free(&mesh->edata, mesh->totedge);
657         mesh->edata= edata;
658         mesh_update_customdata_pointers(mesh);
659
660         /* set default flags */
661         medge= &mesh->medge[mesh->totedge];
662         for(i=0; i<len; i++, medge++)
663                 medge->flag= ME_EDGEDRAW|ME_EDGERENDER|SELECT;
664
665         mesh->totedge= totedge;
666 }
667
668 static void mesh_add_faces(Mesh *mesh, int len)
669 {
670         CustomData fdata;
671         MFace *mface;
672         int i, totface;
673
674         if(len == 0)
675                 return;
676
677         totface= mesh->totface + len;   /* new face count */
678
679         /* update customdata */
680         CustomData_copy(&mesh->fdata, &fdata, CD_MASK_MESH, CD_DEFAULT, totface);
681         CustomData_copy_data(&mesh->fdata, &fdata, 0, 0, mesh->totface);
682
683         if(!CustomData_has_layer(&fdata, CD_MFACE))
684                 CustomData_add_layer(&fdata, CD_MFACE, CD_CALLOC, NULL, totface);
685
686         CustomData_free(&mesh->fdata, mesh->totface);
687         mesh->fdata= fdata;
688         mesh_update_customdata_pointers(mesh);
689
690         /* set default flags */
691         mface= &mesh->mface[mesh->totface];
692         for(i=0; i<len; i++, mface++)
693                 mface->flag= ME_FACE_SEL;
694
695         mesh->totface= totface;
696 }
697
698 static void mesh_remove_verts(Mesh *mesh, int len)
699 {
700         int totvert;
701
702         if(len == 0)
703                 return;
704
705         totvert= mesh->totvert - len;
706         CustomData_free_elem(&mesh->vdata, totvert, len);
707
708         /* set final vertex list size */
709         mesh->totvert= totvert;
710 }
711
712 static void mesh_remove_edges(Mesh *mesh, int len)
713 {
714         int totedge;
715
716         if(len == 0)
717                 return;
718
719         totedge= mesh->totedge - len;
720         CustomData_free_elem(&mesh->edata, totedge, len);
721
722         mesh->totedge= totedge;
723 }
724
725 static void mesh_remove_faces(Mesh *mesh, int len)
726 {
727         int totface;
728
729         if(len == 0)
730                 return;
731
732         totface= mesh->totface - len;   /* new face count */
733         CustomData_free_elem(&mesh->fdata, totface, len);
734
735         mesh->totface= totface;
736 }
737
738 /*
739 void ED_mesh_geometry_add(Mesh *mesh, ReportList *reports, int verts, int edges, int faces)
740 {
741         if(mesh->edit_mesh) {
742                 BKE_report(reports, RPT_ERROR, "Can't add geometry in edit mode");
743                 return;
744         }
745
746         if(verts)
747                 mesh_add_verts(mesh, verts);
748         if(edges)
749                 mesh_add_edges(mesh, edges);
750         if(faces)
751                 mesh_add_faces(mesh, faces);
752 }
753 */
754
755 void ED_mesh_faces_add(Mesh *mesh, ReportList *reports, int count)
756 {
757         if(mesh->edit_mesh) {
758                 BKE_report(reports, RPT_ERROR, "Can't add faces in edit mode");
759                 return;
760         }
761
762         mesh_add_faces(mesh, count);
763 }
764
765 void ED_mesh_edges_add(Mesh *mesh, ReportList *reports, int count)
766 {
767         if(mesh->edit_mesh) {
768                 BKE_report(reports, RPT_ERROR, "Can't add edges in edit mode");
769                 return;
770         }
771
772         mesh_add_edges(mesh, count);
773 }
774
775 void ED_mesh_vertices_add(Mesh *mesh, ReportList *reports, int count)
776 {
777         if(mesh->edit_mesh) {
778                 BKE_report(reports, RPT_ERROR, "Can't add vertices in edit mode");
779                 return;
780         }
781
782         mesh_add_verts(mesh, count);
783 }
784
785 void ED_mesh_faces_remove(Mesh *mesh, ReportList *reports, int count)
786 {
787         if(mesh->edit_mesh) {
788                 BKE_report(reports, RPT_ERROR, "Can't remove faces in edit mode");
789                 return;
790         }
791         else if(count > mesh->totface) {
792                 BKE_report(reports, RPT_ERROR, "Can't remove more faces than the mesh contains");
793                 return;
794         }
795
796         mesh_remove_faces(mesh, count);
797 }
798
799 void ED_mesh_edges_remove(Mesh *mesh, ReportList *reports, int count)
800 {
801         if(mesh->edit_mesh) {
802                 BKE_report(reports, RPT_ERROR, "Can't remove edges in edit mode");
803                 return;
804         }
805         else if(count > mesh->totedge) {
806                 BKE_report(reports, RPT_ERROR, "Can't remove more edges than the mesh contains");
807                 return;
808         }
809
810         mesh_remove_edges(mesh, count);
811 }
812
813 void ED_mesh_vertices_remove(Mesh *mesh, ReportList *reports, int count)
814 {
815         if(mesh->edit_mesh) {
816                 BKE_report(reports, RPT_ERROR, "Can't remove vertices in edit mode");
817                 return;
818         }
819         else if(count > mesh->totvert) {
820                 BKE_report(reports, RPT_ERROR, "Can't remove more vertices than the mesh contains");
821                 return;
822         }
823
824         mesh_remove_verts(mesh, count);
825 }
826
827 void ED_mesh_calc_normals(Mesh *me)
828 {
829         mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
830 }