Sculpt: Minor bmesh refactor, made tool flags a CD layer

The way toolflags reallocated the entire mesh
just to add or remove one pointer from BMEdge/Vert/Face
was highly broken.  Now a CD layer is used instead.
This commit is contained in:
Joseph Eagar 2021-10-03 20:46:44 -07:00
parent 99b9c1bcad
commit 1969510974
20 changed files with 615 additions and 375 deletions

View File

@ -1563,11 +1563,6 @@ static void layerDynTopoVert_interp(
mv->origmask = origmask;
}
static void layerCopy_noop(const void *UNUSED(source), void *UNUSED(dest), int UNUSED(count))
{
// do nothing
}
static void layerInterp_noop(const void **UNUSED(sources),
const float *UNUSED(weights),
const float *UNUSED(sub_weights),
@ -1987,7 +1982,16 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
NULL, // flag singleton layer
layerDynTopoVert_copy,
NULL,
layerDynTopoVert_interp}};
layerDynTopoVert_interp},
/*54 CD_BMESH_TOOLFLAGS */
{sizeof(MToolFlags),
"MToolFlags",
1,
NULL, // flag singleton layer
NULL,
NULL,
layerInterp_noop},
};
static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
/* 0-4 */
@ -3752,7 +3756,7 @@ void CustomData_bmesh_do_versions_update_active_layers(CustomData *fdata, Custom
void CustomData_bmesh_init_pool(CustomData *data, int totelem, const char htype)
{
return CustomData_bmesh_init_pool_ex(data, totelem, htype, __func__);
CustomData_bmesh_init_pool_ex(data, totelem, htype, __func__);
}
void CustomData_bmesh_init_pool_ex(CustomData *data,
@ -3928,7 +3932,7 @@ void CustomData_bmesh_free_block_data(CustomData *data, void *block)
}
}
static void CustomData_bmesh_alloc_block(CustomData *data, void **block)
ATTR_NO_OPT static void CustomData_bmesh_alloc_block(CustomData *data, void **block)
{
if (*block) {
CustomData_bmesh_free_block(data, block);
@ -3936,6 +3940,18 @@ static void CustomData_bmesh_alloc_block(CustomData *data, void **block)
if (data->totsize > 0) {
*block = BLI_mempool_alloc(data->pool);
/*clear toolflags pointer when created for the first time*/
int cd_tflags = data->typemap[CD_TOOLFLAGS];
if (cd_tflags != -1) {
cd_tflags = data->layers[cd_tflags].offset;
char *ptr = (char *)*block;
ptr += cd_tflags;
MToolFlags *flags = (MToolFlags *)ptr;
flags->flag = NULL;
}
}
else {
*block = NULL;
@ -3968,15 +3984,14 @@ void CustomData_bmesh_free_block_data_exclude_by_type(CustomData *data,
static void CustomData_bmesh_set_default_n(CustomData *data, void **block, int n)
{
int offset = data->layers[n].offset;
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[n].type);
/* can't allow this to be called on CD_MESH_ID */
if (data->layers[n].type == CD_MESH_ID) {
if (ELEM(data->layers[n].type, CD_TOOLFLAGS, CD_MESH_ID)) {
/* do not do toolflags or mesh ids */
return;
}
int offset = data->layers[n].offset;
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[n].type);
if (typeInfo->set_default) {
typeInfo->set_default(POINTER_OFFSET(*block, offset), 1);
}
@ -3985,9 +4000,9 @@ static void CustomData_bmesh_set_default_n(CustomData *data, void **block, int n
}
}
void CustomData_bmesh_set_default(CustomData *data, void **block)
ATTR_NO_OPT void CustomData_bmesh_set_default(CustomData *data, void **block)
{
if (*block == NULL) {
if (!*block) {
CustomData_bmesh_alloc_block(data, block);
}
@ -4005,15 +4020,30 @@ void CustomData_bmesh_swap_data_simple(CustomData *data, void **block1, void **b
*block1 = *block2;
*block2 = tmp;
// unswap ids if they exist
if (cd_id != -1 && *block1 && *block2) {
int itmp;
int *id1 = (int *)(((char *)*block1) + cd_id);
int *id2 = (int *)(((char *)*block2) + cd_id);
int cd_tflags = data->typemap[CD_TOOLFLAGS];
cd_tflags = cd_tflags != -1 ? data->layers[cd_tflags].offset : -1;
itmp = *id1;
*id1 = *id2;
*id2 = itmp;
// unswap ids if they exist
if (*block1 && *block2) {
if (cd_id != -1) {
int itmp;
int *id1 = (int *)(((char *)*block1) + cd_id);
int *id2 = (int *)(((char *)*block2) + cd_id);
itmp = *id1;
*id1 = *id2;
*id2 = itmp;
}
if (cd_tflags != -1) {
MToolFlags tmp;
MToolFlags *flags1 = (MToolFlags *)(((char *)*block1) + cd_tflags);
MToolFlags *flags2 = (MToolFlags *)(((char *)*block2) + cd_tflags);
tmp = *flags1;
*flags1 = *flags2;
*flags2 = tmp;
}
}
}
@ -4044,8 +4074,8 @@ void CustomData_bmesh_swap_data(CustomData *source,
dest_i_start++;
}
if (source->layers[src_i].type == CD_MESH_ID) {
// do not swap ids
if (ELEM(source->layers[src_i].type, CD_MESH_ID, CD_TOOLFLAGS)) {
// do not swap ids or toolflags
continue;
}
@ -4096,6 +4126,14 @@ void CustomData_bmesh_copy_data_exclude_by_type(const CustomData *source,
* would cause too much duplicate code, so add a check instead. */
const bool no_mask = (mask_exclude == 0);
/*
Note that we don't handle id/toolflag layers specially here,
instead relying on CD_ELEM_NO_COPY semantics.
This is so BM_data_layer_add can reallocate customdata blocks without
zeroing those two layers.
*/
if (*dest_block == NULL) {
CustomData_bmesh_alloc_block(dest, dest_block);
if (*dest_block) {
@ -4135,6 +4173,9 @@ void CustomData_bmesh_copy_data_exclude_by_type(const CustomData *source,
/* if we found a matching layer, copy the data */
if (STREQ(dest->layers[dest_i].name, source->layers[src_i].name)) {
if (no_mask || ((CD_TYPE_AS_MASK(dest->layers[dest_i].type) & mask_exclude) == 0)) {
/* CD_FLAG_ELEM_NOCOPY is used to forcibly exclude copying CD_MESH_ID and CD_TOOLFLAGS
layers */
if (dest->layers[dest_i].flag & CD_FLAG_ELEM_NOCOPY) {
break;
}
@ -4463,6 +4504,12 @@ void CustomData_bmesh_interp(CustomData *data,
for (int i = 0; i < data->totlayer; i++) {
CustomDataLayer *layer = &data->layers[i];
const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
// ignore id and toolflag layers
if (ELEM(layer->type, CD_MESH_ID, CD_TOOLFLAGS)) {
continue;
}
if (typeInfo->interp) {
for (int j = 0; j < count; j++) {
sources[j] = POINTER_OFFSET(src_blocks[j], layer->offset);

View File

@ -5348,13 +5348,40 @@ ATTR_NO_OPT void BKE_pbvh_bmesh_from_saved_indices(PBVH *pbvh)
BLI_array_free(ltable);
}
extern char dyntopop_node_idx_layer_id[];
extern char dyntopop_faces_areas_layer_id[];
static void pbvh_bmesh_fetch_cdrefs(PBVH *pbvh)
{
BMesh *bm = pbvh->bm;
int idx = CustomData_get_named_layer_index(
&bm->vdata, CD_PROP_INT32, dyntopop_node_idx_layer_id);
pbvh->cd_vert_node_offset = bm->vdata.layers[idx].offset;
idx = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_INT32, dyntopop_node_idx_layer_id);
pbvh->cd_face_node_offset = bm->pdata.layers[idx].offset;
idx = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_FLOAT, dyntopop_faces_areas_layer_id);
pbvh->cd_face_area = bm->pdata.layers[idx].offset;
pbvh->cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
pbvh->cd_vcol_offset = CustomData_get_offset(&bm->vdata, CD_PROP_COLOR);
pbvh->cd_faceset_offset = CustomData_get_offset(&bm->pdata, CD_SCULPT_FACE_SETS);
pbvh->cd_dyn_vert = CustomData_get_offset(&bm->vdata, CD_DYNTOPO_VERT);
}
void BKE_pbvh_bmesh_set_toolflags(PBVH *pbvh, bool use_toolflags)
{
if (use_toolflags == pbvh->bm->use_toolflags) {
return;
}
BKE_pbvh_bmesh_save_indices(pbvh);
// BKE_pbvh_bmesh_save_indices(pbvh);
BM_mesh_toolflags_set(pbvh->bm, use_toolflags);
BKE_pbvh_bmesh_from_saved_indices(pbvh);
// customdata layout might've changed
pbvh_bmesh_fetch_cdrefs(pbvh);
// BKE_pbvh_bmesh_from_saved_indices(pbvh);
}

View File

@ -114,10 +114,9 @@ typedef struct BMVert {
struct BMEdge *e;
} BMVert;
typedef struct BMVert_OFlag {
BMVert base;
struct BMFlagLayer *oflags;
} BMVert_OFlag;
#define BMVert_OFlag BMVert
#define BMEdge_OFlag BMEdge
#define BMFace_OFlag BMFace
/* disk link structure, only used by edges */
typedef struct BMDiskLink {
@ -153,11 +152,6 @@ typedef struct BMEdge {
BMDiskLink v1_disk_link, v2_disk_link;
} BMEdge;
typedef struct BMEdge_OFlag {
BMEdge base;
struct BMFlagLayer *oflags;
} BMEdge_OFlag;
typedef struct BMLoop {
BMHeader head;
/* notice no flags layer */
@ -287,11 +281,6 @@ typedef struct BMFace {
// short _pad[3];
} BMFace;
typedef struct BMFace_OFlag {
BMFace base;
struct BMFlagLayer *oflags;
} BMFace_OFlag;
typedef struct BMFlagLayer {
short f; /* flags */
} BMFlagLayer;

View File

@ -795,28 +795,28 @@ void BM_elem_attrs_copy_ex(BMesh *bm_src,
bm_dst,
(const BMVert *)ele_src,
(BMVert *)ele_dst,
cd_mask_exclude | CD_MASK_MESH_ID);
cd_mask_exclude | CD_MASK_MESH_ID | CD_MASK_TOOLFLAGS);
break;
case BM_EDGE:
bm_edge_attrs_copy(bm_src,
bm_dst,
(const BMEdge *)ele_src,
(BMEdge *)ele_dst,
cd_mask_exclude | CD_MASK_MESH_ID);
cd_mask_exclude | CD_MASK_MESH_ID | CD_MASK_TOOLFLAGS);
break;
case BM_LOOP:
bm_loop_attrs_copy(bm_src,
bm_dst,
(const BMLoop *)ele_src,
(BMLoop *)ele_dst,
cd_mask_exclude | CD_MASK_MESH_ID);
cd_mask_exclude | CD_MASK_MESH_ID | CD_MASK_TOOLFLAGS);
break;
case BM_FACE:
bm_face_attrs_copy(bm_src,
bm_dst,
(const BMFace *)ele_src,
(BMFace *)ele_dst,
cd_mask_exclude | CD_MASK_MESH_ID);
cd_mask_exclude | CD_MASK_MESH_ID | CD_MASK_TOOLFLAGS);
break;
default:
BLI_assert(0);
@ -876,6 +876,8 @@ static BMFace *bm_mesh_copy_new_face(
BM_elem_attrs_copy_ex(bm_old, bm_new, f, f_new, 0xff, 0x0);
f_new->head.hflag = f->head.hflag; /* low level! don't do this for normal api use */
bm_elem_check_toolflags(bm_new, (BMElem *)f);
j = 0;
l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
do {
@ -1047,7 +1049,9 @@ BMesh *BM_mesh_copy_ex(BMesh *bm_old, struct BMeshCreateParams *params)
v_new = BM_vert_create(bm_new, v->co, NULL, BM_CREATE_SKIP_CD | BM_CREATE_SKIP_ID);
BM_elem_attrs_copy_ex(bm_old, bm_new, v, v_new, 0xff, 0x0);
bm_alloc_id(bm_new, (BMElem *)v_new);
bm_elem_check_toolflags(bm_new, (BMElem *)v_new);
v_new->head.hflag = v->head.hflag; /* low level! don't do this for normal api use */
vtable[i] = v_new;
@ -1069,6 +1073,7 @@ BMesh *BM_mesh_copy_ex(BMesh *bm_old, struct BMeshCreateParams *params)
BM_elem_attrs_copy_ex(bm_old, bm_new, e, e_new, 0xff, 0x0);
bm_alloc_id(bm_new, (BMElem *)e_new);
bm_elem_check_toolflags(bm_new, (BMElem *)e_new);
e_new->head.hflag = e->head.hflag; /* low level! don't do this for normal api use */
etable[i] = e_new;

View File

@ -24,6 +24,7 @@
#include "BLI_alloca.h"
#include "BLI_array.h"
#include "BLI_asan.h"
#include "BLI_linklist_stack.h"
#include "BLI_math_vector.h"
#include "BLI_utildefines_stack.h"
@ -53,6 +54,40 @@
#endif
ATTR_NO_OPT void bm_elem_check_toolflags(BMesh *bm, BMElem *elem)
{
int cd_off = -1;
MToolFlags *flags;
BLI_mempool *flagpool;
switch (elem->head.htype) {
case BM_VERT:
cd_off = bm->vdata.typemap[CD_TOOLFLAGS];
cd_off = cd_off != -1 ? bm->vdata.layers[cd_off].offset : -1;
flagpool = bm->vtoolflagpool;
break;
case BM_EDGE:
cd_off = bm->edata.typemap[CD_TOOLFLAGS];
cd_off = cd_off != -1 ? bm->edata.layers[cd_off].offset : -1;
flagpool = bm->etoolflagpool;
break;
case BM_FACE:
cd_off = bm->pdata.typemap[CD_TOOLFLAGS];
cd_off = cd_off != -1 ? bm->pdata.layers[cd_off].offset : -1;
flagpool = bm->ftoolflagpool;
break;
}
if (cd_off == -1 || !flagpool) {
return;
}
flags = (MToolFlags *)BM_ELEM_CD_GET_VOID_P(elem, cd_off);
if (!flags->flag) {
flags->flag = BLI_mempool_calloc(flagpool);
}
}
/**
* \brief Main function for creating a new vertex.
*/
@ -79,11 +114,6 @@ BMVert *BM_vert_create(BMesh *bm,
v->head.hflag = 0;
v->head.api_flag = 0;
/* allocate flags */
if (bm->use_toolflags) {
((BMVert_OFlag *)v)->oflags = bm->vtoolflagpool ? BLI_mempool_calloc(bm->vtoolflagpool) : NULL;
}
/* 'v->no' is handled by BM_elem_attrs_copy */
if (co) {
copy_v3_v3(v->co, co);
@ -137,6 +167,13 @@ BMVert *BM_vert_create(BMesh *bm,
}
}
/* allocate flags */
if (bm->use_toolflags && v->head.data) {
int cd_tflags = bm->vdata.layers[bm->vdata.typemap[CD_TOOLFLAGS]].offset;
MToolFlags *flags = (MToolFlags *)BM_ELEM_CD_GET_VOID_P(v, cd_tflags);
flags->flag = BLI_mempool_calloc(bm->vtoolflagpool);
}
BM_CHECK_ELEMENT(v);
return v;
@ -178,11 +215,6 @@ BMEdge *BM_edge_create(
e->head.hflag = BM_ELEM_SMOOTH | BM_ELEM_DRAW;
e->head.api_flag = 0;
/* allocate flags */
if (bm->use_toolflags) {
((BMEdge_OFlag *)e)->oflags = bm->etoolflagpool ? BLI_mempool_calloc(bm->etoolflagpool) : NULL;
}
e->v1 = v1;
e->v2 = v2;
e->l = NULL;
@ -213,6 +245,13 @@ BMEdge *BM_edge_create(
}
}
/* allocate flags */
if (bm->use_toolflags && e->head.data) {
int cd_tflags = bm->edata.layers[bm->edata.typemap[CD_TOOLFLAGS]].offset;
MToolFlags *flags = (MToolFlags *)BM_ELEM_CD_GET_VOID_P(e, cd_tflags);
flags->flag = BLI_mempool_calloc(bm->etoolflagpool);
}
BM_CHECK_ELEMENT(e);
return e;
@ -366,6 +405,7 @@ BMFace *BM_face_copy(
BM_elem_attrs_copy(bm_src, bm_dst, f, f_copy);
bm_alloc_id(bm_dst, (BMElem *)f_copy);
bm_elem_check_toolflags(bm_dst, (BMElem *)f_copy);
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
l_copy = BM_FACE_FIRST_LOOP(f_copy);
@ -403,11 +443,6 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm)
f->head.hflag = 0;
f->head.api_flag = 0;
/* allocate flags */
if (bm->use_toolflags) {
((BMFace_OFlag *)f)->oflags = bm->ftoolflagpool ? BLI_mempool_calloc(bm->ftoolflagpool) : NULL;
}
#ifdef USE_BMESH_HOLES
BLI_listbase_clear(&f->loops);
#else
@ -510,6 +545,13 @@ BMFace *BM_face_create(BMesh *bm,
}
}
/* allocate flags */
if (bm->use_toolflags && f->head.data) {
int cd_tflags = bm->pdata.layers[bm->pdata.typemap[CD_TOOLFLAGS]].offset;
MToolFlags *flags = (MToolFlags *)BM_ELEM_CD_GET_VOID_P(f, cd_tflags);
flags->flag = BLI_mempool_calloc(bm->ftoolflagpool);
}
BM_CHECK_ELEMENT(f);
return f;
@ -779,13 +821,17 @@ static void bm_kill_only_vert(BMesh *bm, BMVert *v)
BM_select_history_remove(bm, v);
if (bm->vtoolflagpool) {
MToolFlags *flags = BM_ELEM_CD_GET_VOID_P(
v, bm->vdata.layers[bm->vdata.typemap[CD_TOOLFLAGS]].offset);
BLI_mempool_free(bm->vtoolflagpool, flags->flag);
}
if (v->head.data) {
CustomData_bmesh_free_block(&bm->vdata, &v->head.data);
}
if (bm->vtoolflagpool) {
BLI_mempool_free(bm->vtoolflagpool, ((BMVert_OFlag *)v)->oflags);
}
BLI_mempool_free(bm->vpool, v);
}
@ -880,13 +926,17 @@ void bm_kill_only_edge(BMesh *bm, BMEdge *e)
BM_select_history_remove(bm, (BMElem *)e);
if (bm->etoolflagpool) {
MToolFlags *flags = BM_ELEM_CD_GET_VOID_P(
e, bm->edata.layers[bm->edata.typemap[CD_TOOLFLAGS]].offset);
BLI_mempool_free(bm->etoolflagpool, flags->flag);
}
if (e->head.data) {
CustomData_bmesh_free_block(&bm->edata, &e->head.data);
}
if (bm->etoolflagpool) {
BLI_mempool_free(bm->etoolflagpool, ((BMEdge_OFlag *)e)->oflags);
}
BLI_mempool_free(bm->epool, e);
}
@ -909,13 +959,17 @@ void bm_kill_only_face(BMesh *bm, BMFace *f)
BM_select_history_remove(bm, (BMElem *)f);
if (bm->ftoolflagpool) {
MToolFlags *flags = BM_ELEM_CD_GET_VOID_P(
f, bm->pdata.layers[bm->pdata.typemap[CD_TOOLFLAGS]].offset);
BLI_mempool_free(bm->vtoolflagpool, flags->flag);
}
if (f->head.data) {
CustomData_bmesh_free_block(&bm->pdata, &f->head.data);
}
if (bm->ftoolflagpool) {
BLI_mempool_free(bm->ftoolflagpool, ((BMFace_OFlag *)f)->oflags);
}
BLI_mempool_free(bm->fpool, f);
}
@ -1525,6 +1579,12 @@ static BMFace *bm_face_create__sfme(BMesh *bm, BMFace *f_example)
BM_elem_attrs_copy(bm, bm, f_example, f);
bm_alloc_id(bm, (BMElem *)f);
if (bm->use_toolflags && f->head.data) {
int cd_tflags = bm->pdata.layers[bm->pdata.typemap[CD_TOOLFLAGS]].offset;
MToolFlags *flags = (MToolFlags *)BM_ELEM_CD_GET_VOID_P(f, cd_tflags);
flags->flag = BLI_mempool_calloc(bm->ftoolflagpool);
}
return f;
}
@ -1723,7 +1783,10 @@ BMFace *bmesh_kernel_split_face_make_edge(BMesh *bm,
*
* \return The newly created BMVert pointer.
*/
BMVert *bmesh_kernel_split_edge_make_vert(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
ATTR_NO_OPT BMVert *bmesh_kernel_split_edge_make_vert(BMesh *bm,
BMVert *tv,
BMEdge *e,
BMEdge **r_e)
{
BMLoop *l_next;
BMEdge *e_new;
@ -2303,7 +2366,10 @@ BMFace *bmesh_kernel_join_face_kill_edge(BMesh *bm, BMFace *f1, BMFace *f2, BMEd
/* deallocate edge and its two loops as well as f2 */
if (bm->etoolflagpool) {
BLI_mempool_free(bm->etoolflagpool, ((BMEdge_OFlag *)l_f1->e)->oflags);
MToolFlags *flags = (MToolFlags *)BM_ELEM_CD_GET_VOID_P(
l_f1->e, bm->edata.layers[bm->edata.typemap[CD_TOOLFLAGS]].offset);
BLI_mempool_free(bm->etoolflagpool, flags->flag);
}
BLI_mempool_free(bm->epool, l_f1->e);
bm->totedge--;
@ -2311,9 +2377,14 @@ BMFace *bmesh_kernel_join_face_kill_edge(BMesh *bm, BMFace *f1, BMFace *f2, BMEd
bm->totloop--;
BLI_mempool_free(bm->lpool, l_f2);
bm->totloop--;
if (bm->ftoolflagpool) {
BLI_mempool_free(bm->ftoolflagpool, ((BMFace_OFlag *)f2)->oflags);
MToolFlags *flags = (MToolFlags *)BM_ELEM_CD_GET_VOID_P(
f2, bm->pdata.layers[bm->pdata.typemap[CD_TOOLFLAGS]].offset);
BLI_mempool_free(bm->ftoolflagpool, flags->flag);
}
BLI_mempool_free(bm->fpool, f2);
bm->totface--;
/* account for both above */

View File

@ -30,10 +30,14 @@ typedef enum eBMCreateFlag {
/* Skip CustomData - for all element types data,
* use if we immediately write customdata into the element so this skips copying from 'example'
* args or setting defaults, speeds up conversion when data is converted all at once. */
BM_CREATE_SKIP_CD = (1 << 2),
BM_CREATE_SKIP_CD = (1 << 2), /* if true, you must call bm_elem_check_toolflags(bm, elem) later
if toolflags are on */
BM_CREATE_SKIP_ID = (1 << 3)
} eBMCreateFlag;
/* if toolflags are enabled, checks that internal pointer to toolflags it not null */
void bm_elem_check_toolflags(BMesh *bm, BMElem *elem);
BMVert *BM_vert_create(BMesh *bm,
const float co[3],
const BMVert *v_example,

View File

@ -66,6 +66,28 @@ void bm_restore_id(BMesh *bm, BMElem *elem, int id)
}
}
static void copy_cdata_simple(BMesh *bm,
CustomData *data_layer,
BMElem *ele_dst,
const BMElem *ele_src)
{
int id = bm_save_id(bm, ele_dst);
int cd_tflags;
MToolFlags saved_tflags;
if ((cd_tflags = CustomData_get_offset(data_layer, CD_TOOLFLAGS)) != -1) {
saved_tflags = *(MToolFlags *)BM_ELEM_CD_GET_VOID_P(ele_dst, cd_tflags);
}
CustomData_bmesh_free_block_data(data_layer, ele_dst->head.data);
CustomData_bmesh_copy_data(data_layer, data_layer, ele_src->head.data, &ele_dst->head.data);
if (cd_tflags != -1) {
*(MToolFlags *)BM_ELEM_CD_GET_VOID_P(ele_dst, cd_tflags) = saved_tflags;
}
bm_restore_id(bm, ele_dst, id);
}
/* edge and vertex share, currently there's no need to have different logic */
static void bm_data_interp_from_elem(BMesh *bm,
CustomData *data_layer,
@ -81,13 +103,7 @@ static void bm_data_interp_from_elem(BMesh *bm,
/* do nothing */
}
else {
int id = bm_save_id(bm, ele_dst);
CustomData_bmesh_free_block_data(data_layer, ele_dst->head.data);
CustomData_bmesh_copy_data(
data_layer, data_layer, ele_src_1->head.data, &ele_dst->head.data);
bm_restore_id(bm, ele_dst, id);
copy_cdata_simple(bm, data_layer, ele_dst, ele_src_1);
}
}
else if (fac >= 1.0f) {
@ -95,13 +111,7 @@ static void bm_data_interp_from_elem(BMesh *bm,
/* do nothing */
}
else {
int id = bm_save_id(bm, ele_dst);
CustomData_bmesh_free_block_data(data_layer, ele_dst->head.data);
CustomData_bmesh_copy_data(
data_layer, data_layer, ele_src_2->head.data, &ele_dst->head.data);
bm_restore_id(bm, ele_dst, id);
copy_cdata_simple(bm, data_layer, ele_dst, ele_src_2);
}
}
else {

View File

@ -35,6 +35,8 @@
#include "BKE_customdata.h"
#include "BKE_mesh.h"
#include "DNA_meshdata_types.h"
#include "bmesh.h"
#include "bmesh_private.h"
#include "range_tree.h"
@ -43,6 +45,8 @@
const BMAllocTemplate bm_mesh_allocsize_default = {512, 1024, 2048, 512};
const BMAllocTemplate bm_mesh_chunksize_default = {512, 1024, 2048, 512};
static void bm_alloc_toolflags(BMesh *bm);
static void bm_mempool_init_ex(const BMAllocTemplate *allocsize,
const bool use_toolflags,
BLI_mempool **r_vpool,
@ -104,30 +108,15 @@ void BM_mesh_elem_toolflags_ensure(BMesh *bm)
bm->etoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), bm->totedge, 512, BLI_MEMPOOL_NOP);
bm->ftoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), bm->totface, 512, BLI_MEMPOOL_NOP);
BMIter iter;
BMVert_OFlag *v_olfag;
BLI_mempool *toolflagpool = bm->vtoolflagpool;
BM_ITER_MESH (v_olfag, &iter, bm, BM_VERTS_OF_MESH) {
v_olfag->oflags = BLI_mempool_calloc(toolflagpool);
}
BMEdge_OFlag *e_olfag;
toolflagpool = bm->etoolflagpool;
BM_ITER_MESH (e_olfag, &iter, bm, BM_EDGES_OF_MESH) {
e_olfag->oflags = BLI_mempool_calloc(toolflagpool);
}
BMFace_OFlag *f_olfag;
toolflagpool = bm->ftoolflagpool;
BM_ITER_MESH (f_olfag, &iter, bm, BM_FACES_OF_MESH) {
f_olfag->oflags = BLI_mempool_calloc(toolflagpool);
}
bm_alloc_toolflags(bm);
bm->totflags = 1;
}
void BM_mesh_elem_toolflags_clear(BMesh *bm)
ATTR_NO_OPT void BM_mesh_elem_toolflags_clear(BMesh *bm)
{
bool haveflags = bm->vtoolflagpool || bm->etoolflagpool || bm->ftoolflagpool;
if (bm->vtoolflagpool) {
BLI_mempool_destroy(bm->vtoolflagpool);
bm->vtoolflagpool = NULL;
@ -140,6 +129,12 @@ void BM_mesh_elem_toolflags_clear(BMesh *bm)
BLI_mempool_destroy(bm->ftoolflagpool);
bm->ftoolflagpool = NULL;
}
if (haveflags) {
BM_data_layer_free(bm, &bm->vdata, CD_TOOLFLAGS);
BM_data_layer_free(bm, &bm->edata, CD_TOOLFLAGS);
BM_data_layer_free(bm, &bm->pdata, CD_TOOLFLAGS);
}
}
// int cdmap[8] = {0, 1, -1, -1, 2, -1, -1, -1, 3};
@ -225,9 +220,19 @@ BMesh *BM_mesh_create(const BMAllocTemplate *allocsize, const struct BMeshCreate
CustomData_reset(&bm->ldata);
CustomData_reset(&bm->pdata);
bool init_cdata_pools = false;
if (bm->use_toolflags) {
init_cdata_pools = true;
bm_alloc_toolflags_cdlayers(bm, false);
}
if (params->create_unique_ids) {
bm_init_idmap_cdlayers(bm);
init_cdata_pools = true;
}
if (init_cdata_pools) {
if (bm->vdata.totlayer) {
CustomData_bmesh_init_pool_ex(&bm->vdata, 0, BM_VERT, __func__);
}
@ -343,8 +348,20 @@ void BM_mesh_data_free(BMesh *bm)
MEM_freeN(bm->ftable);
}
/* destroy flag pool */
BM_mesh_elem_toolflags_clear(bm);
/* destroy flag pools */
if (bm->vtoolflagpool) {
BLI_mempool_destroy(bm->vtoolflagpool);
bm->vtoolflagpool = NULL;
}
if (bm->etoolflagpool) {
BLI_mempool_destroy(bm->etoolflagpool);
bm->etoolflagpool = NULL;
}
if (bm->ftoolflagpool) {
BLI_mempool_destroy(bm->ftoolflagpool);
bm->ftoolflagpool = NULL;
}
#ifdef USE_BMESH_HOLES
BLI_mempool_destroy(bm->looplistpool);
@ -1422,9 +1439,10 @@ void BM_mesh_rebuild(BMesh *bm,
BMVert *v_dst = BLI_mempool_alloc(vpool_dst);
memcpy(v_dst, v_src, sizeof(BMVert));
if (use_toolflags) {
((BMVert_OFlag *)v_dst)->oflags = bm->vtoolflagpool ?
BLI_mempool_calloc(bm->vtoolflagpool) :
NULL;
MToolFlags *flags = (MToolFlags *)BM_ELEM_CD_GET_VOID_P(
v_dst, bm->vdata.layers[bm->vdata.typemap[CD_TOOLFLAGS]].offset);
flags->flag = bm->vtoolflagpool ? BLI_mempool_calloc(bm->vtoolflagpool) : NULL;
}
vtable_dst[index] = v_dst;
@ -1440,9 +1458,10 @@ void BM_mesh_rebuild(BMesh *bm,
BMEdge *e_dst = BLI_mempool_alloc(epool_dst);
memcpy(e_dst, e_src, sizeof(BMEdge));
if (use_toolflags) {
((BMEdge_OFlag *)e_dst)->oflags = bm->etoolflagpool ?
BLI_mempool_calloc(bm->etoolflagpool) :
NULL;
MToolFlags *flags = (MToolFlags *)BM_ELEM_CD_GET_VOID_P(
e_dst, bm->edata.layers[bm->edata.typemap[CD_TOOLFLAGS]].offset);
flags->flag = bm->etoolflagpool ? BLI_mempool_calloc(bm->etoolflagpool) : NULL;
}
etable_dst[index] = e_dst;
@ -1459,10 +1478,12 @@ void BM_mesh_rebuild(BMesh *bm,
if (remap & BM_FACE) {
BMFace *f_dst = BLI_mempool_alloc(fpool_dst);
memcpy(f_dst, f_src, sizeof(BMFace));
if (use_toolflags) {
((BMFace_OFlag *)f_dst)->oflags = bm->ftoolflagpool ?
BLI_mempool_calloc(bm->ftoolflagpool) :
NULL;
MToolFlags *flags = (MToolFlags *)BM_ELEM_CD_GET_VOID_P(
f_dst, bm->pdata.layers[bm->pdata.typemap[CD_TOOLFLAGS]].offset);
flags->flag = bm->ftoolflagpool ? BLI_mempool_calloc(bm->ftoolflagpool) : NULL;
}
ftable_dst[index] = f_dst;
@ -1646,6 +1667,66 @@ void BM_mesh_rebuild(BMesh *bm,
bm_rebuild_idmap(bm);
}
void bm_alloc_toolflags_cdlayers(BMesh *bm, bool set_elems)
{
CustomData *cdatas[3] = {&bm->vdata, &bm->edata, &bm->pdata};
int iters[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
for (int i = 0; i < 3; i++) {
CustomData *cdata = cdatas[i];
int cd_tflags = CustomData_get_offset(cdata, CD_TOOLFLAGS);
if (cd_tflags == -1) {
if (set_elems) {
BM_data_layer_add(bm, cdata, CD_TOOLFLAGS);
}
else {
CustomData_add_layer(cdata, CD_TOOLFLAGS, CD_ASSIGN, NULL, 0);
}
int idx = CustomData_get_layer_index(cdata, CD_TOOLFLAGS);
cdata->layers[idx].flag |= CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY | CD_FLAG_ELEM_NOCOPY;
cd_tflags = cdata->layers[idx].offset;
if (set_elems) {
BMIter iter;
BMElem *elem;
BM_ITER_MESH (elem, &iter, bm, iters[i]) {
MToolFlags *flags = (MToolFlags *)BM_ELEM_CD_GET_VOID_P(elem, cd_tflags);
flags->flag = NULL;
}
}
}
}
}
static void bm_alloc_toolflags(BMesh *bm)
{
bm_alloc_toolflags_cdlayers(bm, true);
CustomData *cdatas[3] = {&bm->vdata, &bm->edata, &bm->pdata};
BLI_mempool *flagpools[3] = {bm->vtoolflagpool, bm->etoolflagpool, bm->ftoolflagpool};
BLI_mempool *elempools[3] = { bm->vpool, bm->epool, bm->fpool };
for (int i = 0; i < 3; i++) {
CustomData *cdata = cdatas[i];
int cd_tflags = CustomData_get_offset(cdata, CD_TOOLFLAGS);
BLI_mempool_iter iter;
BLI_mempool_iternew(elempools[i], &iter);
BMElem *elem = (BMElem *)BLI_mempool_iterstep(&iter);
for (; elem; elem = (BMElem *)BLI_mempool_iterstep(&iter)) {
MToolFlags *flags = (MToolFlags *)BM_ELEM_CD_GET_VOID_P(elem, cd_tflags);
flags->flag = BLI_mempool_calloc(flagpools[i]);
}
}
}
/**
* Re-allocates mesh data with/without toolflags.
*/
@ -1655,14 +1736,6 @@ void BM_mesh_toolflags_set(BMesh *bm, bool use_toolflags)
return;
}
const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_BM(bm);
BLI_mempool *vpool_dst = NULL;
BLI_mempool *epool_dst = NULL;
BLI_mempool *fpool_dst = NULL;
bm_mempool_init_ex(&allocsize, use_toolflags, &vpool_dst, &epool_dst, NULL, &fpool_dst);
if (use_toolflags == false) {
BLI_mempool_destroy(bm->vtoolflagpool);
BLI_mempool_destroy(bm->etoolflagpool);
@ -1671,18 +1744,20 @@ void BM_mesh_toolflags_set(BMesh *bm, bool use_toolflags)
bm->vtoolflagpool = NULL;
bm->etoolflagpool = NULL;
bm->ftoolflagpool = NULL;
BM_data_layer_free(bm, &bm->vdata, CD_TOOLFLAGS);
BM_data_layer_free(bm, &bm->edata, CD_TOOLFLAGS);
BM_data_layer_free(bm, &bm->pdata, CD_TOOLFLAGS);
}
else {
bm_alloc_toolflags_cdlayers(bm, true);
}
BM_mesh_rebuild(bm,
&((struct BMeshCreateParams){
.use_toolflags = use_toolflags,
}),
vpool_dst,
epool_dst,
NULL,
fpool_dst);
bm->use_toolflags = use_toolflags;
if (use_toolflags) {
BM_mesh_elem_toolflags_ensure(bm);
}
}
/* -------------------------------------------------------------------- */

View File

@ -472,6 +472,21 @@ void BM_mesh_bm_from_me(Object *ob,
}
}
if (bm->use_toolflags) {
bm_alloc_toolflags_cdlayers(bm, !is_new);
if (!bm->vtoolflagpool) {
bm->vtoolflagpool = BLI_mempool_create(
sizeof(BMFlagLayer), bm->totvert, 512, BLI_MEMPOOL_NOP);
bm->etoolflagpool = BLI_mempool_create(
sizeof(BMFlagLayer), bm->totedge, 512, BLI_MEMPOOL_NOP);
bm->ftoolflagpool = BLI_mempool_create(
sizeof(BMFlagLayer), bm->totface, 512, BLI_MEMPOOL_NOP);
bm->totflags = 1;
}
}
if (is_new) {
CustomData_bmesh_init_pool_ex(&bm->vdata, me->totvert, BM_VERT, __func__);
CustomData_bmesh_init_pool_ex(&bm->edata, me->totedge, BM_EDGE, __func__);
@ -532,6 +547,8 @@ void BM_mesh_bm_from_me(Object *ob,
/* Copy Custom Data */
CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data, true);
bm_elem_check_toolflags(bm, (BMElem *)v);
if (has_ids & BM_VERT) {
if (use_exist_ids & BM_VERT) {
bm_assign_id(bm, (BMElem *)v, existing_id_layers[0][i], false);
@ -581,6 +598,8 @@ void BM_mesh_bm_from_me(Object *ob,
/* Copy Custom Data */
CustomData_to_bmesh_block(&me->edata, &bm->edata, i, &e->head.data, true);
bm_elem_check_toolflags(bm, (BMElem *)e);
if (has_ids & BM_EDGE) {
if (use_exist_ids & BM_EDGE) {
bm_assign_id(bm, (BMElem *)e, existing_id_layers[1][i], false);
@ -665,6 +684,8 @@ void BM_mesh_bm_from_me(Object *ob,
/* Copy Custom Data */
CustomData_to_bmesh_block(&me->pdata, &bm->pdata, i, &f->head.data, true);
bm_elem_check_toolflags(bm, (BMElem *)f);
if (has_ids & BM_FACE) {
if (use_exist_ids & BM_FACE) {
bm_assign_id(bm, (BMElem *)f, existing_id_layers[3][i], false);

View File

@ -34,7 +34,9 @@ static BMVert *bm_vert_copy(BMesh *bm_src, BMesh *bm_dst, BMVert *v_src)
{
BMVert *v_dst = BM_vert_create(bm_dst, v_src->co, NULL, BM_CREATE_SKIP_CD);
BM_elem_attrs_copy(bm_src, bm_dst, v_src, v_dst);
bm_alloc_id(bm_dst, (BMElem *)v_dst);
bm_elem_check_toolflags(bm_dst, (BMElem *)v_dst);
return v_dst;
}
@ -47,8 +49,11 @@ static BMEdge *bm_edge_copy_with_arrays(BMesh *bm_src,
BMVert *e_dst_v1 = verts_dst[BM_elem_index_get(e_src->v1)];
BMVert *e_dst_v2 = verts_dst[BM_elem_index_get(e_src->v2)];
BMEdge *e_dst = BM_edge_create(bm_dst, e_dst_v1, e_dst_v2, NULL, BM_CREATE_SKIP_CD);
BM_elem_attrs_copy(bm_src, bm_dst, e_src, e_dst);
bm_alloc_id(bm_dst, (BMElem *)e_dst);
bm_elem_check_toolflags(bm_dst, (BMElem *)e_dst);
return e_dst;
}
@ -78,7 +83,9 @@ static BMFace *bm_face_copy_with_arrays(
/* Copy attributes. */
BM_elem_attrs_copy(bm_src, bm_dst, f_src, f_dst);
bm_alloc_id(bm_dst, (BMElem *)f_dst);
bm_elem_check_toolflags(bm_dst, (BMElem *)f_dst);
/* Copy per-loop custom data. */
l_iter_src = l_first_src;

View File

@ -593,7 +593,7 @@ BMVert *BM_edge_collapse(BMesh *bm,
* \param r_e: The newly created edge.
* \return The new vertex.
*/
BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac)
ATTR_NO_OPT BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac)
{
BMVert *v_new, *v_other;
BMEdge *e_new;

View File

@ -21,6 +21,7 @@
*/
#include "BLI_ghash.h"
#include "DNA_meshdata_types.h"
#include <stdarg.h>
@ -68,122 +69,142 @@ extern "C" {
struct GHashIterator;
BLI_INLINE BMFlagLayer *BMO_elem_flag_from_header(BMHeader *ele_head)
ATTR_NO_OPT static BMFlagLayer *BMO_elem_flag_from_header(BMesh *bm, BMElem *ele)
{
switch (ele_head->htype) {
int cd_tflags;
switch (ele->head.htype) {
case BM_VERT:
return ((BMVert_OFlag *)ele_head)->oflags;
cd_tflags = bm->vdata.layers[bm->vdata.typemap[CD_TOOLFLAGS]].offset;
break;
case BM_EDGE:
return ((BMEdge_OFlag *)ele_head)->oflags;
cd_tflags = bm->edata.layers[bm->edata.typemap[CD_TOOLFLAGS]].offset;
break;
case BM_FACE:
cd_tflags = bm->pdata.layers[bm->pdata.typemap[CD_TOOLFLAGS]].offset;
break;
default:
return ((BMFace_OFlag *)ele_head)->oflags;
return NULL;
}
MToolFlags *flags = (MToolFlags *)BM_ELEM_CD_GET_VOID_P(ele, cd_tflags);
return (BMFlagLayer *)flags->flag;
}
#define BMO_elem_flag_test(bm, ele, oflag) \
_bmo_elem_flag_test(bm, BMO_elem_flag_from_header(&(ele)->head), oflag)
_bmo_elem_flag_test(bm, BMO_elem_flag_from_header(bm, (BMElem *)(ele)), oflag)
#define BMO_elem_flag_test_bool(bm, ele, oflag) \
_bmo_elem_flag_test_bool(bm, BMO_elem_flag_from_header(&(ele)->head), oflag)
_bmo_elem_flag_test_bool(bm, BMO_elem_flag_from_header(bm, (BMElem *)(ele)), oflag)
#define BMO_elem_flag_enable(bm, ele, oflag) \
_bmo_elem_flag_enable( \
bm, (BM_CHECK_TYPE_ELEM_NONCONST(ele), BMO_elem_flag_from_header(&(ele)->head)), oflag)
bm, \
(BM_CHECK_TYPE_ELEM_NONCONST(ele), BMO_elem_flag_from_header(bm, (BMElem *)(ele))), \
oflag)
#define BMO_elem_flag_disable(bm, ele, oflag) \
_bmo_elem_flag_disable( \
bm, (BM_CHECK_TYPE_ELEM_NONCONST(ele), BMO_elem_flag_from_header(&(ele)->head)), oflag)
bm, \
(BM_CHECK_TYPE_ELEM_NONCONST(ele), BMO_elem_flag_from_header(bm, (BMElem *)(ele))), \
oflag)
#define BMO_elem_flag_set(bm, ele, oflag, val) \
_bmo_elem_flag_set(bm, \
(BM_CHECK_TYPE_ELEM_NONCONST(ele), BMO_elem_flag_from_header(&(ele)->head)), \
oflag, \
val)
_bmo_elem_flag_set( \
bm, \
(BM_CHECK_TYPE_ELEM_NONCONST(ele), BMO_elem_flag_from_header(bm, (BMElem *)(ele))), \
oflag, \
val)
#define BMO_elem_flag_toggle(bm, ele, oflag) \
_bmo_elem_flag_toggle( \
bm, (BM_CHECK_TYPE_ELEM_NONCONST(ele), BMO_elem_flag_from_header(&(ele)->head)), oflag)
bm, \
(BM_CHECK_TYPE_ELEM_NONCONST(ele), BMO_elem_flag_from_header(bm, (BMElem *)(ele))), \
oflag)
/* take care not to instantiate args multiple times */
#ifdef __GNUC___
# define _BMO_CAST_V_CONST(e) \
({ \
#ifdef __GNUC__
/* clang-format off */
#define _BMO_CAST_V_CONST(bm, e) ({\
typeof(e) _e = e; \
(BM_CHECK_TYPE_VERT(_e), \
(const BMFlagLayer*) BMO_elem_flag_from_header(bm, \
BLI_assert(((const BMHeader *)_e)->htype == BM_VERT), \
(const BMVert_OFlag *)_e); \
})
# define _BMO_CAST_E_CONST(e) \
({ \
typeof(e) _e = e; \
(BM_CHECK_TYPE_EDGE(_e), \
BLI_assert(((const BMHeader *)_e)->htype == BM_EDGE), \
(const BMEdge_OFlag *)_e); \
})
# define _BMO_CAST_F_CONST(e) \
({ \
typeof(e) _e = e; \
(BM_CHECK_TYPE_FACE(_e), \
BLI_assert(((const BMHeader *)_e)->htype == BM_FACE), \
(const BMFace_OFlag *)_e); \
})
# define _BMO_CAST_V(e) \
({ \
(BMElem*)_e)); \
})
#define _BMO_CAST_V(bm, e) ({\
typeof(e) _e = e; \
(BM_CHECK_TYPE_VERT_NONCONST(_e), \
BLI_assert(((BMHeader *)_e)->htype == BM_VERT), \
(BMVert_OFlag *)_e); \
})
# define _BMO_CAST_E(e) \
({ \
BMO_elem_flag_from_header(bm, \
BLI_assert(((const BMHeader *)_e)->htype == BM_VERT), \
(BMElem*)_e)); \
})
#define _BMO_CAST_E_CONST(bm, e) ({\
typeof(e) _e = e; \
(BM_CHECK_TYPE_EDGE_NONCONST(_e), \
BLI_assert(((BMHeader *)_e)->htype == BM_EDGE), \
(BMEdge_OFlag *)_e); \
})
# define _BMO_CAST_F(e) \
({ \
(BM_CHECK_TYPE_VERT(_e), \
(const BMFlagLayer*) BMO_elem_flag_from_header(bm, \
BLI_assert(((const BMHeader *)_e)->htype == BM_EDGE), \
(BMElem*)_e)); \
})
#define _BMO_CAST_E(bm, e) ({\
typeof(e) _e = e; \
(BM_CHECK_TYPE_FACE_NONCONST(_e), \
BLI_assert(((BMHeader *)_e)->htype == BM_FACE), \
(BMFace_OFlag *)_e); \
})
(BM_CHECK_TYPE_VERT_NONCONST(_e), \
BMO_elem_flag_from_header(bm, \
BLI_assert(((const BMHeader *)_e)->htype == BM_EDGE), \
(BMElem*)_e)); \
})
#define _BMO_CAST_F_CONST(bm, e) ({\
typeof(e) _e = e; \
(BM_CHECK_TYPE_VERT(_e), \
(const BMFlagLayer*) BMO_elem_flag_from_header(bm, \
BLI_assert(((const BMHeader *)_e)->htype == BM_FACE), \
(BMElem*)_e)); \
})
#define _BMO_CAST_F(bm, e) ({\
typeof(e) _e = e; \
(BM_CHECK_TYPE_VERT_NONCONST(_e), \
BMO_elem_flag_from_header(bm, \
BLI_assert(((const BMHeader *)_e)->htype == BM_FACE), \
(BMElem*)_e)); \
})
/* clang-format on */
#else
# define _BMO_CAST_V_CONST(e) (BM_CHECK_TYPE_VERT(e), (const BMVert_OFlag *)e)
# define _BMO_CAST_E_CONST(e) (BM_CHECK_TYPE_EDGE(e), (const BMEdge_OFlag *)e)
# define _BMO_CAST_F_CONST(e) (BM_CHECK_TYPE_FACE(e), (const BMFace_OFlag *)e)
# define _BMO_CAST_V(e) (BM_CHECK_TYPE_VERT_NONCONST(e), (BMVert_OFlag *)e)
# define _BMO_CAST_E(e) (BM_CHECK_TYPE_EDGE_NONCONST(e), (BMEdge_OFlag *)e)
# define _BMO_CAST_F(e) (BM_CHECK_TYPE_FACE_NONCONST(e), (BMFace_OFlag *)e)
# define _BMO_CAST_V_CONST(bm, e) \
(BM_CHECK_TYPE_VERT(e), (const BMFlagLayer *)BMO_elem_flag_from_header(bm, (BMElem *)(e)))
# define _BMO_CAST_E_CONST(bm, e) \
(BM_CHECK_TYPE_EDGE(e), (const BMFlagLayer *)BMO_elem_flag_from_header(bm, (BMElem *)(e)))
# define _BMO_CAST_F_CONST(bm, e) \
(BM_CHECK_TYPE_FACE(e), (const BMFlagLayer *)BMO_elem_flag_from_header(bm, (BMElem *)(e)))
# define _BMO_CAST_V(bm, e) \
(BM_CHECK_TYPE_VERT_NONCONST(e), BMO_elem_flag_from_header(bm, (BMElem *)(e)))
# define _BMO_CAST_E(bm, e) \
(BM_CHECK_TYPE_EDGE_NONCONST(e), BMO_elem_flag_from_header(bm, (BMElem *)(e)))
# define _BMO_CAST_F(bm, e) \
(BM_CHECK_TYPE_FACE_NONCONST(e), BMO_elem_flag_from_header(bm, (BMElem *)(e)))
#endif
#define BMO_vert_flag_test(bm, e, oflag) \
_bmo_elem_flag_test(bm, _BMO_CAST_V_CONST(e)->oflags, oflag)
#define BMO_vert_flag_test(bm, e, oflag) _bmo_elem_flag_test(bm, _BMO_CAST_V_CONST(bm, e), oflag)
#define BMO_vert_flag_test_bool(bm, e, oflag) \
_bmo_elem_flag_test_bool(bm, _BMO_CAST_V_CONST(e)->oflags, oflag)
#define BMO_vert_flag_enable(bm, e, oflag) _bmo_elem_flag_enable(bm, _BMO_CAST_V(e)->oflags, oflag)
#define BMO_vert_flag_disable(bm, e, oflag) \
_bmo_elem_flag_disable(bm, _BMO_CAST_V(e)->oflags, oflag)
#define BMO_vert_flag_set(bm, e, oflag, val) \
_bmo_elem_flag_set(bm, _BMO_CAST_V(e)->oflags, oflag, val)
#define BMO_vert_flag_toggle(bm, e, oflag) _bmo_elem_flag_toggle(bm, _BMO_CAST_V(e)->oflags, oflag)
_bmo_elem_flag_test_bool(bm, _BMO_CAST_V_CONST(bm, e), oflag)
#define BMO_vert_flag_enable(bm, e, oflag) _bmo_elem_flag_enable(bm, _BMO_CAST_V(bm, e), oflag)
#define BMO_vert_flag_disable(bm, e, oflag) _bmo_elem_flag_disable(bm, _BMO_CAST_V(bm, e), oflag)
#define BMO_vert_flag_set(bm, e, oflag, val) _bmo_elem_flag_set(bm, _BMO_CAST_V(bm, e), oflag, val)
#define BMO_vert_flag_toggle(bm, e, oflag) _bmo_elem_flag_toggle(bm, _BMO_CAST_V(bm, e), oflag)
#define BMO_edge_flag_test(bm, e, oflag) \
_bmo_elem_flag_test(bm, _BMO_CAST_E_CONST(e)->oflags, oflag)
#define BMO_edge_flag_test(bm, e, oflag) _bmo_elem_flag_test(bm, _BMO_CAST_E_CONST(bm, e), oflag)
#define BMO_edge_flag_test_bool(bm, e, oflag) \
_bmo_elem_flag_test_bool(bm, _BMO_CAST_E_CONST(e)->oflags, oflag)
#define BMO_edge_flag_enable(bm, e, oflag) _bmo_elem_flag_enable(bm, _BMO_CAST_E(e)->oflags, oflag)
#define BMO_edge_flag_disable(bm, e, oflag) \
_bmo_elem_flag_disable(bm, _BMO_CAST_E(e)->oflags, oflag)
#define BMO_edge_flag_set(bm, e, oflag, val) \
_bmo_elem_flag_set(bm, _BMO_CAST_E(e)->oflags, oflag, val)
#define BMO_edge_flag_toggle(bm, e, oflag) _bmo_elem_flag_toggle(bm, _BMO_CAST_E(e)->oflags, oflag)
_bmo_elem_flag_test_bool(bm, _BMO_CAST_E_CONST(bm, e), oflag)
#define BMO_edge_flag_enable(bm, e, oflag) _bmo_elem_flag_enable(bm, _BMO_CAST_E(bm, e), oflag)
#define BMO_edge_flag_disable(bm, e, oflag) _bmo_elem_flag_disable(bm, _BMO_CAST_E(bm, e), oflag)
#define BMO_edge_flag_set(bm, e, oflag, val) _bmo_elem_flag_set(bm, _BMO_CAST_E(bm, e), oflag, val)
#define BMO_edge_flag_toggle(bm, e, oflag) _bmo_elem_flag_toggle(bm, _BMO_CAST_E(bm, e), oflag)
#define BMO_face_flag_test(bm, e, oflag) \
_bmo_elem_flag_test(bm, _BMO_CAST_F_CONST(e)->oflags, oflag)
#define BMO_face_flag_test(bm, e, oflag) _bmo_elem_flag_test(bm, _BMO_CAST_F_CONST(bm, e), oflag)
#define BMO_face_flag_test_bool(bm, e, oflag) \
_bmo_elem_flag_test_bool(bm, _BMO_CAST_F_CONST(e)->oflags, oflag)
#define BMO_face_flag_enable(bm, e, oflag) _bmo_elem_flag_enable(bm, _BMO_CAST_F(e)->oflags, oflag)
#define BMO_face_flag_disable(bm, e, oflag) \
_bmo_elem_flag_disable(bm, _BMO_CAST_F(e)->oflags, oflag)
#define BMO_face_flag_set(bm, e, oflag, val) \
_bmo_elem_flag_set(bm, _BMO_CAST_F(e)->oflags, oflag, val)
#define BMO_face_flag_toggle(bm, e, oflag) _bmo_elem_flag_toggle(bm, _BMO_CAST_F(e)->oflags, oflag)
_bmo_elem_flag_test_bool(bm, _BMO_CAST_F_CONST(bm, e), oflag)
#define BMO_face_flag_enable(bm, e, oflag) _bmo_elem_flag_enable(bm, _BMO_CAST_F(bm, e), oflag)
#define BMO_face_flag_disable(bm, e, oflag) _bmo_elem_flag_disable(bm, _BMO_CAST_F(bm, e), oflag)
#define BMO_face_flag_set(bm, e, oflag, val) _bmo_elem_flag_set(bm, _BMO_CAST_F(bm, e), oflag, val)
#define BMO_face_flag_toggle(bm, e, oflag) _bmo_elem_flag_toggle(bm, _BMO_CAST_F(bm, e), oflag)
BLI_INLINE short _bmo_elem_flag_test(BMesh *bm, const BMFlagLayer *oflags, const short oflag);
BLI_INLINE bool _bmo_elem_flag_test_bool(BMesh *bm, const BMFlagLayer *oflags, const short oflag);

View File

@ -30,6 +30,7 @@ ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE
short _bmo_elem_flag_test(BMesh *bm, const BMFlagLayer *oflags, const short oflag)
{
BLI_assert(bm->use_toolflags);
return oflags[bm->toolflag_index].f & oflag;
}

View File

@ -31,9 +31,13 @@
#include "BLT_translation.h"
#include "BKE_customdata.h"
#include "bmesh.h"
#include "intern/bmesh_private.h"
#include "DNA_meshdata_types.h"
/* forward declarations */
static void bmo_flag_layer_alloc(BMesh *bm);
static void bmo_flag_layer_free(BMesh *bm);
@ -1248,6 +1252,68 @@ void BMO_slot_buffer_flag_disable(BMesh *bm,
}
}
ATTR_NO_OPT static void bmo_flag_layer_do(BMesh *bm,
int new_totflags,
void (*callback)(BMesh *bm,
int cd_tflags,
int itertype,
int htype,
int totelem,
int new_totflags,
BLI_mempool **pool_ptr))
{
int iters[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
int types[3] = {BM_VERT, BM_EDGE, BM_FACE};
int tots[3] = {bm->totvert, bm->totedge, bm->totface};
BLI_mempool **pools[3] = {&bm->vtoolflagpool, &bm->etoolflagpool, &bm->ftoolflagpool};
CustomData *cdatas[3] = {&bm->vdata, &bm->edata, &bm->pdata};
for (int i = 0; i < 3; i++) {
int cd_tflags = CustomData_get_offset(cdatas[i], CD_TOOLFLAGS);
if (cd_tflags == -1) {
printf("eek!\n");
}
callback(bm, cd_tflags, iters[i], types[i], tots[i], new_totflags, pools[i]);
}
bm->totflags = new_totflags;
}
ATTR_NO_OPT static void bmo_flag_layer_alloc_do(BMesh *bm,
int cd_tflags,
int itertype,
int htype,
int totelem,
int new_totflags,
BLI_mempool **pool_ptr)
{
BMIter iter;
BMElem *elem;
int i;
const size_t old_totflags_size = (bm->totflags * sizeof(BMFlagLayer));
BLI_mempool *oldpool = *pool_ptr;
BLI_mempool *newpool = BLI_mempool_create(
sizeof(BMFlagLayer) * new_totflags, totelem, 512, BLI_MEMPOOL_NOP);
BM_ITER_MESH_INDEX (elem, &iter, bm, itertype, i) {
MToolFlags *flags = BM_ELEM_CD_GET_VOID_P(elem, cd_tflags);
short *oldflags = flags->flag;
flags->flag = BLI_mempool_calloc(newpool);
memcpy(flags->flag, oldflags, old_totflags_size);
BM_elem_index_set(elem, i); /* set_inline */
BM_ELEM_API_FLAG_CLEAR((BMElemF *)elem);
}
*pool_ptr = newpool;
BLI_mempool_destroy(oldpool);
}
/**
* \brief ALLOC/FREE FLAG LAYER
*
@ -1261,165 +1327,42 @@ void BMO_slot_buffer_flag_disable(BMesh *bm,
* all operators have been executed. This would
* save a lot of realloc potentially.
*/
static void bmo_flag_layer_alloc(BMesh *bm)
ATTR_NO_OPT static void bmo_flag_layer_alloc(BMesh *bm)
{
/* set the index values since we are looping over all data anyway,
* may save time later on */
BLI_mempool *voldpool = bm->vtoolflagpool; /* old flag pool */
BLI_mempool *eoldpool = bm->etoolflagpool; /* old flag pool */
BLI_mempool *foldpool = bm->ftoolflagpool; /* old flag pool */
/* store memcpy size for reuse */
const size_t old_totflags_size = (bm->totflags * sizeof(BMFlagLayer));
bm->totflags++;
bm->vtoolflagpool = BLI_mempool_create(
sizeof(BMFlagLayer) * bm->totflags, bm->totvert, 512, BLI_MEMPOOL_NOP);
bm->etoolflagpool = BLI_mempool_create(
sizeof(BMFlagLayer) * bm->totflags, bm->totedge, 512, BLI_MEMPOOL_NOP);
bm->ftoolflagpool = BLI_mempool_create(
sizeof(BMFlagLayer) * bm->totflags, bm->totface, 512, BLI_MEMPOOL_NOP);
/* now go through and memcpy all the flags. Loops don't get a flag layer at this time. */
BMIter iter;
int i;
BMVert_OFlag *v_oflag;
BLI_mempool *newpool = bm->vtoolflagpool;
BM_ITER_MESH_INDEX (v_oflag, &iter, bm, BM_VERTS_OF_MESH, i) {
void *oldflags = v_oflag->oflags;
v_oflag->oflags = BLI_mempool_calloc(newpool);
memcpy(v_oflag->oflags, oldflags, old_totflags_size);
BM_elem_index_set(&v_oflag->base, i); /* set_inline */
BM_ELEM_API_FLAG_CLEAR((BMElemF *)v_oflag);
}
BMEdge_OFlag *e_oflag;
newpool = bm->etoolflagpool;
BM_ITER_MESH_INDEX (e_oflag, &iter, bm, BM_EDGES_OF_MESH, i) {
void *oldflags = e_oflag->oflags;
e_oflag->oflags = BLI_mempool_calloc(newpool);
memcpy(e_oflag->oflags, oldflags, old_totflags_size);
BM_elem_index_set(&e_oflag->base, i); /* set_inline */
BM_ELEM_API_FLAG_CLEAR((BMElemF *)e_oflag);
}
BMFace_OFlag *f_oflag;
newpool = bm->ftoolflagpool;
BM_ITER_MESH_INDEX (f_oflag, &iter, bm, BM_FACES_OF_MESH, i) {
void *oldflags = f_oflag->oflags;
f_oflag->oflags = BLI_mempool_calloc(newpool);
memcpy(f_oflag->oflags, oldflags, old_totflags_size);
BM_elem_index_set(&f_oflag->base, i); /* set_inline */
BM_ELEM_API_FLAG_CLEAR((BMElemF *)f_oflag);
}
BLI_mempool_destroy(voldpool);
BLI_mempool_destroy(eoldpool);
BLI_mempool_destroy(foldpool);
bmo_flag_layer_do(bm, bm->totflags + 1, bmo_flag_layer_alloc_do);
bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE);
}
static void bmo_flag_layer_free(BMesh *bm)
ATTR_NO_OPT static void bmo_flag_layer_free(BMesh *bm)
{
/* set the index values since we are looping over all data anyway,
* may save time later on */
BLI_mempool *voldpool = bm->vtoolflagpool;
BLI_mempool *eoldpool = bm->etoolflagpool;
BLI_mempool *foldpool = bm->ftoolflagpool;
bmo_flag_layer_do(bm, bm->totflags - 1, bmo_flag_layer_alloc_do);
bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE);
}
/* store memcpy size for reuse */
const size_t new_totflags_size = ((bm->totflags - 1) * sizeof(BMFlagLayer));
/* de-increment the totflags first. */
bm->totflags--;
bm->vtoolflagpool = BLI_mempool_create(new_totflags_size, bm->totvert, 512, BLI_MEMPOOL_NOP);
bm->etoolflagpool = BLI_mempool_create(new_totflags_size, bm->totedge, 512, BLI_MEMPOOL_NOP);
bm->ftoolflagpool = BLI_mempool_create(new_totflags_size, bm->totface, 512, BLI_MEMPOOL_NOP);
/* now go through and memcpy all the flag */
ATTR_NO_OPT static void bmo_flag_layer_clear_do(BMesh *bm,
int cd_tflags,
int itertype,
int htype,
int totelem,
int totflag,
BLI_mempool **pool_ptr)
{
BMIter iter;
BMElem *elem;
int i;
BMVert_OFlag *v_oflag;
BLI_mempool *newpool = bm->vtoolflagpool;
BM_ITER_MESH_INDEX (v_oflag, &iter, bm, BM_VERTS_OF_MESH, i) {
void *oldflags = v_oflag->oflags;
v_oflag->oflags = BLI_mempool_alloc(newpool);
memcpy(v_oflag->oflags, oldflags, new_totflags_size);
BM_elem_index_set(&v_oflag->base, i); /* set_inline */
BM_ELEM_API_FLAG_CLEAR((BMElemF *)v_oflag);
BM_ITER_MESH_INDEX (elem, &iter, bm, itertype, i) {
MToolFlags *flags = BM_ELEM_CD_GET_VOID_P(elem, cd_tflags);
flags->flag[totflag - 1] = 0;
BM_elem_index_set(elem, i); /* set_inline */
}
BMEdge_OFlag *e_oflag;
newpool = bm->etoolflagpool;
BM_ITER_MESH_INDEX (e_oflag, &iter, bm, BM_EDGES_OF_MESH, i) {
void *oldflags = e_oflag->oflags;
e_oflag->oflags = BLI_mempool_alloc(newpool);
memcpy(e_oflag->oflags, oldflags, new_totflags_size);
BM_elem_index_set(&e_oflag->base, i); /* set_inline */
BM_ELEM_API_FLAG_CLEAR((BMElemF *)e_oflag);
}
BMFace_OFlag *f_oflag;
newpool = bm->ftoolflagpool;
BM_ITER_MESH_INDEX (f_oflag, &iter, bm, BM_FACES_OF_MESH, i) {
void *oldflags = f_oflag->oflags;
f_oflag->oflags = BLI_mempool_alloc(newpool);
memcpy(f_oflag->oflags, oldflags, new_totflags_size);
BM_elem_index_set(&f_oflag->base, i); /* set_inline */
BM_ELEM_API_FLAG_CLEAR((BMElemF *)f_oflag);
}
BLI_mempool_destroy(voldpool);
BLI_mempool_destroy(eoldpool);
BLI_mempool_destroy(foldpool);
bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE);
}
static void bmo_flag_layer_clear(BMesh *bm)
{
/* set the index values since we are looping over all data anyway,
* may save time later on */
const BMFlagLayer zero_flag = {0};
const int totflags_offset = bm->totflags - 1;
/* now go through and memcpy all the flag */
{
BMIter iter;
BMVert_OFlag *ele;
int i;
BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) {
ele->oflags[totflags_offset] = zero_flag;
BM_elem_index_set(&ele->base, i); /* set_inline */
}
}
{
BMIter iter;
BMEdge_OFlag *ele;
int i;
BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) {
ele->oflags[totflags_offset] = zero_flag;
BM_elem_index_set(&ele->base, i); /* set_inline */
}
}
{
BMIter iter;
BMFace_OFlag *ele;
int i;
BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) {
ele->oflags[totflags_offset] = zero_flag;
BM_elem_index_set(&ele->base, i); /* set_inline */
}
}
bmo_flag_layer_do(bm, bm->totflags, bmo_flag_layer_clear_do);
bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE);
}

View File

@ -53,8 +53,9 @@ int bmesh_radial_length(const BMLoop *l);
int bmesh_disk_count_at_most(const BMVert *v, const int count_max);
int bmesh_disk_count(const BMVert *v);
void bm_rebuild_idmap(BMesh *bm);
void bm_alloc_toolflags_cdlayers(BMesh *bm, bool set_elems);
/**
/**
* Internal BMHeader.api_flag
* \note Ensure different parts of the API do not conflict
* on using these internal flags!

View File

@ -63,6 +63,7 @@ static BMVert *bmo_vert_copy(BMOperator *op,
/* Handle Ids */
bm_alloc_id(bm_dst, (BMElem *)v_dst);
bm_elem_check_toolflags(bm_dst, (BMElem *)v_dst);
/* Mark the vert for output */
BMO_vert_flag_enable(bm_dst, v_dst, DUPE_NEW);
@ -128,6 +129,7 @@ static BMEdge *bmo_edge_copy(BMOperator *op,
/* Handle Ids */
bm_alloc_id(bm_dst, (BMElem *)e_dst);
bm_elem_check_toolflags(bm_dst, (BMElem *)e_dst);
/* Mark the edge for output */
BMO_edge_flag_enable(bm_dst, e_dst, DUPE_NEW);
@ -181,8 +183,9 @@ static BMFace *bmo_face_copy(BMOperator *op,
/* Copy attributes */
BM_elem_attrs_copy(bm_src, bm_dst, f_src, f_dst);
/* Handle Ids */
/* Handle Ids and toolflags */
bm_alloc_id(bm_dst, (BMElem *)f_dst);
bm_elem_check_toolflags(bm_dst, (BMElem *)f_dst);
/* copy per-loop custom data */
l_iter_src = l_first_src;

View File

@ -28,6 +28,7 @@
#include "BLI_math.h"
#include "BLI_stack.h"
#include "BLI_utildefines_stack.h"
#include "DNA_meshdata_types.h"
#include "BKE_customdata.h"
@ -290,7 +291,12 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op)
bmesh_face_swap_data(f_new, f);
if (bm->use_toolflags) {
SWAP(BMFlagLayer *, ((BMFace_OFlag *)f)->oflags, ((BMFace_OFlag *)f_new)->oflags);
MToolFlags *flags = (MToolFlags *)BM_ELEM_CD_GET_VOID_P(
f, bm->pdata.layers[bm->pdata.typemap[CD_TOOLFLAGS]].offset);
MToolFlags *flags_new = (MToolFlags *)BM_ELEM_CD_GET_VOID_P(
f_new, bm->pdata.layers[bm->pdata.typemap[CD_TOOLFLAGS]].offset);
SWAP(short *, flags->flag, flags_new->flag);
}
BMO_face_flag_disable(bm, f, ELE_DEL);

View File

@ -2451,6 +2451,7 @@ ATTR_NO_OPT static void sculpt_face_set_extrude_id(
BMesh *bm = sculpt_faceset_bm_begin(ss, mesh);
if (ss->bm) {
BKE_pbvh_bmesh_set_toolflags(ss->pbvh, true);
SCULPT_update_customdata_refs(ss);
}
BM_mesh_elem_table_init(bm, BM_FACE);
@ -2653,7 +2654,7 @@ ATTR_NO_OPT static void sculpt_face_set_extrude_id(
case BM_EDGE: {
BMEdge *e = (BMEdge *)ele;
BM_log_edge_added(ss->bm_log, e);
#if 0
if (!BM_elem_flag_test(e->v1, tag1)) {
BM_elem_flag_enable(e->v1, tag1);
BM_log_vert_added(ss->bm_log, e->v1, ss->cd_vert_mask_offset);
@ -2680,7 +2681,7 @@ ATTR_NO_OPT static void sculpt_face_set_extrude_id(
} while ((l = l->radial_next) != e->l);
}
}
#endif
break;
}
case BM_FACE: {
@ -2689,7 +2690,7 @@ ATTR_NO_OPT static void sculpt_face_set_extrude_id(
if (dot_v3v3(f->no, f->no) > 0.0f) {
add_v3_v3(no, f->no);
}
#if 0
BMLoop *l = f->l_first;
do {
if (!(l->v->head.hflag & tag1)) {
@ -2702,7 +2703,7 @@ ATTR_NO_OPT static void sculpt_face_set_extrude_id(
BM_log_edge_added(ss->bm_log, l->e);
}
} while ((l = l->next) != f->l_first);
#endif
BKE_pbvh_bmesh_add_face(ss->pbvh, f, false, false);
BM_log_face_added(ss->bm_log, f);
break;
@ -2757,7 +2758,8 @@ ATTR_NO_OPT static void sculpt_face_set_extrude_id(
if (cd_dyn_vert >= 0) {
do {
MDynTopoVert *mv = BM_ELEM_CD_GET_VOID_P(l->v, cd_dyn_vert);
mv->flag |= DYNVERT_NEED_BOUNDARY|DYNVERT_NEED_DISK_SORT|DYNVERT_NEED_TRIANGULATE|DYNVERT_NEED_VALENCE;
mv->flag |= DYNVERT_NEED_BOUNDARY | DYNVERT_NEED_DISK_SORT | DYNVERT_NEED_TRIANGULATE |
DYNVERT_NEED_VALENCE;
} while ((l = l->next) != f->l_first);
}
@ -2841,6 +2843,7 @@ ATTR_NO_OPT static void sculpt_face_set_extrude_id(
sculpt_faceset_bm_end(ss, bm);
if (ss->bm) {
BKE_pbvh_bmesh_set_toolflags(ss->pbvh, false);
SCULPT_update_customdata_refs(ss);
}
}

View File

@ -84,8 +84,7 @@ typedef struct CustomData {
* MUST be >= CD_NUMTYPES, but we can't use a define here.
* Correct size is ensured in CustomData_update_typemap assert().
*/
int typemap[54];
char _pad[4];
int typemap[55];
/** Number of layers, size of layers array. */
int totlayer, maxlayer;
@ -171,7 +170,8 @@ typedef enum CustomDataType {
CD_HAIRLENGTH = 51,
CD_MESH_ID = 52,
CD_DYNTOPO_VERT = 53,
CD_NUMTYPES = 54,
CD_TOOLFLAGS = 54,
CD_NUMTYPES = 55,
} CustomDataType;
/* Bits for CustomDataMask */
@ -228,6 +228,7 @@ typedef enum CustomDataType {
#define CD_MASK_DYNTOPO_VERT (1ULL << CD_DYNTOPO_VERT)
#define CD_MASK_MESH_ID (1ULL << CD_MESH_ID)
#define CD_MASK_HAIRLENGTH (1ULL << CD_HAIRLENGTH)
#define CD_MASK_TOOLFLAGS (1ULL << CD_TOOLFLAGS)
/** Multires loop data. */
#define CD_MASK_MULTIRES_GRIDS (CD_MASK_MDISPS | CD_GRID_PAINT_MASK)

View File

@ -542,7 +542,7 @@ typedef struct MDynTopoVert {
int stroke_id;
} MDynTopoVert;
/*MDynTopoVert->flag*/
/* MDynTopoVert->flag */
enum {
DYNVERT_BOUNDARY = (1 << 0),
DYNVERT_VERT_FSET_HIDDEN = (1 << 1),
@ -561,6 +561,11 @@ enum {
DYNVERT_PBVH_BOUNDARY = (1 << 14)
};
/* for internal bmesh toolflags api */
typedef struct MToolFlags {
short *flag;
} MToolFlags;
#ifdef __cplusplus
}
#endif