Sculpt: Fix broken multires hidden undo

Wrote a new API method, BKE_pbvh_sync_visibility_from_verts
that flushes vertex hidden flags to edges & faces.

Fixes not being able to sculpt outside a face set after
undoing the fkey hide-all-but-this operator.
This commit is contained in:
Joseph Eagar 2022-11-22 10:51:28 -08:00
parent f8d6bbeb63
commit a2a72d89b1
3 changed files with 99 additions and 6 deletions

View File

@ -389,6 +389,8 @@ void BKE_pbvh_bounding_box(const PBVH *pbvh, float min[3], float max[3]);
*/
unsigned int **BKE_pbvh_grid_hidden(const PBVH *pbvh);
void BKE_pbvh_sync_visibility_from_verts(PBVH *pbvh, struct Mesh *me);
/**
* Returns the number of visible quads in the nodes' grids.
*/

View File

@ -841,7 +841,7 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
for (int i = 0; i < me->totpoly; i++) {
max_grids = max_ii(max_grids, mpoly[i].totloop);
}
/* Ensure leaf limit is at least 4 so there's room
* to split at original face boundaries.
* Fixes T102209.
@ -3522,3 +3522,92 @@ int BKE_pbvh_debug_draw_gen_get(PBVHNode *node)
{
return node->debug_draw_gen;
}
void BKE_pbvh_sync_visibility_from_verts(PBVH *pbvh, Mesh *mesh)
{
switch (pbvh->header.type) {
case PBVH_FACES: {
BKE_mesh_flush_hidden_from_verts(mesh);
BKE_pbvh_update_hide_attributes_from_mesh(pbvh);
break;
}
case PBVH_BMESH: {
BMIter iter;
BMVert *v;
BMEdge *e;
BMFace *f;
BM_ITER_MESH (f, &iter, pbvh->header.bm, BM_FACES_OF_MESH) {
BM_elem_flag_disable(f, BM_ELEM_HIDDEN);
}
BM_ITER_MESH (e, &iter, pbvh->header.bm, BM_EDGES_OF_MESH) {
BM_elem_flag_disable(e, BM_ELEM_HIDDEN);
}
BM_ITER_MESH (v, &iter, pbvh->header.bm, BM_VERTS_OF_MESH) {
if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
continue;
}
BMIter iter_l;
BMLoop *l;
BM_ITER_ELEM (l, &iter_l, v, BM_LOOPS_OF_VERT) {
BM_elem_flag_enable(l->e, BM_ELEM_HIDDEN);
BM_elem_flag_enable(l->f, BM_ELEM_HIDDEN);
}
}
break;
}
case PBVH_GRIDS: {
const MPoly *mp = BKE_mesh_polys(mesh);
const MLoop *mloop = BKE_mesh_loops(mesh);
CCGKey key = pbvh->gridkey;
bool *hide_poly = (bool *)CustomData_get_layer_named(
&mesh->pdata, CD_PROP_BOOL, ".hide_poly");
bool delete_hide_poly = true;
for (int face_index = 0; face_index < mesh->totpoly; face_index++, mp++) {
const MLoop *ml = mloop + mp->loopstart;
bool hidden = false;
for (int loop_index = 0; !hidden && loop_index < mp->totloop; loop_index++, ml++) {
int grid_index = mp->loopstart + loop_index;
if (pbvh->grid_hidden[grid_index] &&
BLI_BITMAP_TEST(pbvh->grid_hidden[grid_index], key.grid_area - 1)) {
hidden = true;
break;
}
}
if (hidden && !hide_poly) {
hide_poly = (bool *)CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, ".hide_poly");
if (!hide_poly) {
CustomData_add_layer_named(
&mesh->pdata, CD_PROP_BOOL, CD_CONSTRUCT, NULL, mesh->totpoly, ".hide_poly");
hide_poly = (bool *)CustomData_get_layer_named(
&mesh->pdata, CD_PROP_BOOL, ".hide_poly");
}
}
if (hide_poly) {
delete_hide_poly = delete_hide_poly && !hidden;
hide_poly[face_index] = hidden;
}
}
if (delete_hide_poly) {
CustomData_free_layer_named(&mesh->pdata, ".hide_poly", mesh->totpoly);
}
BKE_mesh_flush_hidden_from_polys(mesh);
BKE_pbvh_update_hide_attributes_from_mesh(pbvh);
break;
}
}
}

View File

@ -1058,6 +1058,13 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
}
if (update_visibility) {
if (ELEM(BKE_pbvh_type(ss->pbvh), PBVH_FACES, PBVH_GRIDS)) {
Mesh *me = (Mesh *)ob->data;
BKE_pbvh_sync_visibility_from_verts(ss->pbvh, me);
BKE_pbvh_update_hide_attributes_from_mesh(ss->pbvh);
}
BKE_pbvh_update_visibility(ss->pbvh);
}
@ -1080,11 +1087,6 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
BKE_sculptsession_free_deformMats(ss);
}
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && update_visibility) {
Mesh *mesh = ob->data;
BKE_mesh_flush_hidden_from_verts(mesh);
}
if (tag_update) {
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
}