Refactor: Sculpt: Separate geometry and per-node undo step code paths

Sometimes undo data is stored per PBVH node, and sometimes the entire
geometry is stored. Currently these go through the same `undo::push_node`
function, which is confusing and limits improvements we can make to the
pushing of per-node undo data.
This commit is contained in:
Hans Goudey
2024-06-20 10:16:11 -04:00
parent e472055db1
commit 2079507ca5
8 changed files with 34 additions and 25 deletions

View File

@@ -1277,11 +1277,12 @@ static void partialvis_gesture_update_bmesh(gesture::GestureData &gesture_data)
*gesture_data.vc.obact, gesture_data.nodes, operation->action, selection_test_fn);
}
static void hide_show_begin(bContext &C, gesture::GestureData & /*gesture_data*/)
static void hide_show_begin(bContext &C, wmOperator &op, gesture::GestureData & /*gesture_data*/)
{
Object *ob = CTX_data_active_object(&C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(&C);
undo::push_begin(*ob, &op);
BKE_sculpt_object_pbvh_ensure(depsgraph, ob);
}
@@ -1305,6 +1306,7 @@ static void hide_show_end(bContext &C, gesture::GestureData &gesture_data)
{
SCULPT_topology_islands_invalidate(*gesture_data.vc.obact->sculpt);
tag_update_visibility(C);
undo::push_end(*gesture_data.vc.obact);
}
static void hide_show_init_properties(bContext & /*C*/,

View File

@@ -557,10 +557,11 @@ struct MaskOperation {
float value;
};
static void gesture_begin(bContext &C, gesture::GestureData &gesture_data)
static void gesture_begin(bContext &C, wmOperator &op, gesture::GestureData &gesture_data)
{
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(&C);
BKE_sculpt_update_object_for_edit(depsgraph, gesture_data.vc.obact, false);
undo::push_begin(*gesture_data.vc.obact, &op);
}
static float mask_gesture_get_new_value(const float elem, FloodFillMode mode, float value)
@@ -648,6 +649,7 @@ static void gesture_end(bContext &C, gesture::GestureData &gesture_data)
multires_mark_as_modified(depsgraph, gesture_data.vc.obact, MULTIRES_COORDS_MODIFIED);
}
blender::bke::pbvh::update_mask(*gesture_data.ss->pbvh);
undo::push_end(*gesture_data.vc.obact);
}
static void init_operation(bContext &C, gesture::GestureData &gesture_data, wmOperator &op)

View File

