Cleanup: Sculpt: Use references for SculptSession variables

This commit is contained in:
Hans Goudey 2024-06-20 10:23:05 -04:00
parent 2079507ca5
commit 385cc4fb3b
7 changed files with 208 additions and 210 deletions

@ -453,8 +453,8 @@ void multires_force_sculpt_rebuild(Object *object)
return; return;
} }
SculptSession *ss = object->sculpt; SculptSession &ss = *object->sculpt;
bke::pbvh::free(ss->pbvh); bke::pbvh::free(ss.pbvh);
} }
void multires_force_external_reload(Object *object) void multires_force_external_reload(Object *object)

@ -1399,16 +1399,16 @@ void BKE_sculptsession_free_vwpaint_data(SculptSession *ss)
*/ */
static void sculptsession_bm_to_me_update_data_only(Object *ob, bool reorder) static void sculptsession_bm_to_me_update_data_only(Object *ob, bool reorder)
{ {
SculptSession *ss = ob->sculpt; SculptSession &ss = *ob->sculpt;
if (ss->bm) { if (ss.bm) {
if (ob->data) { if (ob->data) {
if (reorder) { if (reorder) {
BM_log_mesh_elems_reorder(ss->bm, ss->bm_log); BM_log_mesh_elems_reorder(ss.bm, ss.bm_log);
} }
BMeshToMeshParams params{}; BMeshToMeshParams params{};
params.calc_object_remap = false; params.calc_object_remap = false;
BM_mesh_bm_to_me(nullptr, ss->bm, static_cast<Mesh *>(ob->data), &params); BM_mesh_bm_to_me(nullptr, ss.bm, static_cast<Mesh *>(ob->data), &params);
} }
} }
} }
@ -1624,13 +1624,13 @@ static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
*/ */
static void sculpt_update_persistent_base(Object *ob) static void sculpt_update_persistent_base(Object *ob)
{ {
SculptSession *ss = ob->sculpt; SculptSession &ss = *ob->sculpt;
ss->attrs.persistent_co = BKE_sculpt_attribute_get( ss.attrs.persistent_co = BKE_sculpt_attribute_get(
ob, AttrDomain::Point, CD_PROP_FLOAT3, SCULPT_ATTRIBUTE_NAME(persistent_co)); ob, AttrDomain::Point, CD_PROP_FLOAT3, SCULPT_ATTRIBUTE_NAME(persistent_co));
ss->attrs.persistent_no = BKE_sculpt_attribute_get( ss.attrs.persistent_no = BKE_sculpt_attribute_get(
ob, AttrDomain::Point, CD_PROP_FLOAT3, SCULPT_ATTRIBUTE_NAME(persistent_no)); ob, AttrDomain::Point, CD_PROP_FLOAT3, SCULPT_ATTRIBUTE_NAME(persistent_no));
ss->attrs.persistent_disp = BKE_sculpt_attribute_get( ss.attrs.persistent_disp = BKE_sculpt_attribute_get(
ob, AttrDomain::Point, CD_PROP_FLOAT, SCULPT_ATTRIBUTE_NAME(persistent_disp)); ob, AttrDomain::Point, CD_PROP_FLOAT, SCULPT_ATTRIBUTE_NAME(persistent_disp));
} }
@ -1641,7 +1641,7 @@ static void sculpt_update_object(Depsgraph *depsgraph,
{ {
Scene *scene = DEG_get_input_scene(depsgraph); Scene *scene = DEG_get_input_scene(depsgraph);
Sculpt *sd = scene->toolsettings->sculpt; Sculpt *sd = scene->toolsettings->sculpt;
SculptSession *ss = ob->sculpt; SculptSession &ss = *ob->sculpt;
Mesh *mesh_orig = BKE_object_get_original_mesh(ob); Mesh *mesh_orig = BKE_object_get_original_mesh(ob);
Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval); Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval);
MultiresModifierData *mmd = sculpt_multires_modifier_get(scene, ob, true); MultiresModifierData *mmd = sculpt_multires_modifier_get(scene, ob, true);
@ -1655,93 +1655,93 @@ static void sculpt_update_object(Depsgraph *depsgraph,
return; return;
} }
ss->depsgraph = depsgraph; ss.depsgraph = depsgraph;
ss->deform_modifiers_active = sculpt_modifiers_active(scene, sd, ob); ss.deform_modifiers_active = sculpt_modifiers_active(scene, sd, ob);
ss->building_vp_handle = false; ss.building_vp_handle = false;
ss->scene = scene; ss.scene = scene;
ss->shapekey_active = (mmd == nullptr) ? BKE_keyblock_from_object(ob) : nullptr; ss.shapekey_active = (mmd == nullptr) ? BKE_keyblock_from_object(ob) : nullptr;
/* NOTE: Weight pPaint require mesh info for loop lookup, but it never uses multires code path, /* NOTE: Weight pPaint require mesh info for loop lookup, but it never uses multires code path,
* so no extra checks is needed here. */ * so no extra checks is needed here. */
if (mmd) { if (mmd) {
ss->multires.active = true; ss.multires.active = true;
ss->multires.modifier = mmd; ss.multires.modifier = mmd;
ss->multires.level = mmd->sculptlvl; ss.multires.level = mmd->sculptlvl;
ss->totvert = mesh_eval->verts_num; ss.totvert = mesh_eval->verts_num;
ss->faces_num = mesh_eval->faces_num; ss.faces_num = mesh_eval->faces_num;
ss->totfaces = mesh_orig->faces_num; ss.totfaces = mesh_orig->faces_num;
/* These are assigned to the base mesh in Multires. This is needed because Face Sets operators /* These are assigned to the base mesh in Multires. This is needed because Face Sets operators
* and tools use the Face Sets data from the base mesh when Multires is active. */ * and tools use the Face Sets data from the base mesh when Multires is active. */
ss->vert_positions = mesh_orig->vert_positions_for_write(); ss.vert_positions = mesh_orig->vert_positions_for_write();
ss->faces = mesh_orig->faces(); ss.faces = mesh_orig->faces();
ss->corner_verts = mesh_orig->corner_verts(); ss.corner_verts = mesh_orig->corner_verts();
} }
else { else {
ss->totvert = mesh_orig->verts_num; ss.totvert = mesh_orig->verts_num;
ss->faces_num = mesh_orig->faces_num; ss.faces_num = mesh_orig->faces_num;
ss->totfaces = mesh_orig->faces_num; ss.totfaces = mesh_orig->faces_num;
ss->vert_positions = mesh_orig->vert_positions_for_write(); ss.vert_positions = mesh_orig->vert_positions_for_write();
ss->faces = mesh_orig->faces(); ss.faces = mesh_orig->faces();
ss->corner_verts = mesh_orig->corner_verts(); ss.corner_verts = mesh_orig->corner_verts();
ss->multires.active = false; ss.multires.active = false;
ss->multires.modifier = nullptr; ss.multires.modifier = nullptr;
ss->multires.level = 0; ss.multires.level = 0;
CustomDataLayer *layer; CustomDataLayer *layer;
AttrDomain domain; AttrDomain domain;
if (BKE_pbvh_get_color_layer(mesh_orig, &layer, &domain)) { if (BKE_pbvh_get_color_layer(mesh_orig, &layer, &domain)) {
if (layer->type == CD_PROP_COLOR) { if (layer->type == CD_PROP_COLOR) {
ss->vcol = static_cast<MPropCol *>(layer->data); ss.vcol = static_cast<MPropCol *>(layer->data);
} }
else { else {
ss->mcol = static_cast<MLoopCol *>(layer->data); ss.mcol = static_cast<MLoopCol *>(layer->data);
} }
ss->vcol_domain = domain; ss.vcol_domain = domain;
ss->vcol_type = static_cast<eCustomDataType>(layer->type); ss.vcol_type = static_cast<eCustomDataType>(layer->type);
} }
else { else {
ss->vcol = nullptr; ss.vcol = nullptr;
ss->mcol = nullptr; ss.mcol = nullptr;
ss->vcol_type = (eCustomDataType)-1; ss.vcol_type = (eCustomDataType)-1;
ss->vcol_domain = AttrDomain::Point; ss.vcol_domain = AttrDomain::Point;
} }
} }
/* Sculpt Face Sets. */ /* Sculpt Face Sets. */
if (use_face_sets) { if (use_face_sets) {
ss->face_sets = static_cast<const int *>( ss.face_sets = static_cast<const int *>(
CustomData_get_layer_named(&mesh_orig->face_data, CD_PROP_INT32, ".sculpt_face_set")); CustomData_get_layer_named(&mesh_orig->face_data, CD_PROP_INT32, ".sculpt_face_set"));
} }
else { else {
ss->face_sets = nullptr; ss.face_sets = nullptr;
} }
ss->hide_poly = (bool *)CustomData_get_layer_named( ss.hide_poly = (bool *)CustomData_get_layer_named(
&mesh_orig->face_data, CD_PROP_BOOL, ".hide_poly"); &mesh_orig->face_data, CD_PROP_BOOL, ".hide_poly");
ss->subdiv_ccg = mesh_eval->runtime->subdiv_ccg.get(); ss.subdiv_ccg = mesh_eval->runtime->subdiv_ccg.get();
PBVH *pbvh = BKE_sculpt_object_pbvh_ensure(depsgraph, ob); PBVH *pbvh = BKE_sculpt_object_pbvh_ensure(depsgraph, ob);
BLI_assert(pbvh == ss->pbvh.get()); BLI_assert(pbvh == ss.pbvh.get());
UNUSED_VARS_NDEBUG(pbvh); UNUSED_VARS_NDEBUG(pbvh);
BKE_pbvh_subdiv_cgg_set(*ss->pbvh, ss->subdiv_ccg); BKE_pbvh_subdiv_cgg_set(*ss.pbvh, ss.subdiv_ccg);
sculpt_attribute_update_refs(ob, BKE_pbvh_type(*ss->pbvh)); sculpt_attribute_update_refs(ob, BKE_pbvh_type(*ss.pbvh));
sculpt_update_persistent_base(ob); sculpt_update_persistent_base(ob);
if (ob->type == OB_MESH) { if (ob->type == OB_MESH) {
ss->vert_to_face_map = mesh_orig->vert_to_face_map(); ss.vert_to_face_map = mesh_orig->vert_to_face_map();
} }
if (ss->deform_modifiers_active) { if (ss.deform_modifiers_active) {
/* Painting doesn't need crazyspace, use already evaluated mesh coordinates if possible. */ /* Painting doesn't need crazyspace, use already evaluated mesh coordinates if possible. */
bool used_me_eval = false; bool used_me_eval = false;
@ -1755,67 +1755,67 @@ static void sculpt_update_object(Depsgraph *depsgraph,
me_eval_deform->corners_num == mesh_eval->corners_num && me_eval_deform->corners_num == mesh_eval->corners_num &&
me_eval_deform->verts_num == mesh_eval->verts_num) me_eval_deform->verts_num == mesh_eval->verts_num)
{ {
BKE_sculptsession_free_deformMats(ss); BKE_sculptsession_free_deformMats(&ss);
BLI_assert(me_eval_deform->verts_num == mesh_orig->verts_num); BLI_assert(me_eval_deform->verts_num == mesh_orig->verts_num);
ss->deform_cos = mesh_eval->vert_positions(); ss.deform_cos = mesh_eval->vert_positions();
BKE_pbvh_vert_coords_apply(*ss->pbvh, ss->deform_cos); BKE_pbvh_vert_coords_apply(*ss.pbvh, ss.deform_cos);
used_me_eval = true; used_me_eval = true;
} }
} }
if (ss->orig_cos.is_empty() && !used_me_eval) { if (ss.orig_cos.is_empty() && !used_me_eval) {
BKE_sculptsession_free_deformMats(ss); BKE_sculptsession_free_deformMats(&ss);
ss->orig_cos = (ss->shapekey_active) ? ss.orig_cos = (ss.shapekey_active) ?
Span(static_cast<const float3 *>(ss->shapekey_active->data), Span(static_cast<const float3 *>(ss.shapekey_active->data),
mesh_orig->verts_num) : mesh_orig->verts_num) :
mesh_orig->vert_positions(); mesh_orig->vert_positions();
BKE_crazyspace_build_sculpt(depsgraph, scene, ob, ss->deform_imats, ss->deform_cos); BKE_crazyspace_build_sculpt(depsgraph, scene, ob, ss.deform_imats, ss.deform_cos);
BKE_pbvh_vert_coords_apply(*ss->pbvh, ss->deform_cos); BKE_pbvh_vert_coords_apply(*ss.pbvh, ss.deform_cos);
for (blender::float3x3 &matrix : ss->deform_imats) { for (blender::float3x3 &matrix : ss.deform_imats) {
matrix = blender::math::invert(matrix); matrix = blender::math::invert(matrix);
} }
} }
} }
else { else {
BKE_sculptsession_free_deformMats(ss); BKE_sculptsession_free_deformMats(&ss);
} }
if (ss->shapekey_active != nullptr && ss->deform_cos.is_empty()) { if (ss.shapekey_active != nullptr && ss.deform_cos.is_empty()) {
ss->deform_cos = Span(static_cast<const float3 *>(ss->shapekey_active->data), ss.deform_cos = Span(static_cast<const float3 *>(ss.shapekey_active->data),
mesh_orig->verts_num); mesh_orig->verts_num);
} }
/* if pbvh is deformed, key block is already applied to it */ /* if pbvh is deformed, key block is already applied to it */
if (ss->shapekey_active) { if (ss.shapekey_active) {
bool pbvh_deformed = BKE_pbvh_is_deformed(*ss->pbvh); bool pbvh_deformed = BKE_pbvh_is_deformed(*ss.pbvh);
if (!pbvh_deformed || ss->deform_cos.is_empty()) { if (!pbvh_deformed || ss.deform_cos.is_empty()) {
const Span key_data(static_cast<const float3 *>(ss->shapekey_active->data), const Span key_data(static_cast<const float3 *>(ss.shapekey_active->data),
mesh_orig->verts_num); mesh_orig->verts_num);
if (key_data.data() != nullptr) { if (key_data.data() != nullptr) {
if (!pbvh_deformed) { if (!pbvh_deformed) {
/* apply shape keys coordinates to PBVH */ /* apply shape keys coordinates to PBVH */
BKE_pbvh_vert_coords_apply(*ss->pbvh, key_data); BKE_pbvh_vert_coords_apply(*ss.pbvh, key_data);
} }
if (ss->deform_cos.is_empty()) { if (ss.deform_cos.is_empty()) {
ss->deform_cos = key_data; ss.deform_cos = key_data;
} }
} }
} }
} }
if (is_paint_tool) { if (is_paint_tool) {
if (ss->vcol_domain == AttrDomain::Corner) { if (ss.vcol_domain == AttrDomain::Corner) {
/* Ensure pbvh nodes have loop indices; the sculpt undo system /* Ensure pbvh nodes have loop indices; the sculpt undo system
* needs them for color attributes. * needs them for color attributes.
*/ */
BKE_pbvh_ensure_node_loops(*ss->pbvh); BKE_pbvh_ensure_node_loops(*ss.pbvh);
} }
/* /*
@ -1824,14 +1824,14 @@ static void sculpt_update_object(Depsgraph *depsgraph,
* The relevant changes are stored/encoded in the paint canvas key. * The relevant changes are stored/encoded in the paint canvas key.
* These include the active uv map, and resolutions. * These include the active uv map, and resolutions.
*/ */
if (U.experimental.use_sculpt_texture_paint && ss->pbvh) { if (U.experimental.use_sculpt_texture_paint && ss.pbvh) {
char *paint_canvas_key = BKE_paint_canvas_key_get(&scene->toolsettings->paint_mode, ob); char *paint_canvas_key = BKE_paint_canvas_key_get(&scene->toolsettings->paint_mode, ob);
if (ss->last_paint_canvas_key == nullptr || if (ss.last_paint_canvas_key == nullptr ||
!STREQ(paint_canvas_key, ss->last_paint_canvas_key)) !STREQ(paint_canvas_key, ss.last_paint_canvas_key))
{ {
MEM_SAFE_FREE(ss->last_paint_canvas_key); MEM_SAFE_FREE(ss.last_paint_canvas_key);
ss->last_paint_canvas_key = paint_canvas_key; ss.last_paint_canvas_key = paint_canvas_key;
BKE_pbvh_mark_rebuild_pixels(*ss->pbvh); BKE_pbvh_mark_rebuild_pixels(*ss.pbvh);
} }
else { else {
MEM_freeN(paint_canvas_key); MEM_freeN(paint_canvas_key);
@ -2257,14 +2257,14 @@ int BKE_sculptsession_vertex_count(const SculptSession *ss)
*/ */
static CustomData *sculpt_get_cdata(Object *ob, AttrDomain domain) static CustomData *sculpt_get_cdata(Object *ob, AttrDomain domain)
{ {
SculptSession *ss = ob->sculpt; SculptSession &ss = *ob->sculpt;
if (ss->bm) { if (ss.bm) {
switch (domain) { switch (domain) {
case AttrDomain::Point: case AttrDomain::Point:
return &ss->bm->vdata; return &ss.bm->vdata;
case AttrDomain::Face: case AttrDomain::Face:
return &ss->bm->pdata; return &ss.bm->pdata;
default: default:
BLI_assert_unreachable(); BLI_assert_unreachable();
return nullptr; return nullptr;
@ -2276,7 +2276,7 @@ static CustomData *sculpt_get_cdata(Object *ob, AttrDomain domain)
switch (domain) { switch (domain) {
case AttrDomain::Point: case AttrDomain::Point:
/* Cannot get vertex domain for multires grids. */ /* Cannot get vertex domain for multires grids. */
if (ss->pbvh && BKE_pbvh_type(*ss->pbvh) == PBVH_GRIDS) { if (ss.pbvh && BKE_pbvh_type(*ss.pbvh) == PBVH_GRIDS) {
return nullptr; return nullptr;
} }
@ -2292,14 +2292,14 @@ static CustomData *sculpt_get_cdata(Object *ob, AttrDomain domain)
static int sculpt_attr_elem_count_get(Object *ob, AttrDomain domain) static int sculpt_attr_elem_count_get(Object *ob, AttrDomain domain)
{ {
SculptSession *ss = ob->sculpt; const SculptSession &ss = *ob->sculpt;
switch (domain) { switch (domain) {
case AttrDomain::Point: case AttrDomain::Point:
return BKE_sculptsession_vertex_count(ss); return BKE_sculptsession_vertex_count(&ss);
break; break;
case AttrDomain::Face: case AttrDomain::Face:
return ss->totfaces; return ss.totfaces;
break; break;
default: default:
BLI_assert_unreachable(); BLI_assert_unreachable();

@ -73,7 +73,7 @@ void triangulate(BMesh *bm)
void enable_ex(Main &bmain, Depsgraph &depsgraph, Object &ob) void enable_ex(Main &bmain, Depsgraph &depsgraph, Object &ob)
{ {
SculptSession *ss = ob.sculpt; SculptSession &ss = *ob.sculpt;
Mesh *mesh = static_cast<Mesh *>(ob.data); Mesh *mesh = static_cast<Mesh *>(ob.data);
const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh); const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
@ -85,28 +85,28 @@ void enable_ex(Main &bmain, Depsgraph &depsgraph, Object &ob)
/* Create triangles-only BMesh. */ /* Create triangles-only BMesh. */
BMeshCreateParams create_params{}; BMeshCreateParams create_params{};
create_params.use_toolflags = false; create_params.use_toolflags = false;
ss->bm = BM_mesh_create(&allocsize, &create_params); ss.bm = BM_mesh_create(&allocsize, &create_params);
BMeshFromMeshParams convert_params{}; BMeshFromMeshParams convert_params{};
convert_params.calc_face_normal = true; convert_params.calc_face_normal = true;
convert_params.calc_vert_normal = true; convert_params.calc_vert_normal = true;
convert_params.use_shapekey = true; convert_params.use_shapekey = true;
convert_params.active_shapekey = ob.shapenr; convert_params.active_shapekey = ob.shapenr;
BM_mesh_bm_from_me(ss->bm, mesh, &convert_params); BM_mesh_bm_from_me(ss.bm, mesh, &convert_params);
triangulate(ss->bm); triangulate(ss.bm);
BM_data_layer_ensure_named(ss->bm, &ss->bm->vdata, CD_PROP_FLOAT, ".sculpt_mask"); BM_data_layer_ensure_named(ss.bm, &ss.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
/* Make sure the data for existing faces are initialized. */ /* Make sure the data for existing faces are initialized. */
if (mesh->faces_num != ss->bm->totface) { if (mesh->faces_num != ss.bm->totface) {
BM_mesh_normals_update(ss->bm); BM_mesh_normals_update(ss.bm);
} }
/* Enable dynamic topology. */ /* Enable dynamic topology. */
mesh->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY; mesh->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
/* Enable logging for undo/redo. */ /* Enable logging for undo/redo. */
ss->bm_log = BM_log_create(ss->bm); ss.bm_log = BM_log_create(ss.bm);
/* Update dependency graph, so modifiers that depend on dyntopo being enabled /* Update dependency graph, so modifiers that depend on dyntopo being enabled
* are re-evaluated and the PBVH is re-created. */ * are re-evaluated and the PBVH is re-created. */

@ -321,7 +321,7 @@ static void flip_for_symmetry_pass(GestureData &gesture_data, const ePaintSymmet
static Vector<PBVHNode *> update_affected_nodes_by_line_plane(GestureData &gesture_data) static Vector<PBVHNode *> update_affected_nodes_by_line_plane(GestureData &gesture_data)
{ {
SculptSession *ss = gesture_data.ss; SculptSession &ss = *gesture_data.ss;
float clip_planes[3][4]; float clip_planes[3][4];
copy_v4_v4(clip_planes[0], gesture_data.line.plane); copy_v4_v4(clip_planes[0], gesture_data.line.plane);
copy_v4_v4(clip_planes[1], gesture_data.line.side_plane[0]); copy_v4_v4(clip_planes[1], gesture_data.line.side_plane[0]);
@ -331,14 +331,14 @@ static Vector<PBVHNode *> update_affected_nodes_by_line_plane(GestureData &gestu
frustum.planes = clip_planes; frustum.planes = clip_planes;
frustum.num_planes = gesture_data.line.use_side_planes ? 3 : 1; frustum.num_planes = gesture_data.line.use_side_planes ? 3 : 1;
return gesture_data.nodes = bke::pbvh::search_gather(*ss->pbvh, [&](PBVHNode &node) { return gesture_data.nodes = bke::pbvh::search_gather(*ss.pbvh, [&](PBVHNode &node) {
return BKE_pbvh_node_frustum_contain_AABB(&node, &frustum); return BKE_pbvh_node_frustum_contain_AABB(&node, &frustum);
}); });
} }
static void update_affected_nodes_by_clip_planes(GestureData &gesture_data) static void update_affected_nodes_by_clip_planes(GestureData &gesture_data)
{ {
SculptSession *ss = gesture_data.ss; SculptSession &ss = *gesture_data.ss;
float clip_planes[4][4]; float clip_planes[4][4];
copy_m4_m4(clip_planes, gesture_data.clip_planes); copy_m4_m4(clip_planes, gesture_data.clip_planes);
negate_m4(clip_planes); negate_m4(clip_planes);
@ -347,7 +347,7 @@ static void update_affected_nodes_by_clip_planes(GestureData &gesture_data)
frustum.planes = clip_planes; frustum.planes = clip_planes;
frustum.num_planes = 4; frustum.num_planes = 4;
gesture_data.nodes = bke::pbvh::search_gather(*ss->pbvh, [&](PBVHNode &node) { gesture_data.nodes = bke::pbvh::search_gather(*ss.pbvh, [&](PBVHNode &node) {
switch (gesture_data.selection_type) { switch (gesture_data.selection_type) {
case SelectionType::Inside: case SelectionType::Inside:
return BKE_pbvh_node_frustum_contain_AABB(&node, &frustum); return BKE_pbvh_node_frustum_contain_AABB(&node, &frustum);

@ -85,9 +85,9 @@ 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)
{ {
SculptSession *ss = gesture_data.ss; SculptSession &ss = *gesture_data.ss;
const Sculpt &sd = *CTX_data_tool_settings(&C)->sculpt; const Sculpt &sd = *CTX_data_tool_settings(&C)->sculpt;
if (ss->deform_modifiers_active || ss->shapekey_active) { if (ss.deform_modifiers_active || ss.shapekey_active) {
SCULPT_flush_stroke_deform(sd, *gesture_data.vc.obact, true); SCULPT_flush_stroke_deform(sd, *gesture_data.vc.obact, true);
} }

@ -438,10 +438,10 @@ static bool test_swap_v3_v3(float3 &a, float3 &b)
} }
static bool restore_deformed( static bool restore_deformed(
const SculptSession *ss, Node &unode, int uindex, int oindex, float3 &coord) const SculptSession &ss, Node &unode, int uindex, int oindex, float3 &coord)
{ {
if (test_swap_v3_v3(coord, unode.orig_position[uindex])) { if (test_swap_v3_v3(coord, unode.orig_position[uindex])) {
copy_v3_v3(unode.position[uindex], ss->deform_cos[oindex]); copy_v3_v3(unode.position[uindex], ss.deform_cos[oindex]);
return true; return true;
} }
return false; return false;
@ -454,13 +454,13 @@ static bool restore_coords(bContext *C,
Node &unode, Node &unode,
MutableSpan<bool> modified_verts) MutableSpan<bool> modified_verts)
{ {
SculptSession *ss = object.sculpt; SculptSession &ss = *object.sculpt;
SubdivCCG *subdiv_ccg = ss->subdiv_ccg; SubdivCCG *subdiv_ccg = ss.subdiv_ccg;
if (unode.mesh_verts_num) { if (unode.mesh_verts_num) {
/* Regular mesh restore. */ /* Regular mesh restore. */
if (ss->shapekey_active && ss->shapekey_active->name != step_data.active_shape_key_name) { if (ss.shapekey_active && ss.shapekey_active->name != step_data.active_shape_key_name) {
/* Shape key has been changed before calling undo operator. */ /* Shape key has been changed before calling undo operator. */
Key *key = BKE_key_from_object(&object); Key *key = BKE_key_from_object(&object);
@ -481,14 +481,14 @@ static bool restore_coords(bContext *C,
/* No need for float comparison here (memory is exactly equal or not). */ /* No need for float comparison here (memory is exactly equal or not). */
const Span<int> index = unode.vert_indices.as_span().take_front(unode.unique_verts_num); const Span<int> index = unode.vert_indices.as_span().take_front(unode.unique_verts_num);
MutableSpan<float3> positions = ss->vert_positions; MutableSpan<float3> positions = ss.vert_positions;
if (ss->shapekey_active) { if (ss.shapekey_active) {
float(*vertCos)[3] = BKE_keyblock_convert_to_vertcos(&object, ss->shapekey_active); float(*vertCos)[3] = BKE_keyblock_convert_to_vertcos(&object, ss.shapekey_active);
MutableSpan key_positions(reinterpret_cast<float3 *>(vertCos), ss->shapekey_active->totelem); MutableSpan key_positions(reinterpret_cast<float3 *>(vertCos), ss.shapekey_active->totelem);
if (!unode.orig_position.is_empty()) { if (!unode.orig_position.is_empty()) {
if (ss->deform_modifiers_active) { if (ss.deform_modifiers_active) {
for (const int i : index.index_range()) { for (const int i : index.index_range()) {
restore_deformed(ss, unode, i, index[i], key_positions[index[i]]); restore_deformed(ss, unode, i, index[i], key_positions[index[i]]);
} }
@ -506,17 +506,17 @@ static bool restore_coords(bContext *C,
} }
/* Propagate new coords to keyblock. */ /* Propagate new coords to keyblock. */
SCULPT_vertcos_to_key(object, ss->shapekey_active, key_positions); SCULPT_vertcos_to_key(object, ss.shapekey_active, key_positions);
/* PBVH uses its own vertex array, so coords should be */ /* PBVH uses its own vertex array, so coords should be */
/* propagated to PBVH here. */ /* propagated to PBVH here. */
BKE_pbvh_vert_coords_apply(*ss->pbvh, key_positions); BKE_pbvh_vert_coords_apply(*ss.pbvh, key_positions);
MEM_freeN(vertCos); MEM_freeN(vertCos);
} }
else { else {
if (!unode.orig_position.is_empty()) { if (!unode.orig_position.is_empty()) {
if (ss->deform_modifiers_active) { if (ss.deform_modifiers_active) {
for (const int i : index.index_range()) { for (const int i : index.index_range()) {
restore_deformed(ss, unode, i, index[i], positions[index[i]]); restore_deformed(ss, unode, i, index[i], positions[index[i]]);
modified_verts[index[i]] = true; modified_verts[index[i]] = true;
@ -559,8 +559,8 @@ static bool restore_coords(bContext *C,
static bool restore_hidden(Object &object, Node &unode, MutableSpan<bool> modified_vertices) static bool restore_hidden(Object &object, Node &unode, MutableSpan<bool> modified_vertices)
{ {
SculptSession *ss = object.sculpt; SculptSession &ss = *object.sculpt;
SubdivCCG *subdiv_ccg = ss->subdiv_ccg; SubdivCCG *subdiv_ccg = ss.subdiv_ccg;
if (unode.mesh_verts_num) { if (unode.mesh_verts_num) {
Mesh &mesh = *static_cast<Mesh *>(object.data); Mesh &mesh = *static_cast<Mesh *>(object.data);
@ -628,7 +628,7 @@ static bool restore_hidden_face(Object &object, Node &unode, MutableSpan<bool> m
static bool restore_color(Object &object, Node &unode, MutableSpan<bool> modified_vertices) static bool restore_color(Object &object, Node &unode, MutableSpan<bool> modified_vertices)
{ {
const Mesh &mesh = *static_cast<const Mesh *>(object.data); const Mesh &mesh = *static_cast<const Mesh *>(object.data);
SculptSession *ss = object.sculpt; SculptSession &ss = *object.sculpt;
bool modified = false; bool modified = false;
@ -636,12 +636,12 @@ static bool restore_color(Object &object, Node &unode, MutableSpan<bool> modifie
* vertex colors for original data lookup. */ * vertex colors for original data lookup. */
if (!unode.col.is_empty() && unode.loop_col.is_empty()) { if (!unode.col.is_empty() && unode.loop_col.is_empty()) {
BKE_pbvh_swap_colors( BKE_pbvh_swap_colors(
*ss->pbvh, unode.vert_indices.as_span().take_front(unode.unique_verts_num), unode.col); *ss.pbvh, unode.vert_indices.as_span().take_front(unode.unique_verts_num), unode.col);
modified = true; modified = true;
} }
if (!unode.loop_col.is_empty() && unode.mesh_corners_num == mesh.corners_num) { if (!unode.loop_col.is_empty() && unode.mesh_corners_num == mesh.corners_num) {
BKE_pbvh_swap_colors(*ss->pbvh, unode.corner_indices, unode.loop_col); BKE_pbvh_swap_colors(*ss.pbvh, unode.corner_indices, unode.loop_col);
modified = true; modified = true;
} }
@ -655,8 +655,8 @@ static bool restore_color(Object &object, Node &unode, MutableSpan<bool> modifie
static bool restore_mask(Object &object, Node &unode, MutableSpan<bool> modified_vertices) static bool restore_mask(Object &object, Node &unode, MutableSpan<bool> modified_vertices)
{ {
Mesh *mesh = BKE_object_get_original_mesh(&object); Mesh *mesh = BKE_object_get_original_mesh(&object);
SculptSession *ss = object.sculpt; SculptSession &ss = *object.sculpt;
SubdivCCG *subdiv_ccg = ss->subdiv_ccg; SubdivCCG *subdiv_ccg = ss.subdiv_ccg;
if (unode.mesh_verts_num) { if (unode.mesh_verts_num) {
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write(); bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
@ -715,19 +715,19 @@ static bool restore_face_sets(Object &object,
return modified; return modified;
} }
static void bmesh_restore_generic(Node &unode, Object &object, SculptSession *ss) static void bmesh_restore_generic(Node &unode, Object &object, SculptSession &ss)
{ {
if (unode.applied) { if (unode.applied) {
BM_log_undo(ss->bm, ss->bm_log); BM_log_undo(ss.bm, ss.bm_log);
unode.applied = false; unode.applied = false;
} }
else { else {
BM_log_redo(ss->bm, ss->bm_log); BM_log_redo(ss.bm, ss.bm_log);
unode.applied = true; unode.applied = true;
} }
if (unode.type == Type::Mask) { if (unode.type == Type::Mask) {
Vector<PBVHNode *> nodes = bke::pbvh::search_gather(*ss->pbvh, {}); Vector<PBVHNode *> nodes = bke::pbvh::search_gather(*ss.pbvh, {});
for (PBVHNode *node : nodes) { for (PBVHNode *node : nodes) {
BKE_pbvh_node_mark_redraw(node); BKE_pbvh_node_mark_redraw(node);
} }
@ -740,7 +740,7 @@ static void bmesh_restore_generic(Node &unode, Object &object, SculptSession *ss
/* Create empty sculpt BMesh and enable logging. */ /* Create empty sculpt BMesh and enable logging. */
static void bmesh_enable(Object &object, Node &unode) static void bmesh_enable(Object &object, Node &unode)
{ {
SculptSession *ss = object.sculpt; SculptSession &ss = *object.sculpt;
Mesh *mesh = static_cast<Mesh *>(object.data); Mesh *mesh = static_cast<Mesh *>(object.data);
SCULPT_pbvh_clear(object); SCULPT_pbvh_clear(object);
@ -749,16 +749,16 @@ static void bmesh_enable(Object &object, Node &unode)
BMeshCreateParams bmesh_create_params{}; BMeshCreateParams bmesh_create_params{};
bmesh_create_params.use_toolflags = false; bmesh_create_params.use_toolflags = false;
ss->bm = BM_mesh_create(&bm_mesh_allocsize_default, &bmesh_create_params); ss.bm = BM_mesh_create(&bm_mesh_allocsize_default, &bmesh_create_params);
BM_data_layer_add_named(ss->bm, &ss->bm->vdata, CD_PROP_FLOAT, ".sculpt_mask"); BM_data_layer_add_named(ss.bm, &ss.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
mesh->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY; mesh->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
/* Restore the BMLog using saved entries. */ /* Restore the BMLog using saved entries. */
ss->bm_log = BM_log_from_existing_entries_create(ss->bm, unode.bm_entry); ss.bm_log = BM_log_from_existing_entries_create(ss.bm, unode.bm_entry);
} }
static void bmesh_restore_begin(bContext *C, Node &unode, Object &object, SculptSession *ss) static void bmesh_restore_begin(bContext *C, Node &unode, Object &object, SculptSession &ss)
{ {
if (unode.applied) { if (unode.applied) {
dyntopo::disable(C, &unode); dyntopo::disable(C, &unode);
@ -768,19 +768,19 @@ static void bmesh_restore_begin(bContext *C, Node &unode, Object &object, Sculpt
bmesh_enable(object, unode); bmesh_enable(object, unode);
/* Restore the mesh from the first log entry. */ /* Restore the mesh from the first log entry. */
BM_log_redo(ss->bm, ss->bm_log); BM_log_redo(ss.bm, ss.bm_log);
unode.applied = true; unode.applied = true;
} }
} }
static void bmesh_restore_end(bContext *C, Node &unode, Object &object, SculptSession *ss) static void bmesh_restore_end(bContext *C, Node &unode, Object &object, SculptSession &ss)
{ {
if (unode.applied) { if (unode.applied) {
bmesh_enable(object, unode); bmesh_enable(object, unode);
/* Restore the mesh from the last log entry. */ /* Restore the mesh from the last log entry. */
BM_log_undo(ss->bm, ss->bm_log); BM_log_undo(ss.bm, ss.bm_log);
unode.applied = false; unode.applied = false;
} }
@ -869,7 +869,7 @@ static void restore_geometry(Node &unode, Object &object)
* *
* Returns true if this was a dynamic-topology undo step, otherwise * Returns true if this was a dynamic-topology undo step, otherwise
* returns false to indicate the non-dyntopo code should run. */ * returns false to indicate the non-dyntopo code should run. */
static int bmesh_restore(bContext *C, Node &unode, Object &object, SculptSession *ss) static int bmesh_restore(bContext *C, Node &unode, Object &object, SculptSession &ss)
{ {
switch (unode.type) { switch (unode.type) {
case Type::DyntopoBegin: case Type::DyntopoBegin:
@ -880,7 +880,7 @@ static int bmesh_restore(bContext *C, Node &unode, Object &object, SculptSession
bmesh_restore_end(C, unode, object, ss); bmesh_restore_end(C, unode, object, ss);
return true; return true;
default: default:
if (ss->bm_log) { if (ss.bm_log) {
bmesh_restore_generic(unode, object, ss); bmesh_restore_generic(unode, object, ss);
return true; return true;
} }
@ -904,12 +904,12 @@ static int bmesh_restore(bContext *C, Node &unode, Object &object, SculptSession
* Note that the dependency graph is ensured to be evaluated prior to the undo step is decoded, * Note that the dependency graph is ensured to be evaluated prior to the undo step is decoded,
* so if the object's modifier stack references other object it is all fine. */ * so if the object's modifier stack references other object it is all fine. */
static void refine_subdiv(Depsgraph *depsgraph, static void refine_subdiv(Depsgraph *depsgraph,
SculptSession *ss, SculptSession &ss,
Object &object, Object &object,
bke::subdiv::Subdiv *subdiv) bke::subdiv::Subdiv *subdiv)
{ {
Array<float3> deformed_verts = BKE_multires_create_deformed_base_mesh_vert_coords( Array<float3> deformed_verts = BKE_multires_create_deformed_base_mesh_vert_coords(
depsgraph, &object, ss->multires.modifier); depsgraph, &object, ss.multires.modifier);
bke::subdiv::eval_refine_from_mesh(subdiv, bke::subdiv::eval_refine_from_mesh(subdiv,
static_cast<const Mesh *>(object.data), static_cast<const Mesh *>(object.data),
@ -927,12 +927,12 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
return; return;
} }
Mesh &mesh = *static_cast<Mesh *>(object.data); Mesh &mesh = *static_cast<Mesh *>(object.data);
SculptSession *ss = object.sculpt; SculptSession &ss = *object.sculpt;
SubdivCCG *subdiv_ccg = ss->subdiv_ccg; SubdivCCG *subdiv_ccg = ss.subdiv_ccg;
/* Restore pivot. */ /* Restore pivot. */
ss->pivot_pos = step_data.pivot_pos; ss.pivot_pos = step_data.pivot_pos;
ss->pivot_rot = step_data.pivot_rot; ss.pivot_rot = step_data.pivot_rot;
bool clear_automask_cache = false; bool clear_automask_cache = false;
for (const std::unique_ptr<Node> &unode : step_data.nodes) { for (const std::unique_ptr<Node> &unode : step_data.nodes) {
@ -942,7 +942,7 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
} }
if (clear_automask_cache) { if (clear_automask_cache) {
ss->last_automasking_settings_hash = 0; ss.last_automasking_settings_hash = 0;
} }
if (!step_data.nodes.is_empty()) { if (!step_data.nodes.is_empty()) {
@ -982,7 +982,7 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
for (std::unique_ptr<Node> &unode : step_data.nodes) { for (std::unique_ptr<Node> &unode : step_data.nodes) {
/* Check if undo data matches current data well enough to continue. */ /* Check if undo data matches current data well enough to continue. */
if (unode->mesh_verts_num) { if (unode->mesh_verts_num) {
if (ss->totvert != unode->mesh_verts_num) { if (ss.totvert != unode->mesh_verts_num) {
continue; continue;
} }
} }
@ -998,37 +998,37 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
switch (unode->type) { switch (unode->type) {
case Type::Position: case Type::Position:
modified_verts_position.resize(ss->totvert, false); modified_verts_position.resize(ss.totvert, false);
if (restore_coords(C, object, depsgraph, step_data, *unode, modified_verts_position)) { if (restore_coords(C, object, depsgraph, step_data, *unode, modified_verts_position)) {
changed_position = true; changed_position = true;
} }
break; break;
case Type::HideVert: case Type::HideVert:
modified_verts_hide.resize(ss->totvert, false); modified_verts_hide.resize(ss.totvert, false);
if (restore_hidden(object, *unode, modified_verts_hide)) { if (restore_hidden(object, *unode, modified_verts_hide)) {
changed_hide_vert = true; changed_hide_vert = true;
} }
break; break;
case Type::HideFace: case Type::HideFace:
modified_faces_hide.resize(ss->totfaces, false); modified_faces_hide.resize(ss.totfaces, false);
if (restore_hidden_face(object, *unode, modified_faces_hide)) { if (restore_hidden_face(object, *unode, modified_faces_hide)) {
changed_hide_face = true; changed_hide_face = true;
} }
break; break;
case Type::Mask: case Type::Mask:
modified_verts_mask.resize(ss->totvert, false); modified_verts_mask.resize(ss.totvert, false);
if (restore_mask(object, *unode, modified_verts_mask)) { if (restore_mask(object, *unode, modified_verts_mask)) {
changed_mask = true; changed_mask = true;
} }
break; break;
case Type::FaceSet: case Type::FaceSet:
modified_faces_face_set.resize(ss->totfaces, false); modified_faces_face_set.resize(ss.totfaces, false);
if (restore_face_sets(object, *unode, modified_faces_face_set)) { if (restore_face_sets(object, *unode, modified_faces_face_set)) {
changed_face_sets = true; changed_face_sets = true;
} }
break; break;
case Type::Color: case Type::Color:
modified_verts_color.resize(ss->totvert, false); modified_verts_color.resize(ss.totvert, false);
if (restore_color(object, *unode, modified_verts_color)) { if (restore_color(object, *unode, modified_verts_color)) {
changed_color = true; changed_color = true;
} }
@ -1073,7 +1073,7 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
data.changed_position = changed_position; data.changed_position = changed_position;
data.changed_hide_vert = changed_hide_vert; data.changed_hide_vert = changed_hide_vert;
data.changed_mask = changed_mask; data.changed_mask = changed_mask;
data.pbvh = ss->pbvh.get(); data.pbvh = ss.pbvh.get();
data.modified_grids = modified_grids; data.modified_grids = modified_grids;
data.modified_position_verts = modified_verts_position; data.modified_position_verts = modified_verts_position;
data.modified_hidden_verts = modified_verts_hide; data.modified_hidden_verts = modified_verts_hide;
@ -1083,30 +1083,30 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
data.modified_face_set_faces = modified_faces_face_set; data.modified_face_set_faces = modified_faces_face_set;
if (use_multires_undo) { if (use_multires_undo) {
bke::pbvh::search_callback( bke::pbvh::search_callback(
*ss->pbvh, {}, [&](PBVHNode &node) { update_modified_node_grids(node, data); }); *ss.pbvh, {}, [&](PBVHNode &node) { update_modified_node_grids(node, data); });
} }
else { else {
bke::pbvh::search_callback( bke::pbvh::search_callback(
*ss->pbvh, {}, [&](PBVHNode &node) { update_modified_node_mesh(mesh, node, data); }); *ss.pbvh, {}, [&](PBVHNode &node) { update_modified_node_mesh(mesh, node, data); });
} }
if (changed_position) { if (changed_position) {
bke::pbvh::update_bounds(*ss->pbvh); bke::pbvh::update_bounds(*ss.pbvh);
bke::pbvh::store_bounds_orig(*ss->pbvh); bke::pbvh::store_bounds_orig(*ss.pbvh);
} }
if (changed_mask) { if (changed_mask) {
bke::pbvh::update_mask(*ss->pbvh); bke::pbvh::update_mask(*ss.pbvh);
} }
if (changed_hide_face) { if (changed_hide_face) {
hide::sync_all_from_faces(object); hide::sync_all_from_faces(object);
bke::pbvh::update_visibility(*ss->pbvh); bke::pbvh::update_visibility(*ss.pbvh);
} }
if (changed_hide_vert) { if (changed_hide_vert) {
if (ELEM(BKE_pbvh_type(*ss->pbvh), PBVH_FACES, PBVH_GRIDS)) { if (ELEM(BKE_pbvh_type(*ss.pbvh), PBVH_FACES, PBVH_GRIDS)) {
Mesh &mesh = *static_cast<Mesh *>(object.data); Mesh &mesh = *static_cast<Mesh *>(object.data);
BKE_pbvh_sync_visibility_from_verts(*ss->pbvh, &mesh); BKE_pbvh_sync_visibility_from_verts(*ss.pbvh, &mesh);
} }
bke::pbvh::update_visibility(*ss->pbvh); bke::pbvh::update_visibility(*ss.pbvh);
} }
if (BKE_sculpt_multires_active(scene, &object)) { if (BKE_sculpt_multires_active(scene, &object)) {
@ -1119,14 +1119,14 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
} }
const bool tag_update = ID_REAL_USERS(object.data) > 1 || const bool tag_update = ID_REAL_USERS(object.data) > 1 ||
!BKE_sculptsession_use_pbvh_draw(&object, rv3d) || ss->shapekey_active || !BKE_sculptsession_use_pbvh_draw(&object, rv3d) || ss.shapekey_active ||
ss->deform_modifiers_active; ss.deform_modifiers_active;
if (tag_update) { if (tag_update) {
Mesh *mesh = static_cast<Mesh *>(object.data); Mesh *mesh = static_cast<Mesh *>(object.data);
if (changed_position) { if (changed_position) {
mesh->tag_positions_changed(); mesh->tag_positions_changed();
BKE_sculptsession_free_deformMats(ss); BKE_sculptsession_free_deformMats(&ss);
} }
DEG_id_tag_update(&object.id, ID_RECALC_GEOMETRY); DEG_id_tag_update(&object.id, ID_RECALC_GEOMETRY);
} }
@ -1155,12 +1155,12 @@ Node *get_node(const PBVHNode *node, const Type type)
return step_data->undo_nodes_by_pbvh_node.lookup_default({node, type}, nullptr); return step_data->undo_nodes_by_pbvh_node.lookup_default({node, type}, nullptr);
} }
static size_t alloc_and_store_hidden(const SculptSession *ss, const PBVHNode &node, Node *unode) static size_t alloc_and_store_hidden(const SculptSession &ss, const PBVHNode &node, Node *unode)
{ {
if (!ss->subdiv_ccg) { if (!ss.subdiv_ccg) {
return 0; return 0;
} }
const BitGroupVector<> grid_hidden = ss->subdiv_ccg->grid_hidden; const BitGroupVector<> grid_hidden = ss.subdiv_ccg->grid_hidden;
if (grid_hidden.is_empty()) { if (grid_hidden.is_empty()) {
return 0; return 0;
} }
@ -1208,7 +1208,7 @@ static Node *find_or_alloc_node_type(const Type type)
static Node *alloc_node(const Object &object, const PBVHNode *node, const Type type) static Node *alloc_node(const Object &object, const PBVHNode *node, const Type type)
{ {
StepData *step_data = get_step_data(); StepData *step_data = get_step_data();
const SculptSession *ss = object.sculpt; const SculptSession &ss = *object.sculpt;
Node *unode = alloc_node_type(type); Node *unode = alloc_node_type(type);
step_data->undo_nodes_by_pbvh_node.add({node, type}, unode); step_data->undo_nodes_by_pbvh_node.add({node, type}, unode);
@ -1216,9 +1216,9 @@ static Node *alloc_node(const Object &object, const PBVHNode *node, const Type t
const Mesh &mesh = *static_cast<Mesh *>(object.data); const Mesh &mesh = *static_cast<Mesh *>(object.data);
int verts_num; int verts_num;
if (BKE_pbvh_type(*ss->pbvh) == PBVH_GRIDS) { if (BKE_pbvh_type(*ss.pbvh) == PBVH_GRIDS) {
unode->mesh_grids_num = ss->subdiv_ccg->grids.size(); unode->mesh_grids_num = ss.subdiv_ccg->grids.size();
unode->grid_size = ss->subdiv_ccg->grid_size; unode->grid_size = ss.subdiv_ccg->grid_size;
unode->grids = bke::pbvh::node_grid_indices(*node); unode->grids = bke::pbvh::node_grid_indices(*node);
step_data->undo_size += unode->grids.as_span().size_in_bytes(); step_data->undo_size += unode->grids.as_span().size_in_bytes();
@ -1227,7 +1227,7 @@ static Node *alloc_node(const Object &object, const PBVHNode *node, const Type t
verts_num = unode->grids.size() * grid_area; verts_num = unode->grids.size() * grid_area;
} }
else { else {
unode->mesh_verts_num = ss->totvert; unode->mesh_verts_num = ss.totvert;
unode->vert_indices = bke::pbvh::node_verts(*node); unode->vert_indices = bke::pbvh::node_verts(*node);
unode->unique_verts_num = bke::pbvh::node_unique_verts(*node).size(); unode->unique_verts_num = bke::pbvh::node_unique_verts(*node).size();
@ -1248,11 +1248,11 @@ static Node *alloc_node(const Object &object, const PBVHNode *node, const Type t
} }
if (need_faces) { if (need_faces) {
if (BKE_pbvh_type(*ss->pbvh) == PBVH_FACES) { if (BKE_pbvh_type(*ss.pbvh) == PBVH_FACES) {
bke::pbvh::node_face_indices_calc_mesh(mesh.corner_tri_faces(), *node, unode->face_indices); bke::pbvh::node_face_indices_calc_mesh(mesh.corner_tri_faces(), *node, unode->face_indices);
} }
else { else {
bke::pbvh::node_face_indices_calc_grids(*ss->pbvh, *node, unode->face_indices); bke::pbvh::node_face_indices_calc_grids(*ss.pbvh, *node, unode->face_indices);
} }
step_data->undo_size += unode->face_indices.as_span().size_in_bytes(); step_data->undo_size += unode->face_indices.as_span().size_in_bytes();
} }
@ -1268,7 +1268,7 @@ static Node *alloc_node(const Object &object, const PBVHNode *node, const Type t
break; break;
} }
case Type::HideVert: { case Type::HideVert: {
if (BKE_pbvh_type(*ss->pbvh) == PBVH_GRIDS) { if (BKE_pbvh_type(*ss.pbvh) == PBVH_GRIDS) {
step_data->undo_size += alloc_and_store_hidden(ss, *node, unode); step_data->undo_size += alloc_and_store_hidden(ss, *node, unode);
} }
else { else {
@ -1295,7 +1295,7 @@ static Node *alloc_node(const Object &object, const PBVHNode *node, const Type t
step_data->undo_size += unode->col.as_span().size_in_bytes(); step_data->undo_size += unode->col.as_span().size_in_bytes();
/* Allocate loop colors separately too. */ /* Allocate loop colors separately too. */
if (ss->vcol_domain == bke::AttrDomain::Corner) { if (ss.vcol_domain == bke::AttrDomain::Corner) {
unode->loop_col.reinitialize(unode->corner_indices.size()); unode->loop_col.reinitialize(unode->corner_indices.size());
unode->undo_size += unode->loop_col.as_span().size_in_bytes(); unode->undo_size += unode->loop_col.as_span().size_in_bytes();
} }
@ -1318,7 +1318,7 @@ static Node *alloc_node(const Object &object, const PBVHNode *node, const Type t
} }
} }
if (ss->deform_modifiers_active) { if (ss.deform_modifiers_active) {
unode->orig_position.reinitialize(unode->vert_indices.size()); unode->orig_position.reinitialize(unode->vert_indices.size());
step_data->undo_size += unode->orig_position.as_span().size_in_bytes(); step_data->undo_size += unode->orig_position.as_span().size_in_bytes();
} }
@ -1328,10 +1328,10 @@ static Node *alloc_node(const Object &object, const PBVHNode *node, const Type t
static void store_coords(const Object &object, Node *unode) static void store_coords(const Object &object, Node *unode)
{ {
SculptSession *ss = object.sculpt; SculptSession &ss = *object.sculpt;
if (!unode->grids.is_empty()) { if (!unode->grids.is_empty()) {
const SubdivCCG &subdiv_ccg = *ss->subdiv_ccg; const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
const Span<CCGElem *> grids = subdiv_ccg.grids; const Span<CCGElem *> grids = subdiv_ccg.grids;
{ {
@ -1356,14 +1356,14 @@ static void store_coords(const Object &object, Node *unode)
} }
} }
else { else {
array_utils::gather(BKE_pbvh_get_vert_positions(*ss->pbvh).as_span(), array_utils::gather(BKE_pbvh_get_vert_positions(*ss.pbvh).as_span(),
unode->vert_indices.as_span(), unode->vert_indices.as_span(),
unode->position.as_mutable_span()); unode->position.as_mutable_span());
array_utils::gather(BKE_pbvh_get_vert_normals(*ss->pbvh), array_utils::gather(BKE_pbvh_get_vert_normals(*ss.pbvh),
unode->vert_indices.as_span(), unode->vert_indices.as_span(),
unode->normal.as_mutable_span()); unode->normal.as_mutable_span());
if (ss->deform_modifiers_active) { if (ss.deform_modifiers_active) {
array_utils::gather(ss->orig_cos.as_span(), array_utils::gather(ss.orig_cos.as_span(),
unode->vert_indices.as_span(), unode->vert_indices.as_span(),
unode->orig_position.as_mutable_span()); unode->orig_position.as_mutable_span());
} }
@ -1407,10 +1407,10 @@ static void store_face_hidden(const Object &object, Node &unode)
static void store_mask(const Object &object, Node *unode) static void store_mask(const Object &object, Node *unode)
{ {
const SculptSession *ss = object.sculpt; const SculptSession &ss = *object.sculpt;
if (!unode->grids.is_empty()) { if (!unode->grids.is_empty()) {
const SubdivCCG &subdiv_ccg = *ss->subdiv_ccg; const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
if (key.has_mask) { if (key.has_mask) {
const Span<CCGElem *> grids = subdiv_ccg.grids; const Span<CCGElem *> grids = subdiv_ccg.grids;
@ -1442,19 +1442,19 @@ static void store_mask(const Object &object, Node *unode)
static void store_color(const Object &object, Node *unode) static void store_color(const Object &object, Node *unode)
{ {
const Mesh &mesh = *static_cast<const Mesh *>(object.data); const Mesh &mesh = *static_cast<const Mesh *>(object.data);
SculptSession *ss = object.sculpt; SculptSession &ss = *object.sculpt;
BLI_assert(BKE_pbvh_type(*ss->pbvh) == PBVH_FACES); BLI_assert(BKE_pbvh_type(*ss.pbvh) == PBVH_FACES);
/* NOTE: even with loop colors we still store (derived) /* NOTE: even with loop colors we still store (derived)
* vertex colors for original data lookup. */ * vertex colors for original data lookup. */
BKE_pbvh_store_colors_vertex(*ss->pbvh, BKE_pbvh_store_colors_vertex(*ss.pbvh,
mesh.vert_to_face_map(), mesh.vert_to_face_map(),
unode->vert_indices.as_span().take_front(unode->unique_verts_num), unode->vert_indices.as_span().take_front(unode->unique_verts_num),
unode->col); unode->col);
if (!unode->loop_col.is_empty() && !unode->corner_indices.is_empty()) { if (!unode->loop_col.is_empty() && !unode->corner_indices.is_empty()) {
BKE_pbvh_store_colors(*ss->pbvh, unode->corner_indices, unode->loop_col); BKE_pbvh_store_colors(*ss.pbvh, unode->corner_indices, unode->loop_col);
} }
} }
@ -1492,7 +1492,7 @@ static void store_face_sets(const Mesh &mesh, Node &unode)
static Node *bmesh_push(const Object &object, const PBVHNode *node, Type type) static Node *bmesh_push(const Object &object, const PBVHNode *node, Type type)
{ {
StepData *step_data = get_step_data(); StepData *step_data = get_step_data();
const SculptSession *ss = object.sculpt; const SculptSession &ss = *object.sculpt;
Node *unode = step_data->nodes.is_empty() ? nullptr : step_data->nodes.first().get(); Node *unode = step_data->nodes.is_empty() ? nullptr : step_data->nodes.first().get();
@ -1504,8 +1504,8 @@ static Node *bmesh_push(const Object &object, const PBVHNode *node, Type type)
unode->applied = true; unode->applied = true;
if (type == Type::DyntopoEnd) { if (type == Type::DyntopoEnd) {
unode->bm_entry = BM_log_entry_add(ss->bm_log); unode->bm_entry = BM_log_entry_add(ss.bm_log);
BM_log_before_all_removed(ss->bm, ss->bm_log); BM_log_before_all_removed(ss.bm, ss.bm_log);
} }
else if (type == Type::DyntopoBegin) { else if (type == Type::DyntopoBegin) {
/* Store a copy of the mesh's current vertices, loops, and /* Store a copy of the mesh's current vertices, loops, and
@ -1516,17 +1516,17 @@ static Node *bmesh_push(const Object &object, const PBVHNode *node, Type type)
NodeGeometry *geometry = &unode->geometry_bmesh_enter; NodeGeometry *geometry = &unode->geometry_bmesh_enter;
store_geometry_data(geometry, object); store_geometry_data(geometry, object);
unode->bm_entry = BM_log_entry_add(ss->bm_log); unode->bm_entry = BM_log_entry_add(ss.bm_log);
BM_log_all_added(ss->bm, ss->bm_log); BM_log_all_added(ss.bm, ss.bm_log);
} }
else { else {
unode->bm_entry = BM_log_entry_add(ss->bm_log); unode->bm_entry = BM_log_entry_add(ss.bm_log);
} }
} }
if (node) { if (node) {
const int cd_vert_mask_offset = CustomData_get_offset_named( const int cd_vert_mask_offset = CustomData_get_offset_named(
&ss->bm->vdata, CD_PROP_FLOAT, ".sculpt_mask"); &ss.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
/* The vertices and node aren't changed, though pointers to them are stored in the log. */ /* The vertices and node aren't changed, though pointers to them are stored in the log. */
PBVHNode *node_mut = const_cast<PBVHNode *>(node); PBVHNode *node_mut = const_cast<PBVHNode *>(node);
@ -1537,24 +1537,24 @@ static Node *bmesh_push(const Object &object, const PBVHNode *node, Type type)
/* Before any vertex values get modified, ensure their /* Before any vertex values get modified, ensure their
* original positions are logged. */ * original positions are logged. */
for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(node_mut)) { for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(node_mut)) {
BM_log_vert_before_modified(ss->bm_log, vert, cd_vert_mask_offset); BM_log_vert_before_modified(ss.bm_log, vert, cd_vert_mask_offset);
} }
for (BMVert *vert : BKE_pbvh_bmesh_node_other_verts(node_mut)) { for (BMVert *vert : BKE_pbvh_bmesh_node_other_verts(node_mut)) {
BM_log_vert_before_modified(ss->bm_log, vert, cd_vert_mask_offset); BM_log_vert_before_modified(ss.bm_log, vert, cd_vert_mask_offset);
} }
break; break;
case Type::HideFace: case Type::HideFace:
case Type::HideVert: { case Type::HideVert: {
for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(node_mut)) { for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(node_mut)) {
BM_log_vert_before_modified(ss->bm_log, vert, cd_vert_mask_offset); BM_log_vert_before_modified(ss.bm_log, vert, cd_vert_mask_offset);
} }
for (BMVert *vert : BKE_pbvh_bmesh_node_other_verts(node_mut)) { for (BMVert *vert : BKE_pbvh_bmesh_node_other_verts(node_mut)) {
BM_log_vert_before_modified(ss->bm_log, vert, cd_vert_mask_offset); BM_log_vert_before_modified(ss.bm_log, vert, cd_vert_mask_offset);
} }
for (BMFace *f : BKE_pbvh_bmesh_node_faces(node_mut)) { for (BMFace *f : BKE_pbvh_bmesh_node_faces(node_mut)) {
BM_log_face_modified(ss->bm_log, f); BM_log_face_modified(ss.bm_log, f);
} }
break; break;
} }
@ -1574,7 +1574,7 @@ static Node *bmesh_push(const Object &object, const PBVHNode *node, Type type)
Node *push_node(const Object &object, const PBVHNode *node, Type type) Node *push_node(const Object &object, const PBVHNode *node, Type type)
{ {
SculptSession *ss = object.sculpt; SculptSession &ss = *object.sculpt;
Node *unode; Node *unode;
@ -1583,10 +1583,10 @@ Node *push_node(const Object &object, const PBVHNode *node, Type type)
/* List is manipulated by multiple threads, so we lock. */ /* List is manipulated by multiple threads, so we lock. */
std::scoped_lock lock(step_data->nodes_mutex); std::scoped_lock lock(step_data->nodes_mutex);
ss->needs_flush_to_id = 1; ss.needs_flush_to_id = 1;
threading::isolate_task([&]() { threading::isolate_task([&]() {
if (ss->bm || ELEM(type, Type::DyntopoBegin, Type::DyntopoEnd)) { if (ss.bm || ELEM(type, Type::DyntopoBegin, Type::DyntopoEnd)) {
/* Dynamic topology stores only one undo node per stroke, /* Dynamic topology stores only one undo node per stroke,
* regardless of the number of PBVH nodes modified. */ * regardless of the number of PBVH nodes modified. */
unode = bmesh_push(object, node, type); unode = bmesh_push(object, node, type);
@ -2027,7 +2027,7 @@ static bool use_multires_mesh(bContext *C)
static void push_all_grids(Object *object) static void push_all_grids(Object *object)
{ {
SculptSession *ss = object->sculpt; SculptSession &ss = *object->sculpt;
/* It is possible that undo push is done from an object state where there is no PBVH. This /* It is possible that undo push is done from an object state where there is no PBVH. This
* happens, for example, when an operation which tagged for geometry update was performed prior * happens, for example, when an operation which tagged for geometry update was performed prior
@ -2037,11 +2037,11 @@ static void push_all_grids(Object *object)
* ensure PBVH for the new base geometry, which will have same coordinates as if we create PBVH * ensure PBVH for the new base geometry, which will have same coordinates as if we create PBVH
* here. * here.
*/ */
if (ss->pbvh == nullptr) { if (ss.pbvh == nullptr) {
return; return;
} }
Vector<PBVHNode *> nodes = bke::pbvh::search_gather(*ss->pbvh, {}); Vector<PBVHNode *> nodes = bke::pbvh::search_gather(*ss.pbvh, {});
for (PBVHNode *node : nodes) { for (PBVHNode *node : nodes) {
push_node(*object, node, Type::Position); push_node(*object, node, Type::Position);
} }

@ -362,9 +362,7 @@ static bool stats_is_object_dynamic_topology_sculpt(const Object *ob)
static void stats_object_sculpt(const Object *ob, SceneStats *stats) static void stats_object_sculpt(const Object *ob, SceneStats *stats)
{ {
SculptSession *ss = ob->sculpt; SculptSession *ss = ob->sculpt;
if (ss == nullptr || ss->pbvh == nullptr) { if (ss == nullptr || ss->pbvh == nullptr) {
return; return;
} }