Cycles: svn merge -r39870:r40266 https://svn.blender.org/svnroot/bf-blender/trunk...
[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_main.h"
57 #include "BKE_material.h"
58 #include "BKE_mesh.h"
59 #include "BKE_report.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 static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *layer)
77 {
78         Mesh *me = ob->data;
79         CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
80         void *actlayerdata, *rndlayerdata, *clonelayerdata, *stencillayerdata, *layerdata=layer->data;
81         int type= layer->type;
82         int index= CustomData_get_layer_index(data, type);
83         int i, actindex, rndindex, cloneindex, stencilindex;
84         
85         /* ok, deleting a non-active layer needs to preserve the active layer indices.
86           to do this, we store a pointer to the .data member of both layer and the active layer,
87           (to detect if we're deleting the active layer or not), then use the active
88           layer data pointer to find where the active layer has ended up.
89           
90           this is necassary because the deletion functions only support deleting the active
91           layer. */
92         actlayerdata = data->layers[CustomData_get_active_layer_index(data, type)].data;
93         rndlayerdata = data->layers[CustomData_get_render_layer_index(data, type)].data;
94         clonelayerdata = data->layers[CustomData_get_clone_layer_index(data, type)].data;
95         stencillayerdata = data->layers[CustomData_get_stencil_layer_index(data, type)].data;
96         CustomData_set_layer_active(data, type, layer - &data->layers[index]);
97
98         if(me->edit_mesh) {
99                 EM_free_data_layer(me->edit_mesh, data, type);
100         }
101         else {
102                 CustomData_free_layer_active(data, type, me->totface);
103                 mesh_update_customdata_pointers(me);
104         }
105
106         if(!CustomData_has_layer(data, type) && (type == CD_MCOL && (ob->mode & OB_MODE_VERTEX_PAINT)))
107                 ED_object_toggle_modes(C, OB_MODE_VERTEX_PAINT);
108
109         /* reconstruct active layer */
110         if (actlayerdata != layerdata) {
111                 /* find index */
112                 actindex = CustomData_get_layer_index(data, type);
113                 for (i=actindex; i<data->totlayer; i++) {
114                         if (data->layers[i].data == actlayerdata) {
115                                 actindex = i - actindex;
116                                 break;
117                         }
118                 }
119                 
120                 /* set index */
121                 CustomData_set_layer_active(data, type, actindex);
122         }
123         
124         if (rndlayerdata != layerdata) {
125                 /* find index */
126                 rndindex = CustomData_get_layer_index(data, type);
127                 for (i=rndindex; i<data->totlayer; i++) {
128                         if (data->layers[i].data == rndlayerdata) {
129                                 rndindex = i - rndindex;
130                                 break;
131                         }
132                 }
133                 
134                 /* set index */
135                 CustomData_set_layer_render(data, type, rndindex);
136         }
137         
138         if (clonelayerdata != layerdata) {
139                 /* find index */
140                 cloneindex = CustomData_get_layer_index(data, type);
141                 for (i=cloneindex; i<data->totlayer; i++) {
142                         if (data->layers[i].data == clonelayerdata) {
143                                 cloneindex = i - cloneindex;
144                                 break;
145                         }
146                 }
147                 
148                 /* set index */
149                 CustomData_set_layer_clone(data, type, cloneindex);
150         }
151         
152         if (stencillayerdata != layerdata) {
153                 /* find index */
154                 stencilindex = CustomData_get_layer_index(data, type);
155                 for (i=stencilindex; i<data->totlayer; i++) {
156                         if (data->layers[i].data == stencillayerdata) {
157                                 stencilindex = i - stencilindex;
158                                 break;
159                         }
160                 }
161                 
162                 /* set index */
163                 CustomData_set_layer_stencil(data, type, stencilindex);
164         }
165 }
166
167 static void copy_editface_active_customdata(EditMesh *em, int type, int index)
168 {
169         EditFace *efa;
170         int n= CustomData_get_active_layer(&em->fdata, type);
171
172         for(efa= em->faces.first; efa; efa= efa->next) {
173                 void *data= CustomData_em_get_n(&em->fdata, efa->data, type, n);
174                 CustomData_em_set_n(&em->fdata, efa->data, type, index, data);
175         }
176 }
177
178 int ED_mesh_uv_texture_add(bContext *C, Mesh *me, const char *name, int active_set)
179 {
180         EditMesh *em;
181         int layernum;
182
183         if(me->edit_mesh) {
184                 em= me->edit_mesh;
185
186                 layernum= CustomData_number_of_layers(&em->fdata, CD_MTFACE);
187                 if(layernum >= MAX_MTFACE)
188                         return 0;
189
190                 EM_add_data_layer(em, &em->fdata, CD_MTFACE, name);
191
192                 if(layernum) /* copy data from active UV */
193                         copy_editface_active_customdata(em, CD_MTFACE, layernum);
194
195                 if(active_set || layernum==0)
196                         CustomData_set_layer_active(&em->fdata, CD_MTFACE, layernum);
197         }
198         else {
199                 layernum= CustomData_number_of_layers(&me->fdata, CD_MTFACE);
200                 if(layernum >= MAX_MTFACE)
201                         return 0;
202
203                 if(me->mtface)
204                         CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_DUPLICATE, me->mtface, me->totface, name);
205                 else
206                         CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_DEFAULT, NULL, me->totface, name);
207
208                 if(active_set || layernum==0)
209                         CustomData_set_layer_active(&me->fdata, CD_MTFACE, layernum);
210
211                 mesh_update_customdata_pointers(me);
212         }
213
214         DAG_id_tag_update(&me->id, 0);
215         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
216
217         return 1;
218 }
219
220 int ED_mesh_uv_texture_remove(bContext *C, Object *ob, Mesh *me)
221 {
222         CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
223         CustomDataLayer *cdl;
224         int index;
225
226         index= CustomData_get_active_layer_index(data, CD_MTFACE);
227         cdl= (index == -1) ? NULL: &data->layers[index];
228
229         if(!cdl)
230                 return 0;
231
232         delete_customdata_layer(C, ob, cdl);
233         DAG_id_tag_update(&me->id, 0);
234         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
235
236         return 1;
237 }
238
239 int ED_mesh_color_add(bContext *C, Scene *UNUSED(scene), Object *UNUSED(ob), Mesh *me, const char *name, int active_set)
240 {
241         EditMesh *em;
242         MCol *mcol;
243         int layernum;
244
245         if(me->edit_mesh) {
246                 em= me->edit_mesh;
247
248                 layernum= CustomData_number_of_layers(&em->fdata, CD_MCOL);
249                 if(layernum >= MAX_MCOL)
250                         return 0;
251
252                 EM_add_data_layer(em, &em->fdata, CD_MCOL, name);
253
254                 if(layernum) /* copy data from active vertex color layer */
255                         copy_editface_active_customdata(em, CD_MCOL, layernum);
256
257                 if(active_set || layernum==0)
258                         CustomData_set_layer_active(&em->fdata, CD_MCOL, layernum);
259         }
260         else {
261                 layernum= CustomData_number_of_layers(&me->fdata, CD_MCOL);
262                 if(layernum >= MAX_MCOL)
263                         return 0;
264
265                 mcol= me->mcol;
266
267                 if(me->mcol)
268                         CustomData_add_layer_named(&me->fdata, CD_MCOL, CD_DUPLICATE, me->mcol, me->totface, name);
269                 else
270                         CustomData_add_layer_named(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface, name);
271
272                 if(active_set || layernum==0)
273                         CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum);
274
275                 mesh_update_customdata_pointers(me);
276         }
277
278         DAG_id_tag_update(&me->id, 0);
279         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
280
281         return 1;
282 }
283
284 int ED_mesh_color_remove(bContext *C, Object *ob, Mesh *me)
285 {
286         CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
287         CustomDataLayer *cdl;
288         int index;
289
290          index= CustomData_get_active_layer_index(data, CD_MCOL);
291         cdl= (index == -1)? NULL: &data->layers[index];
292
293         if(!cdl)
294                 return 0;
295
296         delete_customdata_layer(C, ob, cdl);
297         DAG_id_tag_update(&me->id, 0);
298         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
299
300         return 1;
301 }
302
303 /*********************** UV texture operators ************************/
304
305 static int layers_poll(bContext *C)
306 {
307         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
308         ID *data= (ob)? ob->data: NULL;
309         return (ob && !ob->id.lib && ob->type==OB_MESH && data && !data->lib);
310 }
311
312 static int uv_texture_add_exec(bContext *C, wmOperator *UNUSED(op))
313 {
314         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
315         Mesh *me= ob->data;
316
317         if(!ED_mesh_uv_texture_add(C, me, NULL, TRUE))
318                 return OPERATOR_CANCELLED;
319
320         return OPERATOR_FINISHED;
321 }
322
323 void MESH_OT_uv_texture_add(wmOperatorType *ot)
324 {
325         /* identifiers */
326         ot->name= "Add UV Texture";
327         ot->description= "Add UV texture layer";
328         ot->idname= "MESH_OT_uv_texture_add";
329         
330         /* api callbacks */
331         ot->poll= layers_poll;
332         ot->exec= uv_texture_add_exec;
333
334         /* flags */
335         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
336 }
337
338 static int drop_named_image_invoke(bContext *C, wmOperator *op, wmEvent *event)
339 {
340         Main *bmain= CTX_data_main(C);
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(bmain, 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 }