diff --git a/source/blender/editors/sculpt_paint/brushes/grab.cc b/source/blender/editors/sculpt_paint/brushes/grab.cc index a296d01f49d..4ff711aa71c 100644 --- a/source/blender/editors/sculpt_paint/brushes/grab.cc +++ b/source/blender/editors/sculpt_paint/brushes/grab.cc @@ -266,4 +266,70 @@ void do_grab_brush(const Depsgraph &depsgraph, bke::pbvh::flush_bounds_to_parents(pbvh); } +void geometry_preview_lines_update(Depsgraph &depsgraph, + Object &object, + SculptSession &ss, + float radius) +{ + ss.preview_verts = {}; + + /* This function is called from the cursor drawing code, so the tree may not be built yet. */ + const bke::pbvh::Tree *pbvh = bke::object::pbvh_get(object); + if (!pbvh) { + return; + } + + if (!ss.deform_modifiers_active) { + return; + } + + if (pbvh->type() != bke::pbvh::Type::Mesh) { + return; + } + + BKE_sculpt_update_object_for_edit(&depsgraph, &object, false); + + const Mesh &mesh = *static_cast(object.data); + /* Always grab active shape key if the sculpt happens on shapekey. */ + const Span positions = ss.shapekey_active ? + bke::pbvh::vert_positions_eval(depsgraph, object) : + mesh.vert_positions(); + const OffsetIndices faces = mesh.faces(); + const Span corner_verts = mesh.corner_verts(); + const GroupedSpan vert_to_face_map = mesh.vert_to_face_map(); + const bke::AttributeAccessor attributes = mesh.attributes(); + const VArraySpan hide_poly = *attributes.lookup(".hide_poly", bke::AttrDomain::Face); + + const int active_vert = std::get(ss.active_vert()); + const float3 brush_co = positions[active_vert]; + const float radius_sq = radius * radius; + + Vector preview_verts; + Vector neighbors; + BitVector<> visited_verts(positions.size()); + std::queue queue; + queue.push(active_vert); + while (!queue.empty()) { + const int from_vert = queue.front(); + queue.pop(); + + neighbors.clear(); + for (const int neighbor : vert_neighbors_get_mesh( + faces, corner_verts, vert_to_face_map, hide_poly, from_vert, neighbors)) + { + preview_verts.append(from_vert); + preview_verts.append(neighbor); + if (visited_verts[neighbor]) { + continue; + } + visited_verts[neighbor].set(); + if (math::distance_squared(brush_co, positions[neighbor]) < radius_sq) { + queue.push(neighbor); + } + } + } + + ss.preview_verts = preview_verts.as_span(); +} + } // namespace blender::ed::sculpt_paint diff --git a/source/blender/editors/sculpt_paint/paint_cursor.cc b/source/blender/editors/sculpt_paint/paint_cursor.cc index eb7c9d5ace7..19656a4fd4c 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.cc +++ b/source/blender/editors/sculpt_paint/paint_cursor.cc @@ -1874,7 +1874,8 @@ static void paint_cursor_draw_3d_view_brush_cursor_inactive(PaintCursorContext * if (is_brush_tool && brush.sculpt_brush_type == SCULPT_BRUSH_TYPE_GRAB && (brush.flag & BRUSH_GRAB_ACTIVE_VERTEX)) { - geometry_preview_lines_update(pcontext->C, *pcontext->ss, pcontext->radius); + geometry_preview_lines_update( + *pcontext->depsgraph, *pcontext->vc.obact, *pcontext->ss, pcontext->radius); sculpt_geometry_preview_lines_draw( *pcontext->depsgraph, pcontext->pos, *pcontext->brush, active_object); } diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.hh b/source/blender/editors/sculpt_paint/sculpt_intern.hh index 03f3d4d3678..27705266371 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.hh +++ b/source/blender/editors/sculpt_paint/sculpt_intern.hh @@ -424,7 +424,10 @@ bool SCULPT_cursor_geometry_info_update(bContext *C, namespace blender::ed::sculpt_paint { -void geometry_preview_lines_update(bContext *C, SculptSession &ss, float radius); +void geometry_preview_lines_update(Depsgraph &depsgraph, + Object &object, + SculptSession &ss, + float radius); } diff --git a/source/blender/editors/sculpt_paint/sculpt_ops.cc b/source/blender/editors/sculpt_paint/sculpt_ops.cc index ac05e994891..4030e9f0477 100644 --- a/source/blender/editors/sculpt_paint/sculpt_ops.cc +++ b/source/blender/editors/sculpt_paint/sculpt_ops.cc @@ -81,7 +81,11 @@ namespace blender::ed::sculpt_paint { -static int sculpt_set_persistent_base_exec(bContext *C, wmOperator * /*op*/) +/* -------------------------------------------------------------------- */ +/** \name Set Persistent Base Operator + * \{ */ + +static int set_persistent_base_exec(bContext *C, wmOperator * /*op*/) { Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); Object &ob = *CTX_data_active_object(C); @@ -137,15 +141,19 @@ static void SCULPT_OT_set_persistent_base(wmOperatorType *ot) ot->idname = "SCULPT_OT_set_persistent_base"; ot->description = "Reset the copy of the mesh that is being sculpted on"; - ot->exec = sculpt_set_persistent_base_exec; + ot->exec = set_persistent_base_exec; ot->poll = SCULPT_mode_poll; ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/************************* SCULPT_OT_optimize *************************/ +/** \} */ -static int sculpt_optimize_exec(bContext *C, wmOperator * /*op*/) +/* -------------------------------------------------------------------- */ +/** \name Optimize Operator + * \{ */ + +static int optimize_exec(bContext *C, wmOperator * /*op*/) { Object &ob = *CTX_data_active_object(C); @@ -167,15 +175,19 @@ static void SCULPT_OT_optimize(wmOperatorType *ot) ot->idname = "SCULPT_OT_optimize"; ot->description = "Recalculate the sculpt BVH to improve performance"; - ot->exec = sculpt_optimize_exec; + ot->exec = optimize_exec; ot->poll = SCULPT_mode_poll; ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/********************* Dynamic topology symmetrize ********************/ +/** \} */ -static bool sculpt_no_multires_poll(bContext *C) +/* -------------------------------------------------------------------- */ +/** \name Symmetrize Operator + * \{ */ + +static bool no_multires_poll(bContext *C) { Object *ob = CTX_data_active_object(C); if (!ob) { @@ -191,7 +203,7 @@ static bool sculpt_no_multires_poll(bContext *C) return false; } -static int sculpt_symmetrize_exec(bContext *C, wmOperator *op) +static int symmetrize_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); const Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(C); @@ -276,25 +288,29 @@ static void SCULPT_OT_symmetrize(wmOperatorType *ot) ot->idname = "SCULPT_OT_symmetrize"; ot->description = "Symmetrize the topology modifications"; - ot->exec = sculpt_symmetrize_exec; - ot->poll = sculpt_no_multires_poll; + ot->exec = symmetrize_exec; + ot->poll = no_multires_poll; PropertyRNA *prop = RNA_def_float(ot->srna, "merge_tolerance", 0.0005f, 0.0f, - FLT_MAX, + std::numeric_limits::max(), "Merge Distance", "Distance within which symmetrical vertices are merged", 0.0f, 1.0f); - RNA_def_property_ui_range(prop, 0.0, FLT_MAX, 0.001, 5); + RNA_def_property_ui_range(prop, 0.0, std::numeric_limits::max(), 0.001, 5); } -/**** Toggle operator for turning sculpt mode on or off ****/ +/** \} */ -static void sculpt_init_session(Main &bmain, Depsgraph &depsgraph, Scene &scene, Object &ob) +/* -------------------------------------------------------------------- */ +/** \name Sculpt Mode Toggle Operator + * \{ */ + +static void init_sculpt_mode_session(Main &bmain, Depsgraph &depsgraph, Scene &scene, Object &ob) { /* Create persistent sculpt mode data. */ BKE_sculpt_toolsettings_data_ensure(&bmain, &scene); @@ -375,7 +391,7 @@ void object_sculpt_mode_enter(Main &bmain, /* Enter sculpt mode. */ ob.mode |= mode_flag; - sculpt_init_session(bmain, depsgraph, scene, ob); + init_sculpt_mode_session(bmain, depsgraph, scene, ob); if (!(fabsf(ob.scale[0] - ob.scale[1]) < 1e-4f && fabsf(ob.scale[1] - ob.scale[2]) < 1e-4f)) { BKE_report( @@ -403,7 +419,7 @@ void object_sculpt_mode_enter(Main &bmain, message_unsupported = RPT_("multi-res modifier"); } else { - dyntopo::WarnFlag flag = dyntopo::check_attribute_warning(scene, ob); + const dyntopo::WarnFlag flag = dyntopo::check_attribute_warning(scene, ob); if (flag == 0) { /* pass */ } @@ -420,14 +436,14 @@ void object_sculpt_mode_enter(Main &bmain, message_unsupported = RPT_("constructive modifier"); } else { - BLI_assert(0); + BLI_assert_unreachable(); } } if ((message_unsupported == nullptr) || force_dyntopo) { /* Needed because we may be entering this mode before the undo system loads. */ wmWindowManager *wm = static_cast(bmain.wm.first); - bool has_undo = wm->undo_stack != nullptr; + const bool has_undo = wm->undo_stack != nullptr; /* Undo push is needed to prevent memory leak. */ if (has_undo) { undo::push_begin_ex(ob, "Dynamic topology enable"); @@ -581,73 +597,13 @@ static void SCULPT_OT_sculptmode_toggle(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -void geometry_preview_lines_update(bContext *C, SculptSession &ss, float radius) -{ - Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); - Object *ob = CTX_data_active_object(C); +/** \} */ - ss.preview_verts = {}; +/* -------------------------------------------------------------------- */ +/** \name Sample Color Operator + * \{ */ - /* This function is called from the cursor drawing code, so the tree may not be build yet. */ - const bke::pbvh::Tree *pbvh = bke::object::pbvh_get(*ob); - if (!pbvh) { - return; - } - - if (!ss.deform_modifiers_active) { - return; - } - - if (pbvh->type() != bke::pbvh::Type::Mesh) { - return; - } - - BKE_sculpt_update_object_for_edit(depsgraph, ob, false); - - const Mesh &mesh = *static_cast(ob->data); - /* Always grab active shape key if the sculpt happens on shapekey. */ - const Span positions = ss.shapekey_active ? - bke::pbvh::vert_positions_eval(*depsgraph, *ob) : - mesh.vert_positions(); - const OffsetIndices faces = mesh.faces(); - const Span corner_verts = mesh.corner_verts(); - const GroupedSpan vert_to_face_map = mesh.vert_to_face_map(); - const bke::AttributeAccessor attributes = mesh.attributes(); - const VArraySpan hide_poly = *attributes.lookup(".hide_poly", bke::AttrDomain::Face); - - const int active_vert = std::get(ss.active_vert()); - const float3 brush_co = positions[active_vert]; - const float radius_sq = radius * radius; - - Vector preview_verts; - Vector neighbors; - BitVector<> visited_verts(positions.size()); - std::queue queue; - queue.push(active_vert); - while (!queue.empty()) { - const int from_vert = queue.front(); - queue.pop(); - - neighbors.clear(); - for (const int neighbor : vert_neighbors_get_mesh( - faces, corner_verts, vert_to_face_map, hide_poly, from_vert, neighbors)) - { - preview_verts.append(from_vert); - preview_verts.append(neighbor); - if (visited_verts[neighbor]) { - continue; - } - visited_verts[neighbor].set(); - if (math::distance_squared(brush_co, positions[neighbor]) < radius_sq) { - queue.push(neighbor); - } - } - } - - ss.preview_verts = preview_verts.as_span(); -} - -static int sculpt_sample_color_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/) +static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/) { Sculpt &sd = *CTX_data_tool_settings(C)->sculpt; Scene &scene = *CTX_data_scene(C); @@ -702,14 +658,20 @@ static void SCULPT_OT_sample_color(wmOperatorType *ot) ot->idname = "SCULPT_OT_sample_color"; ot->description = "Sample the vertex color of the active vertex"; - ot->invoke = sculpt_sample_color_invoke; + ot->invoke = sample_color_invoke; ot->poll = SCULPT_mode_poll; ot->flag = OPTYPE_REGISTER | OPTYPE_DEPENDS_ON_CURSOR; } +/** \} */ + namespace mask { +/* -------------------------------------------------------------------- */ +/** \name Mask By Color + * \{ */ + /** * #sculpt_mask_by_color_delta_get returns values in the (0,1) range that are used to generate the * mask based on the difference between two colors (the active color and the color of any other @@ -721,14 +683,14 @@ namespace mask { */ #define MASK_BY_COLOR_SLOPE 0.25f -static float sculpt_mask_by_color_delta_get(const float *color_a, - const float *color_b, - const float threshold, - const bool invert) +static float color_delta_get(const float3 &color_a, + const float3 &color_b, + const float threshold, + const bool invert) { - float len = len_v3v3(color_a, color_b); + float len = math::distance(color_a, color_b); /* Normalize len to the (0, 1) range. */ - len = len / M_SQRT3; + len = len / math::numbers::sqrt3_v; if (len < threshold - MASK_BY_COLOR_SLOPE) { len = 1.0f; @@ -746,26 +708,26 @@ static float sculpt_mask_by_color_delta_get(const float *color_a, return len; } -static float sculpt_mask_by_color_final_mask_get(const float current_mask, - const float new_mask, - const bool invert, - const bool preserve_mask) +static float final_mask_get(const float current_mask, + const float new_mask, + const bool invert, + const bool preserve_mask) { if (preserve_mask) { if (invert) { - return min_ff(current_mask, new_mask); + return std::min(current_mask, new_mask); } - return max_ff(current_mask, new_mask); + return std::max(current_mask, new_mask); } return new_mask; } -static void sculpt_mask_by_color_contiguous_mesh(const Depsgraph &depsgraph, - Object &object, - const int vert, - const float threshold, - const bool invert, - const bool preserve_mask) +static void mask_by_color_contiguous_mesh(const Depsgraph &depsgraph, + Object &object, + const int vert, + const float threshold, + const bool invert, + const bool preserve_mask) { const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object); const Mesh &mesh = *static_cast(object.data); @@ -783,12 +745,12 @@ static void sculpt_mask_by_color_contiguous_mesh(const Depsgraph &depsgraph, flood.execute(object, vert_to_face_map, [&](int /*from_v*/, int to_v) { const float4 current_color = float4(colors[to_v]); - float new_vertex_mask = sculpt_mask_by_color_delta_get( - current_color, active_color, threshold, invert); + float new_vertex_mask = color_delta_get( + current_color.xyz(), active_color.xyz(), threshold, invert); new_mask[to_v] = new_vertex_mask; - float len = len_v3v3(current_color, active_color); - len = len / M_SQRT3; + float len = math::distance(current_color.xyz(), active_color.xyz()); + len = len / math::numbers::sqrt3_v; return len <= threshold; }); @@ -796,20 +758,19 @@ static void sculpt_mask_by_color_contiguous_mesh(const Depsgraph &depsgraph, const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory); update_mask_mesh( - depsgraph, object, node_mask, [&](MutableSpan node_mask, const Span verts) { + depsgraph, object, node_mask, [&](MutableSpan node_masks, const Span verts) { for (const int i : verts.index_range()) { - node_mask[i] = sculpt_mask_by_color_final_mask_get( - node_mask[i], new_mask[verts[i]], invert, preserve_mask); + node_masks[i] = final_mask_get(node_masks[i], new_mask[verts[i]], invert, preserve_mask); } }); } -static void sculpt_mask_by_color_full_mesh(const Depsgraph &depsgraph, - Object &object, - const int vert, - const float threshold, - const bool invert, - const bool preserve_mask) +static void mask_by_color_full_mesh(const Depsgraph &depsgraph, + Object &object, + const int vert, + const float threshold, + const bool invert, + const bool preserve_mask) { const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object); const Mesh &mesh = *static_cast(object.data); @@ -822,18 +783,18 @@ static void sculpt_mask_by_color_full_mesh(const Depsgraph &depsgraph, const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory); update_mask_mesh( - depsgraph, object, node_mask, [&](MutableSpan node_mask, const Span verts) { + depsgraph, object, node_mask, [&](MutableSpan node_masks, const Span verts) { for (const int i : verts.index_range()) { - const float current_mask = node_mask[i]; - const float new_mask = sculpt_mask_by_color_delta_get( - active_color, colors[verts[i]], threshold, invert); - node_mask[i] = sculpt_mask_by_color_final_mask_get( - current_mask, new_mask, invert, preserve_mask); + const float4 current_color = float4(colors[verts[i]]); + const float current_mask = node_masks[i]; + const float new_mask = color_delta_get( + active_color.xyz(), current_color.xyz(), threshold, invert); + node_masks[i] = final_mask_get(current_mask, new_mask, invert, preserve_mask); } }); } -static int sculpt_mask_by_color_invoke(bContext *C, wmOperator *op, const wmEvent *event) +static int mask_by_color_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); Object &ob = *CTX_data_active_object(C); @@ -873,11 +834,10 @@ static int sculpt_mask_by_color_invoke(bContext *C, wmOperator *op, const wmEven const int active_vert = std::get(ss.active_vert()); if (RNA_boolean_get(op->ptr, "contiguous")) { - sculpt_mask_by_color_contiguous_mesh( - *depsgraph, ob, active_vert, threshold, invert, preserve_mask); + mask_by_color_contiguous_mesh(*depsgraph, ob, active_vert, threshold, invert, preserve_mask); } else { - sculpt_mask_by_color_full_mesh(*depsgraph, ob, active_vert, threshold, invert, preserve_mask); + mask_by_color_full_mesh(*depsgraph, ob, active_vert, threshold, invert, preserve_mask); } undo::push_end(ob); @@ -894,7 +854,7 @@ static void SCULPT_OT_mask_by_color(wmOperatorType *ot) ot->idname = "SCULPT_OT_mask_by_color"; ot->description = "Creates a mask based on the active color attribute"; - ot->invoke = sculpt_mask_by_color_invoke; + ot->invoke = mask_by_color_invoke; ot->poll = SCULPT_mode_poll; ot->flag = OPTYPE_REGISTER; @@ -921,19 +881,21 @@ static void SCULPT_OT_mask_by_color(wmOperatorType *ot) 1.0f); } -enum CavityBakeMixMode { - AUTOMASK_BAKE_MIX, - AUTOMASK_BAKE_MULTIPLY, - AUTOMASK_BAKE_DIVIDE, - AUTOMASK_BAKE_ADD, - AUTOMASK_BAKE_SUBTRACT, +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Mask from Cavity + * \{ */ + +enum class ApplyMaskMode : int8_t { + Mix, + Multiply, + Divide, + Add, + Subtract, }; -enum CavityBakeSettingsSource { - AUTOMASK_SETTINGS_OPERATOR, - AUTOMASK_SETTINGS_SCENE, - AUTOMASK_SETTINGS_BRUSH -}; +enum class MaskSettingsSource : int8_t { Operator, Scene, Brush }; struct LocalData { Vector mask; @@ -941,29 +903,29 @@ struct LocalData { Vector new_mask; }; -static void calc_new_masks(const CavityBakeMixMode mode, +static void calc_new_masks(const ApplyMaskMode mode, const Span node_mask, const MutableSpan new_mask) { switch (mode) { - case AUTOMASK_BAKE_MIX: + case ApplyMaskMode::Mix: break; - case AUTOMASK_BAKE_MULTIPLY: + case ApplyMaskMode::Multiply: for (const int i : node_mask.index_range()) { new_mask[i] = node_mask[i] * new_mask[i]; } break; - case AUTOMASK_BAKE_DIVIDE: + case ApplyMaskMode::Divide: for (const int i : node_mask.index_range()) { new_mask[i] = new_mask[i] > 0.00001f ? node_mask[i] / new_mask[i] : 0.0f; } break; - case AUTOMASK_BAKE_ADD: + case ApplyMaskMode::Add: for (const int i : node_mask.index_range()) { new_mask[i] = node_mask[i] + new_mask[i]; } break; - case AUTOMASK_BAKE_SUBTRACT: + case ApplyMaskMode::Subtract: for (const int i : node_mask.index_range()) { new_mask[i] = node_mask[i] - new_mask[i]; } @@ -972,14 +934,14 @@ static void calc_new_masks(const CavityBakeMixMode mode, mask::clamp_mask(new_mask); } -static void bake_mask_mesh(const Depsgraph &depsgraph, - const Object &object, - const auto_mask::Cache &automasking, - const CavityBakeMixMode mode, - const float factor, - const bke::pbvh::MeshNode &node, - LocalData &tls, - const MutableSpan mask) +static void apply_mask_mesh(const Depsgraph &depsgraph, + const Object &object, + const auto_mask::Cache &automasking, + const ApplyMaskMode mode, + const float factor, + const bke::pbvh::MeshNode &node, + LocalData &tls, + const MutableSpan mask) { const Mesh &mesh = *static_cast(object.data); const Span verts = node.verts(); @@ -1004,13 +966,13 @@ static void bake_mask_mesh(const Depsgraph &depsgraph, scatter_data_mesh(node_mask.as_span(), verts, mask); } -static void bake_mask_grids(const Depsgraph &depsgraph, - Object &object, - const auto_mask::Cache &automasking, - const CavityBakeMixMode mode, - const float factor, - const bke::pbvh::GridsNode &node, - LocalData &tls) +static void apply_mask_grids(const Depsgraph &depsgraph, + Object &object, + const auto_mask::Cache &automasking, + const ApplyMaskMode mode, + const float factor, + const bke::pbvh::GridsNode &node, + LocalData &tls) { SculptSession &ss = *object.sculpt; SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; @@ -1039,13 +1001,13 @@ static void bake_mask_grids(const Depsgraph &depsgraph, scatter_mask_grids(node_mask.as_span(), subdiv_ccg, grids); } -static void bake_mask_bmesh(const Depsgraph &depsgraph, - Object &object, - const auto_mask::Cache &automasking, - const CavityBakeMixMode mode, - const float factor, - bke::pbvh::BMeshNode &node, - LocalData &tls) +static void apply_mask_bmesh(const Depsgraph &depsgraph, + Object &object, + const auto_mask::Cache &automasking, + const ApplyMaskMode mode, + const float factor, + bke::pbvh::BMeshNode &node, + LocalData &tls) { const SculptSession &ss = *object.sculpt; const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&node); @@ -1070,7 +1032,7 @@ static void bake_mask_bmesh(const Depsgraph &depsgraph, scatter_mask_bmesh(node_mask.as_span(), *ss.bm, verts); } -static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op) +static int mask_from_cavity_exec(bContext *C, wmOperator *op) { Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); Object &ob = *CTX_data_active_object(C); @@ -1091,8 +1053,8 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op) undo::push_begin(ob, op); - CavityBakeMixMode mode = CavityBakeMixMode(RNA_enum_get(op->ptr, "mix_mode")); - float factor = RNA_float_get(op->ptr, "mix_factor"); + const ApplyMaskMode mode = ApplyMaskMode(RNA_enum_get(op->ptr, "mix_mode")); + const float factor = RNA_float_get(op->ptr, "mix_factor"); bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(ob); @@ -1100,67 +1062,68 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op) const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory); /* Set up automasking settings. */ - Sculpt sd2 = sd; + Sculpt scene_copy = sd; - CavityBakeSettingsSource src = (CavityBakeSettingsSource)RNA_enum_get(op->ptr, - "settings_source"); + MaskSettingsSource src = (MaskSettingsSource)RNA_enum_get(op->ptr, "settings_source"); switch (src) { - case AUTOMASK_SETTINGS_OPERATOR: + case MaskSettingsSource::Operator: if (RNA_boolean_get(op->ptr, "invert")) { - sd2.automasking_flags = BRUSH_AUTOMASKING_CAVITY_INVERTED; + scene_copy.automasking_flags = BRUSH_AUTOMASKING_CAVITY_INVERTED; } else { - sd2.automasking_flags = BRUSH_AUTOMASKING_CAVITY_NORMAL; + scene_copy.automasking_flags = BRUSH_AUTOMASKING_CAVITY_NORMAL; } if (RNA_boolean_get(op->ptr, "use_curve")) { - sd2.automasking_flags |= BRUSH_AUTOMASKING_CAVITY_USE_CURVE; + scene_copy.automasking_flags |= BRUSH_AUTOMASKING_CAVITY_USE_CURVE; } - sd2.automasking_cavity_blur_steps = RNA_int_get(op->ptr, "blur_steps"); - sd2.automasking_cavity_factor = RNA_float_get(op->ptr, "factor"); + scene_copy.automasking_cavity_blur_steps = RNA_int_get(op->ptr, "blur_steps"); + scene_copy.automasking_cavity_factor = RNA_float_get(op->ptr, "factor"); - sd2.automasking_cavity_curve = sd.automasking_cavity_curve_op; + scene_copy.automasking_cavity_curve = sd.automasking_cavity_curve_op; break; - case AUTOMASK_SETTINGS_BRUSH: + case MaskSettingsSource::Brush: if (brush) { - sd2.automasking_flags = brush->automasking_flags; - sd2.automasking_cavity_factor = brush->automasking_cavity_factor; - sd2.automasking_cavity_curve = brush->automasking_cavity_curve; - sd2.automasking_cavity_blur_steps = brush->automasking_cavity_blur_steps; + scene_copy.automasking_flags = brush->automasking_flags; + scene_copy.automasking_cavity_factor = brush->automasking_cavity_factor; + scene_copy.automasking_cavity_curve = brush->automasking_cavity_curve; + scene_copy.automasking_cavity_blur_steps = brush->automasking_cavity_blur_steps; /* Ensure only cavity masking is enabled. */ - sd2.automasking_flags &= BRUSH_AUTOMASKING_CAVITY_ALL | BRUSH_AUTOMASKING_CAVITY_USE_CURVE; + scene_copy.automasking_flags &= BRUSH_AUTOMASKING_CAVITY_ALL | + BRUSH_AUTOMASKING_CAVITY_USE_CURVE; } else { - sd2.automasking_flags = 0; + scene_copy.automasking_flags = 0; BKE_report(op->reports, RPT_WARNING, "No active brush"); return OPERATOR_CANCELLED; } break; - case AUTOMASK_SETTINGS_SCENE: + case MaskSettingsSource::Scene: /* Ensure only cavity masking is enabled. */ - sd2.automasking_flags &= BRUSH_AUTOMASKING_CAVITY_ALL | BRUSH_AUTOMASKING_CAVITY_USE_CURVE; + scene_copy.automasking_flags &= BRUSH_AUTOMASKING_CAVITY_ALL | + BRUSH_AUTOMASKING_CAVITY_USE_CURVE; break; } /* Ensure cavity mask is actually enabled. */ - if (!(sd2.automasking_flags & BRUSH_AUTOMASKING_CAVITY_ALL)) { - sd2.automasking_flags |= BRUSH_AUTOMASKING_CAVITY_NORMAL; + if (!(scene_copy.automasking_flags & BRUSH_AUTOMASKING_CAVITY_ALL)) { + scene_copy.automasking_flags |= BRUSH_AUTOMASKING_CAVITY_NORMAL; } /* Create copy of brush with cleared automasking settings. */ - Brush brush2 = dna::shallow_copy(*brush); + Brush brush_copy = dna::shallow_copy(*brush); /* Set a brush type that doesn't change topology so automasking isn't "disabled". */ - brush2.sculpt_brush_type = SCULPT_BRUSH_TYPE_SMOOTH; - brush2.automasking_flags = 0; - brush2.automasking_boundary_edges_propagation_steps = 1; - brush2.automasking_cavity_curve = sd2.automasking_cavity_curve; + brush_copy.sculpt_brush_type = SCULPT_BRUSH_TYPE_SMOOTH; + brush_copy.automasking_flags = 0; + brush_copy.automasking_boundary_edges_propagation_steps = 1; + brush_copy.automasking_cavity_curve = scene_copy.automasking_cavity_curve; std::unique_ptr automasking = auto_mask::cache_init( - *depsgraph, sd2, &brush2, ob); + *depsgraph, scene_copy, &brush_copy, ob); undo::push_nodes(*depsgraph, ob, node_mask, undo::Type::Mask); @@ -1171,14 +1134,11 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op) bke::MutableAttributeAccessor attributes = mesh.attributes_for_write(); bke::SpanAttributeWriter mask = attributes.lookup_or_add_for_write_span( ".sculpt_mask", bke::AttrDomain::Point); - if (!mask) { - return OPERATOR_CANCELLED; - } MutableSpan nodes = pbvh.nodes(); threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); node_mask.slice(range).foreach_index([&](const int i) { - bake_mask_mesh(*depsgraph, ob, *automasking, mode, factor, nodes[i], tls, mask.span); + apply_mask_mesh(*depsgraph, ob, *automasking, mode, factor, nodes[i], tls, mask.span); bke::pbvh::node_update_mask_mesh(mask.span, nodes[i]); }); }); @@ -1192,7 +1152,7 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op) threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); node_mask.slice(range).foreach_index([&](const int i) { - bake_mask_grids(*depsgraph, ob, *automasking, mode, factor, nodes[i], tls); + apply_mask_grids(*depsgraph, ob, *automasking, mode, factor, nodes[i], tls); bke::pbvh::node_update_mask_grids(key, masks, nodes[i]); }); }); @@ -1205,7 +1165,7 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op) threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); node_mask.slice(range).foreach_index([&](const int i) { - bake_mask_bmesh(*depsgraph, ob, *automasking, mode, factor, nodes[i], tls); + apply_mask_bmesh(*depsgraph, ob, *automasking, mode, factor, nodes[i], tls); bke::pbvh::node_update_mask_bmesh(mask_offset, nodes[i]); }); }); @@ -1222,7 +1182,7 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static void cavity_bake_ui(bContext *C, wmOperator *op) +static void mask_from_cavity_ui(bContext *C, wmOperator *op) { uiLayout *layout = op->layout; Scene *scene = CTX_data_scene(C); @@ -1230,15 +1190,14 @@ static void cavity_bake_ui(bContext *C, wmOperator *op) uiLayoutSetPropSep(layout, true); uiLayoutSetPropDecorate(layout, false); - CavityBakeSettingsSource source = (CavityBakeSettingsSource)RNA_enum_get(op->ptr, - "settings_source"); + MaskSettingsSource source = (MaskSettingsSource)RNA_enum_get(op->ptr, "settings_source"); if (!sd) { - source = AUTOMASK_SETTINGS_OPERATOR; + source = MaskSettingsSource::Operator; } switch (source) { - case AUTOMASK_SETTINGS_OPERATOR: { + case MaskSettingsSource::Operator: { uiItemR(layout, op->ptr, "mix_mode", UI_ITEM_NONE, nullptr, ICON_NONE); uiItemR(layout, op->ptr, "mix_factor", UI_ITEM_NONE, nullptr, ICON_NONE); uiItemR(layout, op->ptr, "settings_source", UI_ITEM_NONE, nullptr, ICON_NONE); @@ -1254,8 +1213,8 @@ static void cavity_bake_ui(bContext *C, wmOperator *op) } break; } - case AUTOMASK_SETTINGS_BRUSH: - case AUTOMASK_SETTINGS_SCENE: + case MaskSettingsSource::Brush: + case MaskSettingsSource::Scene: uiItemR(layout, op->ptr, "mix_mode", UI_ITEM_NONE, nullptr, ICON_NONE); uiItemR(layout, op->ptr, "mix_factor", UI_ITEM_NONE, nullptr, ICON_NONE); uiItemR(layout, op->ptr, "settings_source", UI_ITEM_NONE, nullptr, ICON_NONE); @@ -1269,39 +1228,39 @@ static void SCULPT_OT_mask_from_cavity(wmOperatorType *ot) ot->name = "Mask From Cavity"; ot->idname = "SCULPT_OT_mask_from_cavity"; ot->description = "Creates a mask based on the curvature of the surface"; - ot->ui = cavity_bake_ui; + ot->ui = mask_from_cavity_ui; static EnumPropertyItem mix_modes[] = { - {AUTOMASK_BAKE_MIX, "MIX", ICON_NONE, "Mix", ""}, - {AUTOMASK_BAKE_MULTIPLY, "MULTIPLY", ICON_NONE, "Multiply", ""}, - {AUTOMASK_BAKE_DIVIDE, "DIVIDE", ICON_NONE, "Divide", ""}, - {AUTOMASK_BAKE_ADD, "ADD", ICON_NONE, "Add", ""}, - {AUTOMASK_BAKE_SUBTRACT, "SUBTRACT", ICON_NONE, "Subtract", ""}, + {int(ApplyMaskMode::Mix), "MIX", ICON_NONE, "Mix", ""}, + {int(ApplyMaskMode::Multiply), "MULTIPLY", ICON_NONE, "Multiply", ""}, + {int(ApplyMaskMode::Divide), "DIVIDE", ICON_NONE, "Divide", ""}, + {int(ApplyMaskMode::Add), "ADD", ICON_NONE, "Add", ""}, + {int(ApplyMaskMode::Subtract), "SUBTRACT", ICON_NONE, "Subtract", ""}, {0, nullptr, 0, nullptr, nullptr}, }; - ot->exec = sculpt_bake_cavity_exec; + ot->exec = mask_from_cavity_exec; ot->poll = SCULPT_mode_poll; ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_enum(ot->srna, "mix_mode", mix_modes, AUTOMASK_BAKE_MIX, "Mode", "Mix mode"); + RNA_def_enum(ot->srna, "mix_mode", mix_modes, int(ApplyMaskMode::Mix), "Mode", "Mix mode"); RNA_def_float(ot->srna, "mix_factor", 1.0f, 0.0f, 5.0f, "Mix Factor", "", 0.0f, 1.0f); static EnumPropertyItem settings_sources[] = { - {AUTOMASK_SETTINGS_OPERATOR, + {int(MaskSettingsSource::Operator), "OPERATOR", ICON_NONE, "Operator", "Use settings from operator properties"}, - {AUTOMASK_SETTINGS_BRUSH, "BRUSH", ICON_NONE, "Brush", "Use settings from brush"}, - {AUTOMASK_SETTINGS_SCENE, "SCENE", ICON_NONE, "Scene", "Use settings from scene"}, + {int(MaskSettingsSource::Brush), "BRUSH", ICON_NONE, "Brush", "Use settings from brush"}, + {int(MaskSettingsSource::Scene), "SCENE", ICON_NONE, "Scene", "Use settings from scene"}, {0, nullptr, 0, nullptr, nullptr}}; RNA_def_enum(ot->srna, "settings_source", settings_sources, - AUTOMASK_SETTINGS_OPERATOR, + int(MaskSettingsSource::Operator), "Settings", "Use settings from here"); @@ -1328,6 +1287,8 @@ static void SCULPT_OT_mask_from_cavity(wmOperatorType *ot) RNA_def_boolean(ot->srna, "invert", false, "Cavity (Inverted)", ""); } +/** \} */ + } // namespace mask void operatortypes_sculpt()