BMesh: support copying & freeing layers by type

This commit is contained in:
Campbell Barton
2019-11-26 16:19:56 +11:00
parent 0a3f0e64c9
commit 7782936977
4 changed files with 99 additions and 77 deletions

View File

@@ -258,6 +258,11 @@ void CustomData_bmesh_copy_data(const struct CustomData *source,
struct CustomData *dest,
void *src_block,
void **dest_block);
void CustomData_bmesh_copy_data_exclude_by_type(const struct CustomData *source,
struct CustomData *dest,
void *src_block,
void **dest_block,
const CustomDataMask mask_exclude);
/* Copies data of a single layer of a given type. */
void CustomData_copy_layer_type_data(const struct CustomData *source,
@@ -392,6 +397,9 @@ void CustomData_clear_layer_flag(struct CustomData *data, int type, int flag);
void CustomData_bmesh_set_default(struct CustomData *data, void **block);
void CustomData_bmesh_free_block(struct CustomData *data, void **block);
void CustomData_bmesh_free_block_data(struct CustomData *data, void *block);
void CustomData_bmesh_free_block_data_exclude_by_type(struct CustomData *data,
void *block,
const CustomDataMask mask_exclude);
/* copy custom data to/from layers as in mesh/derivedmesh, to editmesh
* blocks of data. the CustomData's must not be compatible */

View File

@@ -3415,24 +3415,18 @@ void CustomData_bmesh_free_block(CustomData *data, void **block)
*/
void CustomData_bmesh_free_block_data(CustomData *data, void *block)
{
const LayerTypeInfo *typeInfo;
int i;
if (block == NULL) {
return;
}
for (i = 0; i < data->totlayer; i++) {
for (int i = 0; i < data->totlayer; i++) {
if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
typeInfo = layerType_getInfo(data->layers[i].type);
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
if (typeInfo->free) {
const size_t offset = data->layers[i].offset;
typeInfo->free(POINTER_OFFSET(block, offset), 1, typeInfo->size);
}
}
}
if (data->totsize) {
memset(block, 0, data->totsize);
}
@@ -3453,6 +3447,30 @@ static void CustomData_bmesh_alloc_block(CustomData *data, void **block)
}
}
/**
* A selective version of #CustomData_bmesh_free_block_data.
*/
void CustomData_bmesh_free_block_data_exclude_by_type(CustomData *data,
void *block,
const CustomDataMask mask_exclude)
{
if (block == NULL) {
return;
}
for (int i = 0; i < data->totlayer; i++) {
if ((CD_TYPE_AS_MASK(data->layers[i].type) & mask_exclude) == 0) {
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
const size_t offset = data->layers[i].offset;
if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
if (typeInfo->free) {
typeInfo->free(POINTER_OFFSET(block, offset), 1, typeInfo->size);
}
}
memset(POINTER_OFFSET(block, offset), 0, typeInfo->size);
}
}
}
static void CustomData_bmesh_set_default_n(CustomData *data, void **block, int n)
{
const LayerTypeInfo *typeInfo;
@@ -3481,12 +3499,15 @@ void CustomData_bmesh_set_default(CustomData *data, void **block)
}
}
void CustomData_bmesh_copy_data(const CustomData *source,
CustomData *dest,
void *src_block,
void **dest_block)
void CustomData_bmesh_copy_data_exclude_by_type(const CustomData *source,
CustomData *dest,
void *src_block,
void **dest_block,
const CustomDataMask mask_exclude)
{
const LayerTypeInfo *typeInfo;
/* Note that having a version of this function without a 'mask_exclude'
* would cause too much duplicate code, so add a check instead. */
const bool no_mask = (mask_exclude == 0);
int dest_i, src_i;
if (*dest_block == NULL) {
@@ -3519,13 +3540,14 @@ void CustomData_bmesh_copy_data(const CustomData *source,
const void *src_data = POINTER_OFFSET(src_block, source->layers[src_i].offset);
void *dest_data = POINTER_OFFSET(*dest_block, dest->layers[dest_i].offset);
typeInfo = layerType_getInfo(source->layers[src_i].type);
if (typeInfo->copy) {
typeInfo->copy(src_data, dest_data, 1);
}
else {
memcpy(dest_data, src_data, typeInfo->size);
if (no_mask || ((CD_TYPE_AS_MASK(dest->layers[dest_i].type) & mask_exclude) == 0)) {
const LayerTypeInfo *typeInfo = layerType_getInfo(source->layers[src_i].type);
if (typeInfo->copy) {
typeInfo->copy(src_data, dest_data, 1);
}
else {
memcpy(dest_data, src_data, typeInfo->size);
}
}
/* if there are multiple source & dest layers of the same type,
@@ -3542,6 +3564,14 @@ void CustomData_bmesh_copy_data(const CustomData *source,
}
}
void CustomData_bmesh_copy_data(const CustomData *source,
CustomData *dest,
void *src_block,
void **dest_block)
{
CustomData_bmesh_copy_data_exclude_by_type(source, dest, src_block, dest_block, 0);
}
/* BMesh Custom Data Functions.
* Should replace edit-mesh ones with these as well, due to more efficient memory alloc.
*/

View File

@@ -89,11 +89,8 @@ void BM_edges_from_verts_ensure(BMesh *bm, BMEdge **edge_arr, BMVert **vert_arr,
}
/* prototypes */
static void bm_loop_attrs_copy(BMesh *source_mesh,
BMesh *target_mesh,
const BMLoop *source_loop,
BMLoop *target_loop,
uint64_t cd_mask);
static void bm_loop_attrs_copy(
BMesh *bm_src, BMesh *bm_dst, const BMLoop *l_src, BMLoop *l_dst, CustomDataMask mask_exclude);
/**
* \brief Make Quad/Triangle
@@ -414,73 +411,59 @@ void BM_verts_sort_radial_plane(BMVert **vert_arr, int len)
/*************************************************************/
static void bm_vert_attrs_copy(BMesh *source_mesh,
BMesh *target_mesh,
const BMVert *source_vertex,
BMVert *target_vertex,
uint64_t cd_mask)
static void bm_vert_attrs_copy(
BMesh *bm_src, BMesh *bm_dst, const BMVert *v_src, BMVert *v_dst, CustomDataMask mask_exclude)
{
if ((source_mesh == target_mesh) && (source_vertex == target_vertex)) {
if ((bm_src == bm_dst) && (v_src == v_dst)) {
BLI_assert(!"BMVert: source and target match");
return;
}
if ((cd_mask & CD_MASK_NORMAL) == 0) {
copy_v3_v3(target_vertex->no, source_vertex->no);
if ((mask_exclude & CD_MASK_NORMAL) == 0) {
copy_v3_v3(v_dst->no, v_src->no);
}
CustomData_bmesh_free_block_data(&target_mesh->vdata, target_vertex->head.data);
CustomData_bmesh_copy_data(&source_mesh->vdata,
&target_mesh->vdata,
source_vertex->head.data,
&target_vertex->head.data);
CustomData_bmesh_free_block_data_exclude_by_type(&bm_dst->vdata, v_dst->head.data, mask_exclude);
CustomData_bmesh_copy_data_exclude_by_type(
&bm_src->vdata, &bm_dst->vdata, v_src->head.data, &v_dst->head.data, mask_exclude);
}
static void bm_edge_attrs_copy(BMesh *source_mesh,
BMesh *target_mesh,
const BMEdge *source_edge,
BMEdge *target_edge,
uint64_t UNUSED(cd_mask))
static void bm_edge_attrs_copy(
BMesh *bm_src, BMesh *bm_dst, const BMEdge *e_src, BMEdge *e_dst, CustomDataMask mask_exclude)
{
if ((source_mesh == target_mesh) && (source_edge == target_edge)) {
if ((bm_src == bm_dst) && (e_src == e_dst)) {
BLI_assert(!"BMEdge: source and target match");
return;
}
CustomData_bmesh_free_block_data(&target_mesh->edata, target_edge->head.data);
CustomData_bmesh_copy_data(
&source_mesh->edata, &target_mesh->edata, source_edge->head.data, &target_edge->head.data);
CustomData_bmesh_free_block_data_exclude_by_type(&bm_dst->edata, e_dst->head.data, mask_exclude);
CustomData_bmesh_copy_data_exclude_by_type(
&bm_src->edata, &bm_dst->edata, e_src->head.data, &e_dst->head.data, mask_exclude);
}
static void bm_loop_attrs_copy(BMesh *source_mesh,
BMesh *target_mesh,
const BMLoop *source_loop,
BMLoop *target_loop,
uint64_t UNUSED(cd_mask))
static void bm_loop_attrs_copy(
BMesh *bm_src, BMesh *bm_dst, const BMLoop *l_src, BMLoop *l_dst, CustomDataMask mask_exclude)
{
if ((source_mesh == target_mesh) && (source_loop == target_loop)) {
if ((bm_src == bm_dst) && (l_src == l_dst)) {
BLI_assert(!"BMLoop: source and target match");
return;
}
CustomData_bmesh_free_block_data(&target_mesh->ldata, target_loop->head.data);
CustomData_bmesh_copy_data(
&source_mesh->ldata, &target_mesh->ldata, source_loop->head.data, &target_loop->head.data);
CustomData_bmesh_free_block_data_exclude_by_type(&bm_dst->ldata, l_dst->head.data, mask_exclude);
CustomData_bmesh_copy_data_exclude_by_type(
&bm_src->ldata, &bm_dst->ldata, l_src->head.data, &l_dst->head.data, mask_exclude);
}
static void bm_face_attrs_copy(BMesh *source_mesh,
BMesh *target_mesh,
const BMFace *source_face,
BMFace *target_face,
uint64_t cd_mask)
static void bm_face_attrs_copy(
BMesh *bm_src, BMesh *bm_dst, const BMFace *f_src, BMFace *f_dst, CustomDataMask mask_exclude)
{
if ((source_mesh == target_mesh) && (source_face == target_face)) {
if ((bm_src == bm_dst) && (f_src == f_dst)) {
BLI_assert(!"BMFace: source and target match");
return;
}
if ((cd_mask & CD_MASK_NORMAL) == 0) {
copy_v3_v3(target_face->no, source_face->no);
if ((mask_exclude & CD_MASK_NORMAL) == 0) {
copy_v3_v3(f_dst->no, f_src->no);
}
CustomData_bmesh_free_block_data(&target_mesh->pdata, target_face->head.data);
CustomData_bmesh_copy_data(
&source_mesh->pdata, &target_mesh->pdata, source_face->head.data, &target_face->head.data);
target_face->mat_nr = source_face->mat_nr;
CustomData_bmesh_free_block_data_exclude_by_type(&bm_dst->pdata, f_dst->head.data, mask_exclude);
CustomData_bmesh_copy_data_exclude_by_type(
&bm_src->pdata, &bm_dst->pdata, f_src->head.data, &f_dst->head.data, mask_exclude);
f_dst->mat_nr = f_src->mat_nr;
}
/* BMESH_TODO: Special handling for hide flags? */
@@ -495,7 +478,7 @@ void BM_elem_attrs_copy_ex(BMesh *bm_src,
const void *ele_src_v,
void *ele_dst_v,
const char hflag_mask,
const uint64_t cd_mask)
const uint64_t cd_mask_exclude)
{
const BMHeader *ele_src = ele_src_v;
BMHeader *ele_dst = ele_dst_v;
@@ -503,9 +486,6 @@ void BM_elem_attrs_copy_ex(BMesh *bm_src,
BLI_assert(ele_src->htype == ele_dst->htype);
BLI_assert(ele_src != ele_dst);
/* Only support normal layer at the moment. */
BLI_assert((cd_mask & ~CD_MASK_NORMAL) == 0);
if ((hflag_mask & BM_ELEM_SELECT) == 0) {
/* First we copy select */
if (BM_elem_flag_test((BMElem *)ele_src, BM_ELEM_SELECT)) {
@@ -527,16 +507,20 @@ void BM_elem_attrs_copy_ex(BMesh *bm_src,
/* Copy specific attributes */
switch (ele_dst->htype) {
case BM_VERT:
bm_vert_attrs_copy(bm_src, bm_dst, (const BMVert *)ele_src, (BMVert *)ele_dst, cd_mask);
bm_vert_attrs_copy(
bm_src, bm_dst, (const BMVert *)ele_src, (BMVert *)ele_dst, cd_mask_exclude);
break;
case BM_EDGE:
bm_edge_attrs_copy(bm_src, bm_dst, (const BMEdge *)ele_src, (BMEdge *)ele_dst, cd_mask);
bm_edge_attrs_copy(
bm_src, bm_dst, (const BMEdge *)ele_src, (BMEdge *)ele_dst, cd_mask_exclude);
break;
case BM_LOOP:
bm_loop_attrs_copy(bm_src, bm_dst, (const BMLoop *)ele_src, (BMLoop *)ele_dst, cd_mask);
bm_loop_attrs_copy(
bm_src, bm_dst, (const BMLoop *)ele_src, (BMLoop *)ele_dst, cd_mask_exclude);
break;
case BM_FACE:
bm_face_attrs_copy(bm_src, bm_dst, (const BMFace *)ele_src, (BMFace *)ele_dst, cd_mask);
bm_face_attrs_copy(
bm_src, bm_dst, (const BMFace *)ele_src, (BMFace *)ele_dst, cd_mask_exclude);
break;
default:
BLI_assert(0);

View File

@@ -61,7 +61,7 @@ void BM_elem_attrs_copy_ex(BMesh *bm_src,
const void *ele_src_v,
void *ele_dst_v,
const char hflag_mask,
const uint64_t cd_mask);
const uint64_t cd_mask_exclude);
void BM_elem_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v);
void BM_elem_select_copy(BMesh *bm_dst, void *ele_dst_v, const void *ele_src_v);