fix for bug introduced with weight paint vertex selection.
[blender-staging.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                 /* load_editMesh free's pointers used by CustomData layers which might be used by DerivedMesh too,
408                  * so signal to re-create DerivedMesh here (sergey) */
409                 DAG_id_tag_update(&me->id, 0);
410         }
411
412         /* dummie drop support; ensure view shows a result :) */
413         if(v3d)
414                 v3d->flag2 |= V3D_SOLID_TEX;
415         
416         WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
417         
418         return OPERATOR_FINISHED;
419 }
420
421 void MESH_OT_drop_named_image(wmOperatorType *ot)
422 {
423         /* identifiers */
424         ot->name= "Assign Image to UV Map";
425         ot->description= "Assign Image to active UV Map, or create an UV Map";
426         ot->idname= "MESH_OT_drop_named_image";
427         
428         /* api callbacks */
429         ot->poll= layers_poll;
430         ot->invoke= drop_named_image_invoke;
431         
432         /* flags */
433         ot->flag= OPTYPE_UNDO;
434         
435         /* properties */
436         RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME-2, "Name", "Image name to assign");
437         RNA_def_string(ot->srna, "filepath", "Path", FILE_MAX, "Filepath", "Path to image file");
438 }
439
440 static int uv_texture_remove_exec(bContext *C, wmOperator *UNUSED(op))
441 {
442         Object *ob= ED_object_context(C);
443         Mesh *me= ob->data;
444
445         if(!ED_mesh_uv_texture_remove(C, ob, me))
446                 return OPERATOR_CANCELLED;
447
448         return OPERATOR_FINISHED;
449 }
450
451 void MESH_OT_uv_texture_remove(wmOperatorType *ot)
452 {
453         /* identifiers */
454         ot->name= "Remove UV Map";
455         ot->description= "Remove UV Map";
456         ot->idname= "MESH_OT_uv_texture_remove";
457         
458         /* api callbacks */
459         ot->poll= layers_poll;
460         ot->exec= uv_texture_remove_exec;
461
462         /* flags */
463         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
464 }
465
466 /*********************** vertex color operators ************************/
467
468 static int vertex_color_add_exec(bContext *C, wmOperator *UNUSED(op))
469 {
470         Scene *scene= CTX_data_scene(C);
471         Object *ob= ED_object_context(C);
472         Mesh *me= ob->data;
473
474         if(ED_mesh_color_add(C, scene, ob, me, NULL, TRUE) == -1)
475                 return OPERATOR_CANCELLED;
476
477         return OPERATOR_FINISHED;
478 }
479
480 void MESH_OT_vertex_color_add(wmOperatorType *ot)
481 {
482         /* identifiers */
483         ot->name= "Add Vertex Color";
484         ot->description= "Add vertex color layer";
485         ot->idname= "MESH_OT_vertex_color_add";
486         
487         /* api callbacks */
488         ot->poll= layers_poll;
489         ot->exec= vertex_color_add_exec;
490
491         /* flags */
492         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
493 }
494
495 static int vertex_color_remove_exec(bContext *C, wmOperator *UNUSED(op))
496 {
497         Object *ob= ED_object_context(C);
498         Mesh *me= ob->data;
499
500         if(!ED_mesh_color_remove(C, ob, me))
501                 return OPERATOR_CANCELLED;
502
503         return OPERATOR_FINISHED;
504 }
505
506 void MESH_OT_vertex_color_remove(wmOperatorType *ot)
507 {
508         /* identifiers */
509         ot->name= "Remove Vertex Color";
510         ot->description= "Remove vertex color layer";
511         ot->idname= "MESH_OT_vertex_color_remove";
512         
513         /* api callbacks */
514         ot->exec= vertex_color_remove_exec;
515         ot->poll= layers_poll;
516
517         /* flags */
518         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
519 }
520
521 /*********************** sticky operators ************************/
522
523 static int sticky_add_exec(bContext *C, wmOperator *UNUSED(op))
524 {
525         Scene *scene= CTX_data_scene(C);
526         View3D *v3d= CTX_wm_view3d(C);
527         Object *ob= ED_object_context(C);
528         Mesh *me= ob->data;
529
530         /*if(me->msticky)
531                 return OPERATOR_CANCELLED;*/
532
533         RE_make_sticky(scene, v3d);
534
535         DAG_id_tag_update(&me->id, 0);
536         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
537
538         return OPERATOR_FINISHED;
539 }
540
541 void MESH_OT_sticky_add(wmOperatorType *ot)
542 {
543         /* identifiers */
544         ot->name= "Add Sticky";
545         ot->description= "Add sticky UV texture layer";
546         ot->idname= "MESH_OT_sticky_add";
547         
548         /* api callbacks */
549         ot->poll= layers_poll;
550         ot->exec= sticky_add_exec;
551
552         /* flags */
553         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
554 }
555
556 static int sticky_remove_exec(bContext *C, wmOperator *UNUSED(op))
557 {
558         Object *ob= ED_object_context(C);
559         Mesh *me= ob->data;
560
561         if(!me->msticky)
562                 return OPERATOR_CANCELLED;
563
564         CustomData_free_layer_active(&me->vdata, CD_MSTICKY, me->totvert);
565         me->msticky= NULL;
566
567         DAG_id_tag_update(&me->id, 0);
568         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
569
570         return OPERATOR_FINISHED;
571 }
572
573 void MESH_OT_sticky_remove(wmOperatorType *ot)
574 {
575         /* identifiers */
576         ot->name= "Remove Sticky";
577         ot->description= "Remove sticky UV texture layer";
578         ot->idname= "MESH_OT_sticky_remove";
579         
580         /* api callbacks */
581         ot->poll= layers_poll;
582         ot->exec= sticky_remove_exec;
583
584         /* flags */
585         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
586 }
587
588 /************************** Add Geometry Layers *************************/
589
590 void ED_mesh_update(Mesh *mesh, bContext *C, int calc_edges)
591 {
592         if(calc_edges || (mesh->totface && mesh->totedge == 0))
593                 BKE_mesh_calc_edges(mesh, calc_edges);
594
595         mesh_calc_normals(mesh->mvert, mesh->totvert, mesh->mface, mesh->totface, NULL);
596
597         DAG_id_tag_update(&mesh->id, 0);
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 static void mesh_remove_verts(Mesh *mesh, int len)
703 {
704         int totvert;
705
706         if(len == 0)
707                 return;
708
709         totvert= mesh->totvert - len;
710         CustomData_free_elem(&mesh->vdata, totvert, len);
711
712         /* set final vertex list size */
713         mesh->totvert= totvert;
714 }
715
716 static void mesh_remove_edges(Mesh *mesh, int len)
717 {
718         int totedge;
719
720         if(len == 0)
721                 return;
722
723         totedge= mesh->totedge - len;
724         CustomData_free_elem(&mesh->edata, totedge, len);
725
726         mesh->totedge= totedge;
727 }
728
729 static void mesh_remove_faces(Mesh *mesh, int len)
730 {
731         int totface;
732
733         if(len == 0)
734                 return;
735
736         totface= mesh->totface - len;   /* new face count */
737         CustomData_free_elem(&mesh->fdata, totface, len);
738
739         mesh->totface= totface;
740 }
741
742 /*
743 void ED_mesh_geometry_add(Mesh *mesh, ReportList *reports, int verts, int edges, int faces)
744 {
745         if(mesh->edit_mesh) {
746                 BKE_report(reports, RPT_ERROR, "Can't add geometry in edit mode");
747                 return;
748         }
749
750         if(verts)
751                 mesh_add_verts(mesh, verts);
752         if(edges)
753                 mesh_add_edges(mesh, edges);
754         if(faces)
755                 mesh_add_faces(mesh, faces);
756 }
757 */
758
759 void ED_mesh_faces_add(Mesh *mesh, ReportList *reports, int count)
760 {
761         if(mesh->edit_mesh) {
762                 BKE_report(reports, RPT_ERROR, "Can't add faces in edit mode");
763                 return;
764         }
765
766         mesh_add_faces(mesh, count);
767 }
768
769 void ED_mesh_edges_add(Mesh *mesh, ReportList *reports, int count)
770 {
771         if(mesh->edit_mesh) {
772                 BKE_report(reports, RPT_ERROR, "Can't add edges in edit mode");
773                 return;
774         }
775
776         mesh_add_edges(mesh, count);
777 }
778
779 void ED_mesh_vertices_add(Mesh *mesh, ReportList *reports, int count)
780 {
781         if(mesh->edit_mesh) {
782                 BKE_report(reports, RPT_ERROR, "Can't add vertices in edit mode");
783                 return;
784         }
785
786         mesh_add_verts(mesh, count);
787 }
788
789 void ED_mesh_faces_remove(Mesh *mesh, ReportList *reports, int count)
790 {
791         if(mesh->edit_mesh) {
792                 BKE_report(reports, RPT_ERROR, "Can't remove faces in edit mode");
793                 return;
794         }
795         else if(count > mesh->totface) {
796                 BKE_report(reports, RPT_ERROR, "Can't remove more faces than the mesh contains");
797                 return;
798         }
799
800         mesh_remove_faces(mesh, count);
801 }
802
803 void ED_mesh_edges_remove(Mesh *mesh, ReportList *reports, int count)
804 {
805         if(mesh->edit_mesh) {
806                 BKE_report(reports, RPT_ERROR, "Can't remove edges in edit mode");
807                 return;
808         }
809         else if(count > mesh->totedge) {
810                 BKE_report(reports, RPT_ERROR, "Can't remove more edges than the mesh contains");
811                 return;
812         }
813
814         mesh_remove_edges(mesh, count);
815 }
816
817 void ED_mesh_vertices_remove(Mesh *mesh, ReportList *reports, int count)
818 {
819         if(mesh->edit_mesh) {
820                 BKE_report(reports, RPT_ERROR, "Can't remove vertices in edit mode");
821                 return;
822         }
823         else if(count > mesh->totvert) {
824                 BKE_report(reports, RPT_ERROR, "Can't remove more vertices than the mesh contains");
825                 return;
826         }
827
828         mesh_remove_verts(mesh, count);
829 }
830
831 void ED_mesh_calc_normals(Mesh *me)
832 {
833         mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
834 }