Refactor: Introduce typed version of SculptSession#active_vertex

Part of #118145.

Uses std::variant (and std::monostate to represent no value) to hold the
current active vertex type among the three different concrete types.

Pull Request: https://projects.blender.org/blender/blender/pulls/126000
This commit is contained in:
Sean Kim
2024-08-07 21:17:42 +02:00
committed by Sean Kim
parent 51152cec30
commit e16e07b2da
13 changed files with 72 additions and 48 deletions

View File

@@ -8,6 +8,8 @@
* \ingroup bke
*/
#include <variant>
#include "BLI_array.hh"
#include "BLI_bit_vector.hh"
#include "BLI_map.hh"
@@ -74,6 +76,7 @@ struct Scene;
struct Sculpt;
struct SculptSession;
struct SubdivCCG;
struct SubdivCCGCoord;
struct Tex;
struct ToolSettings;
struct UnifiedPaintSettings;
@@ -406,6 +409,8 @@ struct SculptTopologyIslandCache {
blender::Array<uint8_t> vert_island_ids;
};
using ActiveVert = std::variant<std::monostate, int, SubdivCCGCoord, BMVert *>;
struct SculptSession : blender::NonCopyable, blender::NonMovable {
/* Mesh data (not copied) can come either directly from a Mesh, or from a MultiresDM */
struct { /* Special handling for multires meshes */
@@ -587,11 +592,13 @@ struct SculptSession : blender::NonCopyable, blender::NonMovable {
SculptSession();
~SculptSession();
PBVHVertRef active_vertex() const;
void set_active_vertex(PBVHVertRef vert);
PBVHVertRef active_vert_ref() const;
ActiveVert active_vert() const;
void set_active_vert(PBVHVertRef vert);
private:
PBVHVertRef active_vertex_ = PBVHVertRef{PBVH_REF_NONE};
PBVHVertRef active_vert_ = PBVHVertRef{PBVH_REF_NONE};
};
void BKE_sculptsession_free(Object *ob);

View File

@@ -1736,22 +1736,42 @@ SculptSession::~SculptSession()
MEM_SAFE_FREE(this->last_paint_canvas_key);
}
PBVHVertRef SculptSession::active_vertex() const
PBVHVertRef SculptSession::active_vert_ref() const
{
if (ELEM(this->pbvh->type(),
blender::bke::pbvh::Type::Mesh,
blender::bke::pbvh::Type::Grids,
blender::bke::pbvh::Type::BMesh))
{
return active_vertex_;
return active_vert_;
}
return {PBVH_REF_NONE};
}
void SculptSession::set_active_vertex(const PBVHVertRef vert)
ActiveVert SculptSession::active_vert() const
{
active_vertex_ = vert;
/* TODO: While this code currently translates the stored PBVHVertRef into the given type, once
* we stored the actual field as ActiveVertex, this call can replace #active_vertex. */
switch (this->pbvh->type()) {
case blender::bke::pbvh::Type::Mesh:
return (int)active_vert_.i;
case blender::bke::pbvh::Type::Grids: {
const CCGKey key = BKE_subdiv_ccg_key_top_level(*this->subdiv_ccg);
return SubdivCCGCoord::from_index(key, active_vert_.i);
}
case blender::bke::pbvh::Type::BMesh:
return reinterpret_cast<BMVert *>(active_vert_.i);
default:
BLI_assert_unreachable();
}
return {};
}
void SculptSession::set_active_vert(const PBVHVertRef vert)
{
active_vert_ = vert;
}
static MultiresModifierData *sculpt_multires_modifier_get(const Scene *scene,

View File

@@ -1411,7 +1411,7 @@ static void paint_cursor_sculpt_session_update_and_init(PaintCursorContext *pcon
/* This updates the active vertex, which is needed for most of the Sculpt/Vertex Colors tools to
* work correctly */
pcontext->prev_active_vertex = ss.active_vertex();
pcontext->prev_active_vertex = ss.active_vert_ref();
if (!ups.stroke_active) {
pcontext->is_cursor_over_mesh = SCULPT_cursor_geometry_info_update(
C, &gi, mval_fl, (pcontext->brush->falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE));
@@ -1733,7 +1733,7 @@ static void paint_cursor_preview_boundary_data_update(PaintCursorContext *pconte
BKE_sculpt_update_object_for_edit(pcontext->depsgraph, pcontext->vc.obact, false);
ss.boundary_preview = boundary::preview_data_init(
*pcontext->vc.obact, pcontext->brush, ss.active_vertex(), pcontext->radius);
*pcontext->vc.obact, pcontext->brush, ss.active_vert_ref(), pcontext->radius);
}
static void paint_cursor_draw_3d_view_brush_cursor_inactive(PaintCursorContext *pcontext)
@@ -1760,7 +1760,7 @@ static void paint_cursor_draw_3d_view_brush_cursor_inactive(PaintCursorContext *
paint_cursor_update_object_space_radius(pcontext);
const PBVHVertRef active_vert = pcontext->ss->active_vertex();
const PBVHVertRef active_vert = pcontext->ss->active_vert_ref();
/* Setup drawing. */
wmViewport(&pcontext->region->winrct);

View File

@@ -227,7 +227,7 @@ const float *SCULPT_vertex_co_for_grab_active_get(const SculptSession &ss, PBVHV
const float *SCULPT_active_vertex_co_get(const SculptSession &ss)
{
return SCULPT_vertex_co_get(ss, ss.active_vertex());
return SCULPT_vertex_co_get(ss, ss.active_vert_ref());
}
MutableSpan<float3> SCULPT_mesh_deformed_positions_get(SculptSession &ss)
@@ -4671,7 +4671,7 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings &ups, Object &ob, con
if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(*ss.cache)) {
if (tool == SCULPT_TOOL_GRAB && brush.flag & BRUSH_GRAB_ACTIVE_VERTEX) {
copy_v3_v3(cache->orig_grab_location,
SCULPT_vertex_co_for_grab_active_get(ss, ss.active_vertex()));
SCULPT_vertex_co_for_grab_active_get(ss, ss.active_vert_ref()));
}
else {
copy_v3_v3(cache->orig_grab_location, cache->true_location);
@@ -5178,7 +5178,7 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
/* Update the active vertex of the SculptSession. */
const PBVHVertRef active_vertex = srd.active_vertex;
ss.set_active_vertex(active_vertex);
ss.set_active_vert(active_vertex);
SCULPT_vertex_random_access_ensure(ss);
copy_v3_v3(out->active_vertex_co, SCULPT_vertex_co_get(ss, active_vertex));

View File

@@ -759,7 +759,7 @@ static void topology_automasking_init(const Sculpt &sd, Object &ob)
* the brush radius if the tool requires it. */
flood_fill::FillData flood = flood_fill::init_fill(ss);
const float radius = ss.cache ? ss.cache->radius : FLT_MAX;
flood_fill::add_initial_with_symmetry(ob, ss, flood, ss.active_vertex(), radius);
flood_fill::add_initial_with_symmetry(ob, ss, flood, ss.active_vert_ref(), radius);
AutomaskFloodFillData fdata = {0};
@@ -767,7 +767,7 @@ static void topology_automasking_init(const Sculpt &sd, Object &ob)
fdata.use_radius = ss.cache && is_constrained_by_radius(brush);
fdata.symm = SCULPT_mesh_symmetry_xyz_get(ob);
copy_v3_v3(fdata.location, SCULPT_vertex_co_get(ss, ss.active_vertex()));
copy_v3_v3(fdata.location, SCULPT_vertex_co_get(ss, ss.active_vert_ref()));
flood_fill::execute(ss, flood, [&](PBVHVertRef from_v, PBVHVertRef to_v, bool /*is_duplicate*/) {
return floodfill_cb(ss, from_v, to_v, &fdata);
});
@@ -956,10 +956,10 @@ std::unique_ptr<Cache> cache_init(const Sculpt &sd, const Brush *brush, Object &
int mode = calc_effective_bits(sd, brush);
if (mode & BRUSH_AUTOMASKING_TOPOLOGY && ss.active_vertex().i != PBVH_REF_NONE) {
if (mode & BRUSH_AUTOMASKING_TOPOLOGY && ss.active_vert_ref().i != PBVH_REF_NONE) {
islands::ensure_cache(ob);
automasking->settings.initial_island_nr = islands::vert_id_get(
ss, BKE_pbvh_vertex_to_index(*ss.pbvh, ss.active_vertex()));
ss, BKE_pbvh_vertex_to_index(*ss.pbvh, ss.active_vert_ref()));
}
bool use_stroke_id = false;

View File

@@ -3109,18 +3109,17 @@ static void init_boundary_mesh(Object &object,
const Span<float3> positions_eval = BKE_pbvh_get_vert_positions(pbvh);
const Span<float3> vert_normals = BKE_pbvh_get_vert_normals(pbvh);
/* TODO: Remove PBVHVertRef here once we decide how we are storing the active_vertex value. */
PBVHVertRef initial_vert_ref = ss.active_vertex();
if (initial_vert_ref.i == PBVH_REF_NONE) {
ActiveVert initial_vert_ref = ss.active_vert();
if (std::holds_alternative<std::monostate>(initial_vert_ref)) {
return;
}
std::optional<int> initial_vert;
if (ss.cache->mirror_symmetry_pass == 0) {
initial_vert = initial_vert_ref.i;
initial_vert = std::get<int>(initial_vert_ref);
}
else {
float3 location = symmetry_flip(positions_eval[initial_vert_ref.i], symm_area);
float3 location = symmetry_flip(positions_eval[std::get<int>(initial_vert_ref)], symm_area);
initial_vert = nearest_vert_calc_mesh(
*ss.pbvh, positions_eval, hide_vert, location, ss.cache->radius_squared, false);
}
@@ -3168,18 +3167,17 @@ static void init_boundary_grids(Object &object,
const CCGKey &key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
Span<CCGElem *> grids = subdiv_ccg.grids;
/* TODO: Remove PBVHVertRef here once we decide how we are storing the active_vertex value. */
PBVHVertRef initial_vert_ref = ss.active_vertex();
if (initial_vert_ref.i == PBVH_REF_NONE) {
ActiveVert initial_vert_ref = ss.active_vert();
if (std::holds_alternative<std::monostate>(initial_vert_ref)) {
return;
}
std::optional<SubdivCCGCoord> initial_vert;
if (ss.cache->mirror_symmetry_pass == 0) {
initial_vert = SubdivCCGCoord::from_index(key, initial_vert_ref.i);
initial_vert = std::get<SubdivCCGCoord>(initial_vert_ref);
}
else {
const SubdivCCGCoord active_vert = SubdivCCGCoord::from_index(key, initial_vert_ref.i);
const SubdivCCGCoord active_vert = std::get<SubdivCCGCoord>(initial_vert_ref);
float3 location = symmetry_flip(
CCG_grid_elem_co(key, grids[active_vert.grid_index], active_vert.x, active_vert.y),
symm_area);
@@ -3229,18 +3227,17 @@ static void init_boundary_bmesh(Object &object,
BMesh *bm = ss.bm;
/* TODO: Remove PBVHVertRef here once we decide how we are storing the active_vertex value. */
PBVHVertRef initial_vert_ref = ss.active_vertex();
if (initial_vert_ref.i == PBVH_REF_NONE) {
ActiveVert initial_vert_ref = ss.active_vert();
if (std::holds_alternative<std::monostate>(initial_vert_ref)) {
return;
}
std::optional<BMVert *> initial_vert;
if (ss.cache->mirror_symmetry_pass == 0) {
initial_vert = reinterpret_cast<BMVert *>(initial_vert_ref.i);
initial_vert = std::get<BMVert *>(initial_vert_ref);
}
else {
BMVert *active_vert = reinterpret_cast<BMVert *>(initial_vert_ref.i);
BMVert *active_vert = std::get<BMVert *>(initial_vert_ref);
float3 location = symmetry_flip(active_vert->co, symm_area);
initial_vert = nearest_vert_calc_bmesh(pbvh, location, ss.cache->radius_squared, false);
}

View File

@@ -2312,7 +2312,7 @@ static int sculpt_cloth_filter_invoke(bContext *C, wmOperator *op, const wmEvent
use_collisions,
cloth_filter_is_deformation_filter(filter_type));
ss.filter_cache->cloth_sim_pinch_point = SCULPT_vertex_co_get(ss, ss.active_vertex());
ss.filter_cache->cloth_sim_pinch_point = SCULPT_vertex_co_get(ss, ss.active_vert_ref());
float3 origin(0);
ensure_nodes_constraints(

View File

@@ -200,7 +200,7 @@ static void sample_detail_voxel(bContext *C, ViewContext *vc, const int mval[2])
BKE_sculpt_update_object_for_edit(depsgraph, &ob, false);
/* Average the edge length of the connected edges to the active vertex. */
const int active_vert = ss.active_vertex().i;
const int active_vert = ss.active_vert_ref().i;
const float3 active_vert_position = positions[active_vert];
float edge_length = 0.0f;
Vector<int> neighbors;
@@ -590,7 +590,7 @@ static void dyntopo_detail_size_sample_from_surface(Object &ob,
DyntopoDetailSizeEditCustomData *cd)
{
SculptSession &ss = *ob.sculpt;
BMVert *active_vertex = reinterpret_cast<BMVert *>(ss.active_vertex().i);
BMVert *active_vertex = reinterpret_cast<BMVert *>(ss.active_vert_ref().i);
float len_accum = 0;
Vector<BMVert *, 64> neighbors;

View File

@@ -1655,7 +1655,7 @@ static PBVHVertRef target_vert_update_and_get(bContext *C, Object &ob, const flo
SculptSession &ss = *ob.sculpt;
SculptCursorGeometryInfo sgi;
if (SCULPT_cursor_geometry_info_update(C, &sgi, mval, false)) {
return ss.active_vertex();
return ss.active_vert_ref();
}
return BKE_pbvh_make_vref(SCULPT_EXPAND_VERTEX_NONE);
}
@@ -1788,7 +1788,7 @@ static void set_initial_components_for_mouse(bContext *C,
if (initial_vertex.i == SCULPT_EXPAND_VERTEX_NONE) {
/* Cursor not over the mesh, for creating valid initial falloffs, fallback to the last active
* vertex in the sculpt session. */
initial_vertex = ss.active_vertex();
initial_vertex = ss.active_vert_ref();
}
int initial_vertex_i = BKE_pbvh_vertex_to_index(*ss.pbvh, initial_vertex);

View File

@@ -889,7 +889,7 @@ static int change_visibility_exec(bContext *C, wmOperator *op)
UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
float location[3];
copy_v3_v3(location, SCULPT_vertex_co_get(ss, ss.active_vertex()));
copy_v3_v3(location, SCULPT_vertex_co_get(ss, ss.active_vert_ref()));
mul_m4_v3(object.object_to_world().ptr(), location);
copy_v3_v3(ups->average_stroke_accum, location);
ups->average_stroke_counter = 1;

View File

@@ -600,7 +600,7 @@ void geometry_preview_lines_update(bContext *C, SculptSession &ss, float radius)
BKE_sculpt_update_object_for_edit(depsgraph, ob, false);
float brush_co[3];
copy_v3_v3(brush_co, SCULPT_vertex_co_get(ss, ss.active_vertex()));
copy_v3_v3(brush_co, SCULPT_vertex_co_get(ss, ss.active_vert_ref()));
BitVector<> visited_verts(SCULPT_vertex_count_get(ss));
@@ -612,7 +612,7 @@ void geometry_preview_lines_update(bContext *C, SculptSession &ss, float radius)
}
std::queue<PBVHVertRef> non_visited_verts;
non_visited_verts.push(ss.active_vertex());
non_visited_verts.push(ss.active_vert_ref());
while (!non_visited_verts.empty()) {
PBVHVertRef from_v = non_visited_verts.front();
@@ -650,7 +650,7 @@ static int sculpt_sample_color_invoke(bContext *C, wmOperator *op, const wmEvent
Object &ob = *CTX_data_active_object(C);
Brush &brush = *BKE_paint_brush(&sd.paint);
SculptSession &ss = *ob.sculpt;
PBVHVertRef active_vertex = ss.active_vertex();
PBVHVertRef active_vertex = ss.active_vert_ref();
if (!SCULPT_handles_colors_report(ss, op->reports)) {
return OPERATOR_CANCELLED;
@@ -879,7 +879,7 @@ static int sculpt_mask_by_color_invoke(bContext *C, wmOperator *op, const wmEven
undo::push_begin(ob, op);
BKE_sculpt_color_layer_create_if_needed(&ob);
const PBVHVertRef active_vertex = ss.active_vertex();
const PBVHVertRef active_vertex = ss.active_vert_ref();
const float threshold = RNA_float_get(op->ptr, "threshold");
const bool invert = RNA_boolean_get(op->ptr, "invert");
const bool preserve_mask = RNA_boolean_get(op->ptr, "preserve_previous_mask");

View File

@@ -609,7 +609,7 @@ void calc_pose_data(Object &ob,
/* Calculate the pose rotation point based on the boundaries of the brush factor. */
flood_fill::FillData flood = flood_fill::init_fill(ss);
flood_fill::add_initial_with_symmetry(
ob, ss, flood, ss.active_vertex(), !r_pose_factor.is_empty() ? radius : 0.0f);
ob, ss, flood, ss.active_vert_ref(), !r_pose_factor.is_empty() ? radius : 0.0f);
const int symm = SCULPT_mesh_symmetry_xyz_get(ob);
@@ -815,7 +815,7 @@ static std::unique_ptr<SculptPoseIKChain> pose_ik_chain_init_face_sets(Object &o
int current_face_set = SCULPT_FACE_SET_NONE;
PBVHVertRef current_vertex = ss.active_vertex();
PBVHVertRef current_vertex = ss.active_vert_ref();
for (const int i : ik_chain->segments.index_range()) {
const bool is_first_iteration = i == 0;
@@ -871,7 +871,7 @@ static std::unique_ptr<SculptPoseIKChain> pose_ik_chain_init_face_sets(Object &o
current_vertex = next_vertex;
}
pose_ik_chain_origin_heads_init(*ik_chain, SCULPT_vertex_co_get(ss, ss.active_vertex()));
pose_ik_chain_origin_heads_init(*ik_chain, SCULPT_vertex_co_get(ss, ss.active_vert_ref()));
return ik_chain;
}
@@ -938,7 +938,7 @@ static std::unique_ptr<SculptPoseIKChain> pose_ik_chain_init_face_sets_fk(
std::unique_ptr<SculptPoseIKChain> ik_chain = pose_ik_chain_new(1, totvert);
const PBVHVertRef active_vertex = ss.active_vertex();
const PBVHVertRef active_vertex = ss.active_vert_ref();
int active_vertex_index = BKE_pbvh_vertex_to_index(*ss.pbvh, active_vertex);
const int active_face_set = face_set::active_face_set_get(ss);
@@ -1012,7 +1012,7 @@ static std::unique_ptr<SculptPoseIKChain> pose_ik_chain_init_face_sets_fk(
{
flood_fill::FillData flood = flood_fill::init_fill(ss);
flood_fill::add_initial_with_symmetry(ob, ss, flood, ss.active_vertex(), radius);
flood_fill::add_initial_with_symmetry(ob, ss, flood, ss.active_vert_ref(), radius);
MutableSpan<float> fk_weights = ik_chain->segments[0].weights;
flood_fill::execute(
ss, flood, [&](PBVHVertRef /*from_v*/, PBVHVertRef to_v, bool /*is_duplicate*/) {

View File

@@ -891,7 +891,7 @@ static int set_pivot_position_exec(bContext *C, wmOperator *op)
}
/* Pivot to active vertex. */
else if (mode == PivotPositionMode::ActiveVert) {
copy_v3_v3(ss.pivot_pos, SCULPT_vertex_co_get(ss, ss.active_vertex()));
copy_v3_v3(ss.pivot_pos, SCULPT_vertex_co_get(ss, ss.active_vert_ref()));
}
/* Pivot to ray-cast surface. */
else if (mode == PivotPositionMode::CursorSurface) {