From e62bc29a9b5a4bb69547bb565e9793fca6df5b76 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 8 Jan 2013 14:25:17 +0000 Subject: fix [#33792] Accessing a bmesh object created by from_object crashes blender Issue was customdata wasnt being initialized for layers in the destination BMesh but not in the source data. --- source/blender/blenkernel/BKE_customdata.h | 3 +- source/blender/blenkernel/intern/customdata.c | 43 +++++++++++++++++----- source/blender/blenkernel/intern/modifiers_bmesh.c | 8 ++-- 3 files changed, 39 insertions(+), 15 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 4736e7b7312..70532384643 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -39,6 +39,7 @@ extern "C" { #endif #include "../blenloader/BLO_sys_types.h" /* XXX, should have a more generic include for this */ +#include "BLI_utildefines.h" struct BMesh; struct ID; @@ -304,7 +305,7 @@ void CustomData_bmesh_free_block(struct CustomData *data, void **block); /* copy custom data to/from layers as in mesh/derivedmesh, to editmesh * blocks of data. the CustomData's must not be compatible */ void CustomData_to_bmesh_block(const struct CustomData *source, - struct CustomData *dest, int src_index, void **dest_block); + struct CustomData *dest, int src_index, void **dest_block, bool use_default_init); void CustomData_from_bmesh_block(const struct CustomData *source, struct CustomData *dest, void *src_block, int dest_index); diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 832c1979a51..19624e8a2b9 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -2660,27 +2660,40 @@ void CustomData_bmesh_interp(CustomData *data, void **src_blocks, const float *w if (count > SOURCE_BUF_SIZE) MEM_freeN(sources); } -void CustomData_bmesh_set_default(CustomData *data, void **block) +static void CustomData_bmesh_set_default_n(CustomData *data, void **block, int n) { const LayerTypeInfo *typeInfo; + int offset = data->layers[n].offset; + + typeInfo = layerType_getInfo(data->layers[n].type); + + if (typeInfo->set_default) { + typeInfo->set_default((char *)*block + offset, 1); + } + else { + memset((char *)*block + offset, 0, typeInfo->size); + } +} + +void CustomData_bmesh_set_default(CustomData *data, void **block) +{ int i; if (*block == NULL) CustomData_bmesh_alloc_block(data, block); for (i = 0; i < data->totlayer; ++i) { - int offset = data->layers[i].offset; - - typeInfo = layerType_getInfo(data->layers[i].type); - - if (typeInfo->set_default) - typeInfo->set_default((char *)*block + offset, 1); - else memset((char *)*block + offset, 0, typeInfo->size); + CustomData_bmesh_set_default_n(data, block, i); } } +/** + * \param use_default_init initializes data which can't be copied, + * typically you'll want to use this if the BM_xxx create function + * is called with BM_CREATE_SKIP_CD flag + */ void CustomData_to_bmesh_block(const CustomData *source, CustomData *dest, - int src_index, void **dest_block) + int src_index, void **dest_block, bool use_default_init) { const LayerTypeInfo *typeInfo; int dest_i, src_i, src_offset; @@ -2696,11 +2709,14 @@ void CustomData_to_bmesh_block(const CustomData *source, CustomData *dest, * (this should work because layers are ordered by type) */ while (dest_i < dest->totlayer && dest->layers[dest_i].type < source->layers[src_i].type) { + if (use_default_init) { + CustomData_bmesh_set_default_n(dest, dest_block, dest_i); + } dest_i++; } /* if there are no more dest layers, we're done */ - if (dest_i >= dest->totlayer) return; + if (dest_i >= dest->totlayer) break; /* if we found a matching layer, copy the data */ if (dest->layers[dest_i].type == source->layers[src_i].type) { @@ -2723,6 +2739,13 @@ void CustomData_to_bmesh_block(const CustomData *source, CustomData *dest, dest_i++; } } + + if (use_default_init) { + while (dest_i < dest->totlayer) { + CustomData_bmesh_set_default_n(dest, dest_block, dest_i); + dest_i++; + } + } } void CustomData_from_bmesh_block(const CustomData *source, CustomData *dest, diff --git a/source/blender/blenkernel/intern/modifiers_bmesh.c b/source/blender/blenkernel/intern/modifiers_bmesh.c index 9b5cf443bcf..3939c45a436 100644 --- a/source/blender/blenkernel/intern/modifiers_bmesh.c +++ b/source/blender/blenkernel/intern/modifiers_bmesh.c @@ -96,7 +96,7 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm) v->head.hflag = BM_vert_flag_from_mflag(mv->flag); BM_elem_index_set(v, i); /* set_inline */ - CustomData_to_bmesh_block(&dm->vertData, &bm->vdata, i, &v->head.data); + CustomData_to_bmesh_block(&dm->vertData, &bm->vdata, i, &v->head.data, true); vtable[i] = v; /* add bevel weight */ @@ -118,7 +118,7 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm) e->head.hflag = BM_edge_flag_from_mflag(me->flag); BM_elem_index_set(e, i); /* set_inline */ - CustomData_to_bmesh_block(&dm->edgeData, &bm->edata, i, &e->head.data); + CustomData_to_bmesh_block(&dm->edgeData, &bm->edata, i, &e->head.data, true); etable[i] = e; /* add crease */ @@ -168,10 +168,10 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm) l = BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, f); for (k = mp->loopstart; l; l = BM_iter_step(&liter), k++) { - CustomData_to_bmesh_block(&dm->loopData, &bm->ldata, k, &l->head.data); + CustomData_to_bmesh_block(&dm->loopData, &bm->ldata, k, &l->head.data, true); } - CustomData_to_bmesh_block(&dm->polyData, &bm->pdata, i, &f->head.data); + CustomData_to_bmesh_block(&dm->polyData, &bm->pdata, i, &f->head.data, true); if (face_normals) { copy_v3_v3(f->no, face_normals[i]); -- cgit v1.2.3