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