Sculpt: Fix more attribute bugs when switching PBVH modes
Fixed more cases where attributes weren't being reinitialized on switching PBVH mode: * When PBVH_GRIDS and PBVH_BMESH force attributes into simple array mode they no longer override simple_array in the SculptAttributeParams parameters, instead they set a field in SculptAttribute itself. Thus if the attribute is reinitialized in another mode it won't retain the simple_array parameter. * sculpt_attribute_ensure_ex now calls sculpt_attr_update if the attribute already exists. * Fixed a bug from a couple commits ago that set SculptAttribute.data_for_bmesh wrong.
This commit is contained in:
parent
6f9cfb037a
commit
939b63bcd6
|
@ -516,6 +516,11 @@ typedef struct SculptAttribute {
|
|||
int elem_size, elem_num;
|
||||
bool data_for_bmesh; /* Temporary data store as array outside of bmesh. */
|
||||
|
||||
/* Data is a flat array outside the CustomData system.
|
||||
* This will be true if simple_array is requested in
|
||||
* SculptAttributeParams, or the PBVH type is PBVH_GRIDS or PBVH_BMESH.
|
||||
*/
|
||||
bool simple_array;
|
||||
/* Data stored per BMesh element. */
|
||||
int bmesh_cd_offset;
|
||||
|
||||
|
|
|
@ -426,6 +426,28 @@ void multires_flush_sculpt_updates(Object *object)
|
|||
}
|
||||
|
||||
Mesh *mesh = static_cast<Mesh *>(object->data);
|
||||
|
||||
/* Check that the multires modifier still exists.
|
||||
* Fixes crash when deleting multires modifier
|
||||
* from within sculpt mode.
|
||||
*/
|
||||
ModifierData *md;
|
||||
MultiresModifierData *mmd = nullptr;
|
||||
VirtualModifierData virtualModifierData;
|
||||
|
||||
for (md = BKE_modifiers_get_virtual_modifierlist(object, &virtualModifierData); md;
|
||||
md = md->next) {
|
||||
if (md->type == eModifierType_Multires) {
|
||||
if (BKE_modifier_is_enabled(nullptr, md, eModifierMode_Realtime)) {
|
||||
mmd = (MultiresModifierData *)md;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!mmd) {
|
||||
return;
|
||||
}
|
||||
|
||||
multiresModifier_reshapeFromCCG(
|
||||
sculpt_session->multires.modifier->totlvl, mesh, sculpt_session->subdiv_ccg);
|
||||
|
||||
|
|
|
@ -2454,7 +2454,7 @@ static bool sculpt_attribute_create(SculptSession *ss,
|
|||
permanent = (out->params.permanent = false);
|
||||
}
|
||||
|
||||
simple_array = (out->params.simple_array = true);
|
||||
simple_array = true;
|
||||
}
|
||||
|
||||
BLI_assert(!(simple_array && permanent));
|
||||
|
@ -2466,8 +2466,8 @@ static bool sculpt_attribute_create(SculptSession *ss,
|
|||
|
||||
out->data = MEM_calloc_arrayN(totelem, elemsize, __func__);
|
||||
|
||||
out->data_for_bmesh = false;
|
||||
out->params.simple_array = true;
|
||||
out->data_for_bmesh = ss->bm != nullptr;
|
||||
out->simple_array = true;
|
||||
out->bmesh_cd_offset = -1;
|
||||
out->layer = nullptr;
|
||||
out->elem_size = elemsize;
|
||||
|
@ -2477,6 +2477,8 @@ static bool sculpt_attribute_create(SculptSession *ss,
|
|||
return true;
|
||||
}
|
||||
|
||||
out->simple_array = false;
|
||||
|
||||
switch (BKE_pbvh_type(ss->pbvh)) {
|
||||
case PBVH_BMESH: {
|
||||
CustomData *cdata = nullptr;
|
||||
|
@ -2512,8 +2514,6 @@ static bool sculpt_attribute_create(SculptSession *ss,
|
|||
case PBVH_FACES: {
|
||||
CustomData *cdata = nullptr;
|
||||
|
||||
out->data_for_bmesh = false;
|
||||
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
cdata = &me->vdata;
|
||||
|
@ -2535,10 +2535,10 @@ static bool sculpt_attribute_create(SculptSession *ss,
|
|||
cdata->layers[index].flag |= CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY;
|
||||
}
|
||||
|
||||
out->data = nullptr;
|
||||
out->layer = cdata->layers + index;
|
||||
out->bmesh_cd_offset = -1;
|
||||
out->data = out->layer->data;
|
||||
out->data_for_bmesh = false;
|
||||
out->bmesh_cd_offset = -1;
|
||||
out->elem_size = CustomData_get_elem_size(out->layer);
|
||||
|
||||
break;
|
||||
|
@ -2566,31 +2566,36 @@ static bool sculpt_attr_update(Object *ob, SculptAttribute *attr)
|
|||
|
||||
bool bad = false;
|
||||
|
||||
if (attr->params.simple_array) {
|
||||
if (attr->data) {
|
||||
bad = attr->elem_num != elem_num;
|
||||
|
||||
if (bad) {
|
||||
MEM_SAFE_FREE(attr->data);
|
||||
}
|
||||
else {
|
||||
attr->data_for_bmesh = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
CustomData *cdata = sculpt_get_cdata(ob, attr->domain);
|
||||
|
||||
if (cdata) {
|
||||
int layer_index = CustomData_get_named_layer_index(cdata, attr->proptype, attr->name);
|
||||
/* Check if we are a coerced simple array and shouldn't be. */
|
||||
bad |= attr->simple_array && !attr->params.simple_array &&
|
||||
!ELEM(BKE_pbvh_type(ss->pbvh), PBVH_GRIDS, PBVH_BMESH);
|
||||
|
||||
bad |= (ss->bm != nullptr) != attr->data_for_bmesh;
|
||||
CustomData *cdata = sculpt_get_cdata(ob, attr->domain);
|
||||
if (cdata && !attr->simple_array) {
|
||||
int layer_index = CustomData_get_named_layer_index(cdata, attr->proptype, attr->name);
|
||||
|
||||
bad |= layer_index == -1;
|
||||
bad |= (ss->bm != nullptr) != attr->data_for_bmesh;
|
||||
|
||||
if (!bad) {
|
||||
if (attr->data_for_bmesh) {
|
||||
attr->bmesh_cd_offset = cdata->layers[layer_index].offset;
|
||||
}
|
||||
else {
|
||||
attr->data = cdata->layers[layer_index].data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bad) {
|
||||
if (attr->simple_array) {
|
||||
MEM_SAFE_FREE(attr->data);
|
||||
}
|
||||
|
||||
sculpt_attribute_create(ss,
|
||||
ob,
|
||||
attr->domain,
|
||||
|
@ -2725,6 +2730,8 @@ static SculptAttribute *sculpt_attribute_ensure_ex(Object *ob,
|
|||
SculptAttribute *attr = BKE_sculpt_attribute_get(ob, domain, proptype, name);
|
||||
|
||||
if (attr) {
|
||||
sculpt_attr_update(ob, attr);
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
|
@ -2763,7 +2770,7 @@ static void sculptsession_bmesh_attr_update_internal(Object *ob)
|
|||
}
|
||||
}
|
||||
|
||||
void sculptsession_bmesh_add_layers(Object *ob)
|
||||
static void sculptsession_bmesh_add_layers(Object *ob)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
SculptAttributeParams params = {0};
|
||||
|
@ -2870,7 +2877,7 @@ bool BKE_sculpt_attribute_destroy(Object *ob, SculptAttribute *attr)
|
|||
|
||||
Mesh *me = BKE_object_get_original_mesh(ob);
|
||||
|
||||
if (attr->params.simple_array) {
|
||||
if (attr->simple_array) {
|
||||
MEM_SAFE_FREE(attr->data);
|
||||
}
|
||||
else if (ss->bm) {
|
||||
|
|
|
@ -1368,6 +1368,8 @@ GPUBatch *DRW_pbvh_tris_get(PBVHBatches *batches,
|
|||
int *r_prim_count,
|
||||
bool do_coarse_grids)
|
||||
{
|
||||
do_coarse_grids &= args->pbvh_type == PBVH_GRIDS;
|
||||
|
||||
PBVHBatch &batch = batches->ensure_batch(attrs, attrs_num, args, do_coarse_grids);
|
||||
|
||||
*r_prim_count = batch.tris_count;
|
||||
|
@ -1382,6 +1384,8 @@ GPUBatch *DRW_pbvh_lines_get(PBVHBatches *batches,
|
|||
int *r_prim_count,
|
||||
bool do_coarse_grids)
|
||||
{
|
||||
do_coarse_grids &= args->pbvh_type == PBVH_GRIDS;
|
||||
|
||||
PBVHBatch &batch = batches->ensure_batch(attrs, attrs_num, args, do_coarse_grids);
|
||||
|
||||
*r_prim_count = batch.lines_count;
|
||||
|
|
Loading…
Reference in New Issue