@@ -1740,10 +1740,11 @@ struct FaceSetOperation {
int new_face_set_id;
};
static void gesture_begin(bContext &C, gesture::GestureData &gesture_data)
static void gesture_begin(bContext &C, wmOperator &op, gesture::GestureData &gesture_data)
{
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(&C);
BKE_sculpt_update_object_for_edit(depsgraph, gesture_data.vc.obact, false);
undo::push_begin(*gesture_data.vc.obact, &op);
}
static void gesture_apply_mesh(gesture::GestureData &gesture_data, const Span<PBVHNode *> nodes)
@@ -1845,7 +1846,10 @@ static void gesture_apply_for_symmetry_pass(bContext & /*C*/, gesture::GestureDa
}
}
static void gesture_end(bContext & /*C*/, gesture::GestureData & /*gesture_data*/) {}
static void gesture_end(bContext & /*C*/, gesture::GestureData &gesture_data)
{
undo::push_end(*gesture_data.vc.obact);
}
static void init_operation(gesture::GestureData &gesture_data, wmOperator & /*op*/)
{

View File

@@ -444,9 +444,8 @@ bool is_affected(GestureData &gesture_data, const float3 &co, const float3 &vert
void apply(bContext &C, GestureData &gesture_data, wmOperator &op)
{
Operation *operation = gesture_data.operation;
undo::push_begin(*CTX_data_active_object(&C), &op);
operation->begin(C, gesture_data);
operation->begin(C, op, gesture_data);
for (int symmpass = 0; symmpass <= gesture_data.symm; symmpass++) {
if (SCULPT_is_symmetry_iteration_valid(symmpass, gesture_data.symm)) {
@@ -459,8 +458,6 @@ void apply(bContext &C, GestureData &gesture_data, wmOperator &op)
operation->end(C, gesture_data);
undo::push_end(*CTX_data_active_object(&C));
SCULPT_tag_update_overlays(&C);
}
} // namespace blender::ed::sculpt_paint::gesture

View File

@@ -1806,7 +1806,7 @@ struct GestureData {
/* Common abstraction structure for gesture operations. */
struct Operation {
/* Initial setup (data updates, special undo push...). */
void (*begin)(bContext &, GestureData &);
void (*begin)(bContext &, wmOperator &, GestureData &);
/* Apply the gesture action for each symmetry pass. */
void (*apply_for_symmetry_pass)(bContext &, GestureData &);

View File

@@ -24,10 +24,11 @@ struct ProjectOperation {
gesture::Operation operation;
};
static void gesture_begin(bContext &C, gesture::GestureData &gesture_data)
static void gesture_begin(bContext &C, wmOperator &op, gesture::GestureData &gesture_data)
{
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(&C);
BKE_sculpt_update_object_for_edit(depsgraph, gesture_data.vc.obact, false);
undo::push_begin(*gesture_data.vc.obact, &op);
}
static void apply_projection(gesture::GestureData &gesture_data, PBVHNode *node)
@@ -92,6 +93,7 @@ static void gesture_end(bContext &C, gesture::GestureData &gesture_data)
flush_update_step(&C, UpdateType::Position);
flush_update_done(&C, *gesture_data.vc.obact, UpdateType::Position);
undo::push_end(*gesture_data.vc.obact);
}
static void init_operation(gesture::GestureData &gesture_data, wmOperator & /*op*/)

View File

@@ -505,7 +505,7 @@ static void generate_geometry(gesture::GestureData &gesture_data)
update_normals(gesture_data);
}
static void gesture_begin(bContext &C, gesture::GestureData &gesture_data)
static void gesture_begin(bContext &C, wmOperator &op, gesture::GestureData &gesture_data)
{
Object *object = gesture_data.vc.obact;
SculptSession &ss = *object->sculpt;
@@ -522,7 +522,7 @@ static void gesture_begin(bContext &C, gesture::GestureData &gesture_data)
generate_geometry(gesture_data);
SCULPT_topology_islands_invalidate(ss);
BKE_sculpt_update_object_for_edit(depsgraph, gesture_data.vc.obact, false);
undo::push_node(*gesture_data.vc.obact, nullptr, undo::Type::Geometry);
undo::geometry_begin(*gesture_data.vc.obact, &op);
}
static int bm_face_isect_pair(BMFace *f, void * /*user_data*/)
@@ -657,7 +657,7 @@ static void gesture_end(bContext & /*C*/, gesture::GestureData &gesture_data)
free_geometry(gesture_data);
undo::push_node(*gesture_data.vc.obact, nullptr, undo::Type::Geometry);
undo::geometry_end(*object);
BKE_mesh_batch_cache_dirty_tag(mesh, BKE_MESH_BATCH_DIRTY_ALL);
DEG_id_tag_update(&gesture_data.vc.obact->id, ID_RECALC_GEOMETRY);
}

View File

@@ -1304,9 +1304,12 @@ static Node *alloc_node(const Object &object, const PBVHNode *node, const Type t
case Type::DyntopoBegin:
case Type::DyntopoEnd:
case Type::DyntopoSymmetrize:
BLI_assert_msg(0, "Dynamic topology should've already been handled");
/* Dyntopo should be handled elsewhere. */
BLI_assert_unreachable();
break;
case Type::Geometry:
/* See #geometry_push. */
BLI_assert_unreachable();
break;
case Type::FaceSet: {
unode->face_sets.reinitialize(unode->face_indices.size());
@@ -1590,11 +1593,6 @@ Node *push_node(const Object &object, const PBVHNode *node, Type type)
// return unode;
return;
}
if (type == Type::Geometry) {
unode = geometry_push(object);
// return unode;
return;
}
if ((unode = get_node(node, type))) {
// return unode;
return;
@@ -1624,8 +1622,12 @@ Node *push_node(const Object &object, const PBVHNode *node, Type type)
case Type::DyntopoBegin:
case Type::DyntopoEnd:
case Type::DyntopoSymmetrize:
BLI_assert_msg(0, "Dynamic topology should've already been handled");
/* Dyntopo should be handled above. */
BLI_assert_unreachable();
break;
case Type::Geometry:
/* See #geometry_push. */
BLI_assert_unreachable();
break;
case Type::FaceSet:
store_face_sets(*static_cast<const Mesh *>(object.data), *unode);
@@ -1958,18 +1960,18 @@ static void step_free(UndoStep *us_p)
void geometry_begin(Object &ob, const wmOperator *op)
{
push_begin(ob, op);
push_node(ob, nullptr, Type::Geometry);
geometry_push(ob);
}
void geometry_begin_ex(Object &ob, const char *name)
{
push_begin_ex(ob, name);
push_node(ob, nullptr, Type::Geometry);
geometry_push(ob);
}
void geometry_end(Object &ob)
{
push_node(ob, nullptr, Type::Geometry);
geometry_push(ob);
push_end(ob);
}
@@ -2055,7 +2057,7 @@ void push_multires_mesh_begin(bContext *C, const char *str)
push_begin_ex(*object, str);
Node *geometry_unode = push_node(*object, nullptr, Type::Geometry);
Node *geometry_unode = geometry_push(*object);
geometry_unode->geometry_clear_pbvh = false;
push_all_grids(object);
@@ -2070,7 +2072,7 @@ void push_multires_mesh_end(bContext *C, const char *str)
Object *object = CTX_data_active_object(C);
Node *geometry_unode = push_node(*object, nullptr, Type::Geometry);
Node *geometry_unode = geometry_push(*object);
geometry_unode->geometry_clear_pbvh = false;
push_end(*object);