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