From 1eb39a868928735b8dcc63f7825546b4ff8f42b3 Mon Sep 17 00:00:00 2001 From: Falk David Date: Fri, 24 Jan 2025 10:20:03 +0100 Subject: [PATCH] Grease Pencil: Sculpt Mode Auto-Masking option This implements all the auto masking options in sculpt mode. * Stroke: Only affects strokes that are initially under the cursor. * Layer: Only affect strokes in the same layer as the initial strokes under the cursor. * Material: Only affect strokes with the same material as the initial strokes under the cursor. * Active Layer: Only affect strokes in the active layer. * Active Material: Only affect strokes that use the active material. The `Active Layer` toggle in the toolbar has been moved to this panel. Resolves #130022. Pull Request: https://projects.blender.org/blender/blender/pulls/132986 --- .../keyconfig/keymap_data/blender_default.py | 4 + scripts/startup/bl_ui/space_view3d.py | 8 +- .../sculpt_paint/grease_pencil_intern.hh | 44 ++- .../grease_pencil_paint_common.cc | 345 ++++++++++++++---- .../grease_pencil_sculpt_clone.cc | 7 +- .../sculpt_paint/grease_pencil_sculpt_grab.cc | 13 +- .../grease_pencil_sculpt_pinch.cc | 20 +- .../sculpt_paint/grease_pencil_sculpt_push.cc | 21 +- .../grease_pencil_sculpt_randomize.cc | 27 +- .../grease_pencil_sculpt_smooth.cc | 162 ++++---- .../grease_pencil_sculpt_strength.cc | 37 +- .../grease_pencil_sculpt_thickness.cc | 43 +-- .../grease_pencil_sculpt_twist.cc | 21 +- .../grease_pencil_vertex_average.cc | 14 +- .../sculpt_paint/grease_pencil_vertex_blur.cc | 8 +- .../grease_pencil_vertex_paint.cc | 8 +- .../grease_pencil_vertex_replace.cc | 8 +- .../grease_pencil_vertex_smear.cc | 10 +- 18 files changed, 499 insertions(+), 301 deletions(-) diff --git a/scripts/presets/keyconfig/keymap_data/blender_default.py b/scripts/presets/keyconfig/keymap_data/blender_default.py index 3f1e42fff61..f6f3abd8ac2 100644 --- a/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -4077,6 +4077,10 @@ def km_grease_pencil_sculpt_mode(params): # Active layer op_menu("GREASE_PENCIL_MT_layer_active", {"type": 'Y', "value": 'PRESS'}), + # Auto-masking menu. + op_menu_pie("VIEW3D_MT_grease_pencil_sculpt_automasking_pie", { + "type": 'A', "value": 'PRESS', "shift": True, "alt": True}), + *_template_paint_radial_control("gpencil_sculpt_paint"), *_template_asset_shelf_popup("VIEW3D_AST_brush_gpencil_sculpt", params.spacebar_action), *_template_items_context_panel("VIEW3D_PT_greasepencil_sculpt_context_menu", params.context_menu_event), diff --git a/scripts/startup/bl_ui/space_view3d.py b/scripts/startup/bl_ui/space_view3d.py index 0c1f183d068..7fd009b2f50 100644 --- a/scripts/startup/bl_ui/space_view3d.py +++ b/scripts/startup/bl_ui/space_view3d.py @@ -435,8 +435,6 @@ class _draw_tool_settings_context_mode: # Brush falloff layout.popover("VIEW3D_PT_tools_brush_falloff") - # Active layer only switch - layout.prop(brush.gpencil_settings, "use_active_layer_only") return True @staticmethod @@ -954,6 +952,12 @@ class VIEW3D_HT_header(Header): panel="VIEW3D_PT_grease_pencil_guide", text="Guides", ) + if object_mode == 'SCULPT_GREASE_PENCIL': + layout.popover( + panel="VIEW3D_PT_grease_pencil_sculpt_automasking", + text="", + icon=VIEW3D_HT_header._grease_pencil_sculpt_automasking_icon(tool_settings.gpencil_sculpt), + ) elif object_mode == 'SCULPT': # If the active tool supports it, show the canvas selector popover. diff --git a/source/blender/editors/sculpt_paint/grease_pencil_intern.hh b/source/blender/editors/sculpt_paint/grease_pencil_intern.hh index ca588ce3b6e..cc842778792 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_intern.hh +++ b/source/blender/editors/sculpt_paint/grease_pencil_intern.hh @@ -47,7 +47,9 @@ class GreasePencilStrokeOperation : public PaintModeData { namespace greasepencil { /* Get list of drawings the tool should be operating on. */ -Vector get_drawings_for_painting(const bContext &C); +Vector get_drawings_for_stroke_operation(const bContext &C); +Vector get_drawings_with_masking_for_stroke_operation( + const bContext &C); /* Get the brush radius accounting for pen pressure. */ float brush_radius(const Scene &scene, const Brush &brush, float pressure); @@ -118,15 +120,15 @@ struct GreasePencilStrokeParams { }; /* Point index mask for a drawing based on selection tool settings. */ -IndexMask point_selection_mask(const GreasePencilStrokeParams ¶ms, - const bool use_masking, - IndexMaskMemory &memory); -IndexMask stroke_selection_mask(const GreasePencilStrokeParams ¶ms, - const bool use_masking, - IndexMaskMemory &memory); -IndexMask fill_selection_mask(const GreasePencilStrokeParams ¶ms, - const bool use_masking, - IndexMaskMemory &memory); +IndexMask point_mask_for_stroke_operation(const GreasePencilStrokeParams ¶ms, + bool use_selection_masking, + IndexMaskMemory &memory); +IndexMask curve_mask_for_stroke_operation(const GreasePencilStrokeParams ¶ms, + bool use_selection_masking, + IndexMaskMemory &memory); +IndexMask fill_mask_for_stroke_operation(const GreasePencilStrokeParams ¶ms, + bool use_selection_masking, + IndexMaskMemory &memory); bke::crazyspace::GeometryDeformation get_drawing_deformation( const GreasePencilStrokeParams ¶ms); @@ -170,6 +172,13 @@ class GreasePencilStrokeOperationCommon : public GreasePencilStrokeOperation { /** Previous mouse position for computing the direction. */ float2 prev_mouse_position; + /* When auto-masking is used, this contains the index mask of the elements that are affected. */ + struct AutoMaskingInfo { + IndexMask point_mask; + IndexMaskMemory memory; + }; + Array auto_masking_info_per_drawing; + GreasePencilStrokeOperationCommon() {} GreasePencilStrokeOperationCommon(const BrushStrokeMode stroke_mode) : stroke_mode(stroke_mode) { @@ -179,18 +188,25 @@ class GreasePencilStrokeOperationCommon : public GreasePencilStrokeOperation { float2 mouse_delta(const InputSample &input_sample) const; void init_stroke(const bContext &C, const InputSample &start_sample); + void init_auto_masking(const bContext &C, const InputSample &start_sample); void stroke_extended(const InputSample &extension_sample); + void foreach_editable_drawing_with_automask( + const bContext &C, + FunctionRef fn) const; + void foreach_editable_drawing_with_automask( + const bContext &C, + FunctionRef fn) const; + + /** Used in vertex paint mode. */ void foreach_editable_drawing( const bContext &C, FunctionRef fn) const; void foreach_editable_drawing( const bContext &C, GrainSize grain_size, FunctionRef fn) const; - void foreach_editable_drawing( - const bContext &C, - FunctionRef fn) const; }; /* Operations */ diff --git a/source/blender/editors/sculpt_paint/grease_pencil_paint_common.cc b/source/blender/editors/sculpt_paint/grease_pencil_paint_common.cc index 35a9bc4958c..6341094ca65 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_paint_common.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_paint_common.cc @@ -28,19 +28,32 @@ namespace blender::ed::sculpt_paint::greasepencil { -Vector get_drawings_for_painting(const bContext &C) +Vector get_drawings_for_stroke_operation(const bContext &C) { using namespace blender::bke::greasepencil; const Scene &scene = *CTX_data_scene(&C); Object &ob_orig = *CTX_data_active_object(&C); GreasePencil &grease_pencil = *static_cast(ob_orig.data); - Paint &paint = *BKE_paint_get_active_from_context(&C); - const Brush &brush = *BKE_paint_brush(&paint); - const bool active_layer_only = ((brush.gpencil_settings->flag & GP_BRUSH_ACTIVE_LAYER_ONLY) != - 0); - if (active_layer_only) { + /* Apply to all editable drawings. */ + return ed::greasepencil::retrieve_editable_drawings_with_falloff(scene, grease_pencil); +} + +Vector get_drawings_with_masking_for_stroke_operation( + const bContext &C) +{ + using namespace blender::bke::greasepencil; + + const Scene &scene = *CTX_data_scene(&C); + const ToolSettings &ts = *CTX_data_tool_settings(&C); + Object &ob_orig = *CTX_data_active_object(&C); + GreasePencil &grease_pencil = *static_cast(ob_orig.data); + + const bool active_layer_masking = (ts.gp_sculpt.flag & + GP_SCULPT_SETT_FLAG_AUTOMASK_LAYER_ACTIVE) != 0; + + if (active_layer_masking) { /* Apply only to the drawing at the current frame of the active layer. */ if (!grease_pencil.has_active_layer()) { return {}; @@ -293,35 +306,33 @@ GreasePencilStrokeParams GreasePencilStrokeParams::from_context( drawing}; } -IndexMask point_selection_mask(const GreasePencilStrokeParams ¶ms, - const bool use_masking, - IndexMaskMemory &memory) +IndexMask point_mask_for_stroke_operation(const GreasePencilStrokeParams ¶ms, + const bool use_selection_masking, + IndexMaskMemory &memory) { - - return use_masking ? ed::greasepencil::retrieve_editable_and_selected_points( - params.ob_orig, params.drawing, params.layer_index, memory) : - ed::greasepencil::retrieve_editable_points( - params.ob_orig, params.drawing, params.layer_index, memory); + return use_selection_masking ? ed::greasepencil::retrieve_editable_and_selected_points( + params.ob_orig, params.drawing, params.layer_index, memory) : + ed::greasepencil::retrieve_editable_points( + params.ob_orig, params.drawing, params.layer_index, memory); } -IndexMask stroke_selection_mask(const GreasePencilStrokeParams ¶ms, - const bool use_masking, - IndexMaskMemory &memory) +IndexMask curve_mask_for_stroke_operation(const GreasePencilStrokeParams ¶ms, + const bool use_selection_masking, + IndexMaskMemory &memory) { - - return use_masking ? ed::greasepencil::retrieve_editable_and_selected_strokes( - params.ob_orig, params.drawing, params.layer_index, memory) : - ed::greasepencil::retrieve_editable_strokes( - params.ob_orig, params.drawing, params.layer_index, memory); + return use_selection_masking ? ed::greasepencil::retrieve_editable_and_selected_strokes( + params.ob_orig, params.drawing, params.layer_index, memory) : + ed::greasepencil::retrieve_editable_strokes( + params.ob_orig, params.drawing, params.layer_index, memory); } -IndexMask fill_selection_mask(const GreasePencilStrokeParams ¶ms, - const bool use_masking, - IndexMaskMemory &memory) +IndexMask fill_mask_for_stroke_operation(const GreasePencilStrokeParams ¶ms, + const bool use_selection_masking, + IndexMaskMemory &memory) { - return use_masking ? ed::greasepencil::retrieve_editable_and_selected_fill_strokes( - params.ob_orig, params.drawing, params.layer_index, memory) : - params.drawing.strokes().curves_range(); + return use_selection_masking ? ed::greasepencil::retrieve_editable_and_selected_fill_strokes( + params.ob_orig, params.drawing, params.layer_index, memory) : + params.drawing.strokes().curves_range(); } bke::crazyspace::GeometryDeformation get_drawing_deformation( @@ -395,6 +406,92 @@ float2 GreasePencilStrokeOperationCommon::mouse_delta(const InputSample &input_s return input_sample.mouse_position - this->prev_mouse_position; } +void GreasePencilStrokeOperationCommon::foreach_editable_drawing_with_automask( + const bContext &C, + FunctionRef fn) + const +{ + using namespace blender::bke::greasepencil; + + const Scene &scene = *CTX_data_scene(&C); + Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(&C); + ARegion ®ion = *CTX_wm_region(&C); + RegionView3D &rv3d = *CTX_wm_region_view3d(&C); + Object &object = *CTX_data_active_object(&C); + GreasePencil &grease_pencil = *static_cast(object.data); + + std::atomic changed = false; + const Vector drawings = get_drawings_with_masking_for_stroke_operation(C); + for (const int64_t i : drawings.index_range()) { + const MutableDrawingInfo &info = drawings[i]; + const AutoMaskingInfo &auto_mask_info = this->auto_masking_info_per_drawing[i]; + GreasePencilStrokeParams params = GreasePencilStrokeParams::from_context( + scene, + depsgraph, + region, + rv3d, + object, + info.layer_index, + info.frame_number, + info.multi_frame_falloff, + info.drawing); + + if (fn(params, auto_mask_info.point_mask)) { + changed = true; + } + } + + if (changed) { + DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(&C, NC_GEOM | ND_DATA, &grease_pencil); + } +} + +void GreasePencilStrokeOperationCommon::foreach_editable_drawing_with_automask( + const bContext &C, + FunctionRef fn) const +{ + using namespace blender::bke::greasepencil; + + const Scene &scene = *CTX_data_scene(&C); + Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(&C); + ARegion ®ion = *CTX_wm_region(&C); + RegionView3D &rv3d = *CTX_wm_region_view3d(&C); + Object &object = *CTX_data_active_object(&C); + Object &object_eval = *DEG_get_evaluated_object(&depsgraph, &object); + GreasePencil &grease_pencil = *static_cast(object.data); + + std::atomic changed = false; + const Vector drawings = get_drawings_with_masking_for_stroke_operation(C); + threading::parallel_for_each(drawings.index_range(), [&](const int i) { + const MutableDrawingInfo &info = drawings[i]; + const Layer &layer = grease_pencil.layer(info.layer_index); + const AutoMaskingInfo &auto_mask_info = this->auto_masking_info_per_drawing[i]; + const GreasePencilStrokeParams params = GreasePencilStrokeParams::from_context( + scene, + depsgraph, + region, + rv3d, + object, + info.layer_index, + info.frame_number, + info.multi_frame_falloff, + info.drawing); + + const DeltaProjectionFunc projection_fn = get_screen_projection_fn(params, object_eval, layer); + if (fn(params, auto_mask_info.point_mask, projection_fn)) { + changed = true; + } + }); + + if (changed) { + DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(&C, NC_GEOM | ND_DATA, &grease_pencil); + } +} + void GreasePencilStrokeOperationCommon::foreach_editable_drawing( const bContext &C, FunctionRef fn) const { @@ -407,8 +504,8 @@ void GreasePencilStrokeOperationCommon::foreach_editable_drawing( Object &object = *CTX_data_active_object(&C); GreasePencil &grease_pencil = *static_cast(object.data); - std::atomic changed = false; - const Vector drawings = get_drawings_for_painting(C); + bool changed = false; + const Vector drawings = get_drawings_for_stroke_operation(C); for (const int64_t i : drawings.index_range()) { const MutableDrawingInfo &info = drawings[i]; GreasePencilStrokeParams params = GreasePencilStrokeParams::from_context( @@ -447,7 +544,7 @@ void GreasePencilStrokeOperationCommon::foreach_editable_drawing( GreasePencil &grease_pencil = *static_cast(object.data); std::atomic changed = false; - const Vector drawings = get_drawings_for_painting(C); + const Vector drawings = get_drawings_for_stroke_operation(C); threading::parallel_for(drawings.index_range(), grain_size.value, [&](const IndexRange range) { for (const int64_t i : range) { const MutableDrawingInfo &info = drawings[i]; @@ -473,48 +570,6 @@ void GreasePencilStrokeOperationCommon::foreach_editable_drawing( } } -void GreasePencilStrokeOperationCommon::foreach_editable_drawing( - const bContext &C, - FunctionRef fn) const -{ - using namespace blender::bke::greasepencil; - - const Scene &scene = *CTX_data_scene(&C); - Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(&C); - ARegion ®ion = *CTX_wm_region(&C); - RegionView3D &rv3d = *CTX_wm_region_view3d(&C); - Object &object = *CTX_data_active_object(&C); - Object &object_eval = *DEG_get_evaluated_object(&depsgraph, &object); - GreasePencil &grease_pencil = *static_cast(object.data); - - std::atomic changed = false; - const Vector drawings = get_drawings_for_painting(C); - threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { - const Layer &layer = grease_pencil.layer(info.layer_index); - - const GreasePencilStrokeParams params = GreasePencilStrokeParams::from_context( - scene, - depsgraph, - region, - rv3d, - object, - info.layer_index, - info.frame_number, - info.multi_frame_falloff, - info.drawing); - const DeltaProjectionFunc projection_fn = get_screen_projection_fn(params, object_eval, layer); - if (fn(params, projection_fn)) { - changed = true; - } - }); - - if (changed) { - DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(&C, NC_GEOM | ND_DATA, &grease_pencil); - } -} - void GreasePencilStrokeOperationCommon::init_stroke(const bContext &C, const InputSample &start_sample) { @@ -527,6 +582,150 @@ void GreasePencilStrokeOperationCommon::init_stroke(const bContext &C, this->prev_mouse_position = start_sample.mouse_position; } +void GreasePencilStrokeOperationCommon::init_auto_masking(const bContext &C, + const InputSample &start_sample) +{ + const Scene &scene = *CTX_data_scene(&C); + ARegion ®ion = *CTX_wm_region(&C); + RegionView3D &rv3d = *CTX_wm_region_view3d(&C); + Object &object = *CTX_data_active_object(&C); + Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(&C); + Paint &paint = *BKE_paint_get_active_from_context(&C); + const Brush &brush = *BKE_paint_brush(&paint); + + const eGP_Sculpt_SelectMaskFlag sculpt_selection_flag = eGP_Sculpt_SelectMaskFlag( + scene.toolsettings->gpencil_selectmode_sculpt); + const bool use_sculpt_selection_masking = (sculpt_selection_flag & + (GP_SCULPT_MASK_SELECTMODE_POINT | + GP_SCULPT_MASK_SELECTMODE_STROKE | + GP_SCULPT_MASK_SELECTMODE_SEGMENT)) != 0; + + const eGP_Sculpt_SettingsFlag sculpt_settings_flag = eGP_Sculpt_SettingsFlag( + scene.toolsettings->gp_sculpt.flag); + const bool use_auto_mask_stroke = (sculpt_settings_flag & GP_SCULPT_SETT_FLAG_AUTOMASK_STROKE); + const bool use_auto_mask_layer = (sculpt_settings_flag & + GP_SCULPT_SETT_FLAG_AUTOMASK_LAYER_STROKE); + const bool use_auto_mask_material = (sculpt_settings_flag & + GP_SCULPT_SETT_FLAG_AUTOMASK_MATERIAL_STROKE); + const bool use_auto_mask_active_material = (sculpt_settings_flag & + GP_SCULPT_SETT_FLAG_AUTOMASK_MATERIAL_ACTIVE); + + const float radius = brush_radius(scene, brush); + const int2 mval_i = int2(math::round(start_sample.mouse_position)); + const int active_material_index = math::max(object.actcol - 1, 0); + + const Vector drawings = get_drawings_with_masking_for_stroke_operation(C); + this->auto_masking_info_per_drawing.reinitialize(drawings.size()); + + VectorSet masked_layer_indices; + VectorSet masked_material_indices; + for (const int drawing_i : drawings.index_range()) { + const MutableDrawingInfo &drawing_info = drawings[drawing_i]; + AutoMaskingInfo &automask_info = this->auto_masking_info_per_drawing[drawing_i]; + GreasePencilStrokeParams params = GreasePencilStrokeParams::from_context( + scene, + depsgraph, + region, + rv3d, + object, + drawing_info.layer_index, + drawing_info.frame_number, + drawing_info.multi_frame_falloff, + drawing_info.drawing); + automask_info.point_mask = point_mask_for_stroke_operation( + params, use_sculpt_selection_masking, automask_info.memory); + if (automask_info.point_mask.is_empty()) { + continue; + } + + const bke::CurvesGeometry &curves = drawing_info.drawing.strokes(); + const OffsetIndices points_by_curve = curves.points_by_curve(); + const bke::AttributeAccessor attributes = curves.attributes(); + + if (use_auto_mask_active_material) { + IndexMaskMemory memory; + const VArraySpan materials = *attributes.lookup_or_default( + "material_index", bke::AttrDomain::Point, 0); + const IndexMask active_material_mask = IndexMask::from_predicate( + curves.points_range(), GrainSize(4096), memory, [&](const int64_t point_i) { + return active_material_index == materials[point_i]; + }); + automask_info.point_mask = IndexMask::from_intersection( + automask_info.point_mask, active_material_mask, automask_info.memory); + if (automask_info.point_mask.is_empty()) { + continue; + } + } + + if (use_auto_mask_layer || use_auto_mask_stroke || use_auto_mask_material) { + Array view_positions = calculate_view_positions(params, automask_info.point_mask); + + IndexMaskMemory memory; + const IndexMask stroke_selection = curve_mask_for_stroke_operation( + params, use_sculpt_selection_masking, memory); + const IndexMask strokes_under_brush = IndexMask::from_predicate( + stroke_selection, GrainSize(512), memory, [&](const int curve_i) { + for (const int point_i : points_by_curve[curve_i]) { + const float distance = math::distance(mval_i, int2(view_positions[point_i])); + if (distance <= radius) { + return true; + } + } + return false; + }); + + if (use_auto_mask_layer && !strokes_under_brush.is_empty()) { + masked_layer_indices.add(drawing_info.layer_index); + } + + if (use_auto_mask_stroke) { + automask_info.point_mask = IndexMask::from_intersection( + automask_info.point_mask, + IndexMask::from_ranges(curves.points_by_curve(), strokes_under_brush, memory), + automask_info.memory); + } + + if (use_auto_mask_material) { + const VArraySpan material_indices = *attributes.lookup("material_index", + bke::AttrDomain::Curve); + strokes_under_brush.foreach_index( + [&](const int curve_i) { masked_material_indices.add(material_indices[curve_i]); }); + } + } + } + + /* When we mask by the initial strokes under the cursor, the other masking options don't affect + * the resulting mask. So we can skip the second loop. */ + if (use_auto_mask_stroke) { + return; + } + + threading::parallel_for_each(drawings.index_range(), [&](const int drawing_i) { + const MutableDrawingInfo &drawing_info = drawings[drawing_i]; + AutoMaskingInfo &automask_info = this->auto_masking_info_per_drawing[drawing_i]; + + if (use_auto_mask_layer && !masked_layer_indices.contains(drawing_info.layer_index)) { + automask_info.point_mask = {}; + return; + } + + if (use_auto_mask_material) { + const bke::CurvesGeometry &curves = drawing_info.drawing.strokes(); + const VArraySpan material_indices = *curves.attributes().lookup("material_index"); + IndexMaskMemory memory; + const IndexMask masked_curves = IndexMask::from_predicate( + curves.curves_range(), GrainSize(1024), memory, [&](const int curve_i) { + return masked_material_indices.contains(material_indices[curve_i]); + }); + + automask_info.point_mask = IndexMask::from_intersection( + automask_info.point_mask, + IndexMask::from_ranges(curves.points_by_curve(), masked_curves, memory), + automask_info.memory); + } + }); +} + void GreasePencilStrokeOperationCommon::stroke_extended(const InputSample &extension_sample) { this->prev_mouse_position = extension_sample.mouse_position; diff --git a/source/blender/editors/sculpt_paint/grease_pencil_sculpt_clone.cc b/source/blender/editors/sculpt_paint/grease_pencil_sculpt_clone.cc index dda5051a64a..9ba4d8b0fa2 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_sculpt_clone.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_sculpt_clone.cc @@ -47,8 +47,11 @@ void CloneOperation::on_stroke_begin(const bContext &C, const InputSample &start * - Continuous: Create multiple copies during the stroke (disabled) * * Here we only have the GPv2 behavior that actually works for now. */ - this->foreach_editable_drawing( - C, [&](const GreasePencilStrokeParams ¶ms, const DeltaProjectionFunc &projection_fn) { + this->foreach_editable_drawing_with_automask( + C, + [&](const GreasePencilStrokeParams ¶ms, + const IndexMask & /*point_mask*/, + const DeltaProjectionFunc &projection_fn) { /* Only insert on the active layer. */ if (¶ms.layer != grease_pencil.get_active_layer()) { return false; diff --git a/source/blender/editors/sculpt_paint/grease_pencil_sculpt_grab.cc b/source/blender/editors/sculpt_paint/grease_pencil_sculpt_grab.cc index 8c6482e1549..059ff67997e 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_sculpt_grab.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_sculpt_grab.cc @@ -127,17 +127,16 @@ void GrabOperation::on_stroke_begin(const bContext &C, const InputSample &start_ Object &ob_eval = *DEG_get_evaluated_object(&depsgraph, &ob_orig); GreasePencil &grease_pencil = *static_cast(ob_orig.data); - const bool is_masking = GPENCIL_ANY_SCULPT_MASK( - eGP_Sculpt_SelectMaskFlag(scene.toolsettings->gpencil_selectmode_sculpt)); - init_brush(brush); + init_auto_masking(C, start_sample); this->prev_mouse_position = start_sample.mouse_position; - const Vector drawings = get_drawings_for_painting(C); + const Vector drawings = get_drawings_with_masking_for_stroke_operation(C); this->drawing_data.reinitialize(drawings.size()); threading::parallel_for_each(drawings.index_range(), [&](const int i) { const MutableDrawingInfo &info = drawings[i]; + const AutoMaskingInfo &auto_mask_info = this->auto_masking_info_per_drawing[i]; BLI_assert(info.layer_index >= 0); PointWeights &data = this->drawing_data[i]; @@ -155,10 +154,8 @@ void GrabOperation::on_stroke_begin(const bContext &C, const InputSample &start_ info.frame_number, info.multi_frame_falloff, info.drawing}; - IndexMaskMemory selection_memory; - IndexMask selection = point_selection_mask(params, is_masking, selection_memory); - Array view_positions = calculate_view_positions(params, selection); + Array view_positions = calculate_view_positions(params, auto_mask_info.point_mask); /* Cache points under brush influence. */ Vector weights; @@ -167,7 +164,7 @@ void GrabOperation::on_stroke_begin(const bContext &C, const InputSample &start_ start_sample.mouse_position, 1.0f, info.multi_frame_falloff, - selection, + auto_mask_info.point_mask, view_positions, weights, data.memory); diff --git a/source/blender/editors/sculpt_paint/grease_pencil_sculpt_pinch.cc b/source/blender/editors/sculpt_paint/grease_pencil_sculpt_pinch.cc index bc7bd37297c..69556795d4b 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_sculpt_pinch.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_sculpt_pinch.cc @@ -33,6 +33,7 @@ class PinchOperation : public GreasePencilStrokeOperationCommon { void PinchOperation::on_stroke_begin(const bContext &C, const InputSample &start_sample) { this->init_stroke(C, start_sample); + this->init_auto_masking(C, start_sample); } void PinchOperation::on_stroke_extended(const bContext &C, const InputSample &extension_sample) @@ -41,25 +42,20 @@ void PinchOperation::on_stroke_extended(const bContext &C, const InputSample &ex Paint &paint = *BKE_paint_get_active_from_context(&C); const Brush &brush = *BKE_paint_brush(&paint); const bool invert = this->is_inverted(brush); - const bool is_masking = GPENCIL_ANY_SCULPT_MASK( - eGP_Sculpt_SelectMaskFlag(scene.toolsettings->gpencil_selectmode_sculpt)); - - this->foreach_editable_drawing( - C, [&](const GreasePencilStrokeParams ¶ms, const DeltaProjectionFunc &projection_fn) { - IndexMaskMemory selection_memory; - const IndexMask selection = point_selection_mask(params, is_masking, selection_memory); - if (selection.is_empty()) { - return false; - } + this->foreach_editable_drawing_with_automask( + C, + [&](const GreasePencilStrokeParams ¶ms, + const IndexMask &point_mask, + const DeltaProjectionFunc &projection_fn) { bke::crazyspace::GeometryDeformation deformation = get_drawing_deformation(params); - Array view_positions = calculate_view_positions(params, selection); + Array view_positions = calculate_view_positions(params, point_mask); bke::CurvesGeometry &curves = params.drawing.strokes_for_write(); MutableSpan positions = curves.positions_for_write(); const float2 target = extension_sample.mouse_position; - selection.foreach_index(GrainSize(4096), [&](const int64_t point_i) { + point_mask.foreach_index(GrainSize(4096), [&](const int64_t point_i) { const float2 &co = view_positions[point_i]; const float influence = brush_point_influence( scene, brush, co, extension_sample, params.multi_frame_falloff); diff --git a/source/blender/editors/sculpt_paint/grease_pencil_sculpt_push.cc b/source/blender/editors/sculpt_paint/grease_pencil_sculpt_push.cc index 606003e1e63..8112851bc92 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_sculpt_push.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_sculpt_push.cc @@ -33,6 +33,7 @@ class PushOperation : public GreasePencilStrokeOperationCommon { void PushOperation::on_stroke_begin(const bContext &C, const InputSample &start_sample) { this->init_stroke(C, start_sample); + this->init_auto_masking(C, start_sample); } void PushOperation::on_stroke_extended(const bContext &C, const InputSample &extension_sample) @@ -41,25 +42,19 @@ void PushOperation::on_stroke_extended(const bContext &C, const InputSample &ext Paint &paint = *BKE_paint_get_active_from_context(&C); const Brush &brush = *BKE_paint_brush(&paint); - const bool is_masking = GPENCIL_ANY_SCULPT_MASK( - eGP_Sculpt_SelectMaskFlag(scene.toolsettings->gpencil_selectmode_sculpt)); - - this->foreach_editable_drawing( - C, [&](const GreasePencilStrokeParams ¶ms, const DeltaProjectionFunc &projection_fn) { - IndexMaskMemory selection_memory; - const IndexMask selection = point_selection_mask(params, is_masking, selection_memory); - if (selection.is_empty()) { - return false; - } - + this->foreach_editable_drawing_with_automask( + C, + [&](const GreasePencilStrokeParams ¶ms, + const IndexMask &point_mask, + const DeltaProjectionFunc &projection_fn) { bke::crazyspace::GeometryDeformation deformation = get_drawing_deformation(params); - Array view_positions = calculate_view_positions(params, selection); + Array view_positions = calculate_view_positions(params, point_mask); bke::CurvesGeometry &curves = params.drawing.strokes_for_write(); MutableSpan positions = curves.positions_for_write(); const float2 mouse_delta = this->mouse_delta(extension_sample); - selection.foreach_index(GrainSize(4096), [&](const int64_t point_i) { + point_mask.foreach_index(GrainSize(4096), [&](const int64_t point_i) { const float2 &co = view_positions[point_i]; const float influence = brush_point_influence( scene, brush, co, extension_sample, params.multi_frame_falloff); diff --git a/source/blender/editors/sculpt_paint/grease_pencil_sculpt_randomize.cc b/source/blender/editors/sculpt_paint/grease_pencil_sculpt_randomize.cc index cd3c2fd15a1..9c06a6d168a 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_sculpt_randomize.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_sculpt_randomize.cc @@ -53,6 +53,7 @@ uint32_t RandomizeOperation::unique_seed() const void RandomizeOperation::on_stroke_begin(const bContext &C, const InputSample &start_sample) { this->init_stroke(C, start_sample); + this->init_auto_masking(C, start_sample); } void RandomizeOperation::on_stroke_extended(const bContext &C, const InputSample &extension_sample) @@ -62,21 +63,15 @@ void RandomizeOperation::on_stroke_extended(const bContext &C, const InputSample const Brush &brush = *BKE_paint_brush(&paint); const int sculpt_mode_flag = brush.gpencil_settings->sculpt_mode_flag; - const bool is_masking = GPENCIL_ANY_SCULPT_MASK( - eGP_Sculpt_SelectMaskFlag(scene.toolsettings->gpencil_selectmode_sculpt)); - - this->foreach_editable_drawing( - C, [&](const GreasePencilStrokeParams ¶ms, const DeltaProjectionFunc &projection_fn) { + this->foreach_editable_drawing_with_automask( + C, + [&](const GreasePencilStrokeParams ¶ms, + const IndexMask &point_mask, + const DeltaProjectionFunc &projection_fn) { const uint32_t seed = this->unique_seed(); - IndexMaskMemory selection_memory; - const IndexMask selection = point_selection_mask(params, is_masking, selection_memory); - if (selection.is_empty()) { - return false; - } - bke::crazyspace::GeometryDeformation deformation = get_drawing_deformation(params); - Array view_positions = calculate_view_positions(params, selection); + Array view_positions = calculate_view_positions(params, point_mask); bke::CurvesGeometry &curves = params.drawing.strokes_for_write(); bke::MutableAttributeAccessor attributes = curves.attributes_for_write(); @@ -88,7 +83,7 @@ void RandomizeOperation::on_stroke_extended(const bContext &C, const InputSample const float2 forward = math::normalize(this->mouse_delta(extension_sample)); const float2 sideways = float2(-forward.y, forward.x); - selection.foreach_index(GrainSize(4096), [&](const int64_t point_i) { + point_mask.foreach_index(GrainSize(4096), [&](const int64_t point_i) { const float2 &co = view_positions[point_i]; const float influence = brush_point_influence( scene, brush, co, extension_sample, params.multi_frame_falloff); @@ -105,7 +100,7 @@ void RandomizeOperation::on_stroke_extended(const bContext &C, const InputSample } if (sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_STRENGTH) { MutableSpan opacities = params.drawing.opacities_for_write(); - selection.foreach_index(GrainSize(4096), [&](const int64_t point_i) { + point_mask.foreach_index(GrainSize(4096), [&](const int64_t point_i) { const float2 &co = view_positions[point_i]; const float influence = brush_point_influence( scene, brush, co, extension_sample, params.multi_frame_falloff); @@ -119,7 +114,7 @@ void RandomizeOperation::on_stroke_extended(const bContext &C, const InputSample } if (sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_THICKNESS) { const MutableSpan radii = params.drawing.radii_for_write(); - selection.foreach_index(GrainSize(4096), [&](const int64_t point_i) { + point_mask.foreach_index(GrainSize(4096), [&](const int64_t point_i) { const float2 &co = view_positions[point_i]; const float influence = brush_point_influence( scene, brush, co, extension_sample, params.multi_frame_falloff); @@ -135,7 +130,7 @@ void RandomizeOperation::on_stroke_extended(const bContext &C, const InputSample if (sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_UV) { bke::SpanAttributeWriter rotations = attributes.lookup_or_add_for_write_span("rotation", bke::AttrDomain::Point); - selection.foreach_index(GrainSize(4096), [&](const int64_t point_i) { + point_mask.foreach_index(GrainSize(4096), [&](const int64_t point_i) { const float2 &co = view_positions[point_i]; const float influence = brush_point_influence( scene, brush, co, extension_sample, params.multi_frame_falloff); diff --git a/source/blender/editors/sculpt_paint/grease_pencil_sculpt_smooth.cc b/source/blender/editors/sculpt_paint/grease_pencil_sculpt_smooth.cc index 0665a47ec66..daa7a43e1a6 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_sculpt_smooth.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_sculpt_smooth.cc @@ -57,6 +57,7 @@ void SmoothOperation::on_stroke_begin(const bContext &C, const InputSample &star else { this->init_stroke(C, start_sample); } + this->init_auto_masking(C, start_sample); } void SmoothOperation::on_stroke_extended(const bContext &C, const InputSample &extension_sample) @@ -74,91 +75,86 @@ void SmoothOperation::on_stroke_extended(const bContext &C, const InputSample &e }(); const int sculpt_mode_flag = brush.gpencil_settings->sculpt_mode_flag; - const bool is_masking = GPENCIL_ANY_SCULPT_MASK( - eGP_Sculpt_SelectMaskFlag(scene.toolsettings->gpencil_selectmode_sculpt)); + this->foreach_editable_drawing_with_automask( + C, [&](const GreasePencilStrokeParams ¶ms, const IndexMask &point_mask) { + Array view_positions = calculate_view_positions(params, point_mask); + bke::CurvesGeometry &curves = params.drawing.strokes_for_write(); + bke::MutableAttributeAccessor attributes = curves.attributes_for_write(); + const OffsetIndices points_by_curve = curves.points_by_curve(); + const VArray cyclic = curves.cyclic(); + const int iterations = 2; - this->foreach_editable_drawing(C, [&](const GreasePencilStrokeParams ¶ms) { - IndexMaskMemory selection_memory; - const IndexMask selection = point_selection_mask(params, is_masking, selection_memory); - if (selection.is_empty()) { - return false; - } + const VArray influences = VArray::ForFunc( + view_positions.size(), [&](const int64_t point_) { + return brush_point_influence(scene, + brush, + view_positions[point_], + extension_sample, + params.multi_frame_falloff); + }); + Array selection_array(curves.points_num()); + point_mask.to_bools(selection_array); + const VArray selection_varray = VArray::ForSpan(selection_array); - Array view_positions = calculate_view_positions(params, selection); - bke::CurvesGeometry &curves = params.drawing.strokes_for_write(); - bke::MutableAttributeAccessor attributes = curves.attributes_for_write(); - const OffsetIndices points_by_curve = curves.points_by_curve(); - const VArray cyclic = curves.cyclic(); - const int iterations = 2; - - const VArray influences = VArray::ForFunc( - view_positions.size(), [&](const int64_t point_) { - return brush_point_influence( - scene, brush, view_positions[point_], extension_sample, params.multi_frame_falloff); - }); - Array selection_array(curves.points_num()); - selection.to_bools(selection_array); - const VArray selection_varray = VArray::ForSpan(selection_array); - - bool changed = false; - if (sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_POSITION) { - MutableSpan positions = curves.positions_for_write(); - geometry::smooth_curve_attribute(curves.curves_range(), - points_by_curve, - selection_varray, - cyclic, - iterations, - influences, - false, - false, - positions); - params.drawing.tag_positions_changed(); - changed = true; - } - if (sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_STRENGTH) { - MutableSpan opacities = params.drawing.opacities_for_write(); - geometry::smooth_curve_attribute(curves.curves_range(), - points_by_curve, - selection_varray, - cyclic, - iterations, - influences, - true, - false, - opacities); - changed = true; - } - if (sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_THICKNESS) { - const MutableSpan radii = params.drawing.radii_for_write(); - geometry::smooth_curve_attribute(curves.curves_range(), - points_by_curve, - selection_varray, - cyclic, - iterations, - influences, - true, - false, - radii); - curves.tag_radii_changed(); - changed = true; - } - if (sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_UV) { - bke::SpanAttributeWriter rotations = attributes.lookup_or_add_for_write_span( - "rotation", bke::AttrDomain::Point); - geometry::smooth_curve_attribute(curves.curves_range(), - points_by_curve, - selection_varray, - cyclic, - iterations, - influences, - true, - false, - rotations.span); - rotations.finish(); - changed = true; - } - return changed; - }); + bool changed = false; + if (sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_POSITION) { + MutableSpan positions = curves.positions_for_write(); + geometry::smooth_curve_attribute(curves.curves_range(), + points_by_curve, + selection_varray, + cyclic, + iterations, + influences, + false, + false, + positions); + params.drawing.tag_positions_changed(); + changed = true; + } + if (sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_STRENGTH) { + MutableSpan opacities = params.drawing.opacities_for_write(); + geometry::smooth_curve_attribute(curves.curves_range(), + points_by_curve, + selection_varray, + cyclic, + iterations, + influences, + true, + false, + opacities); + changed = true; + } + if (sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_THICKNESS) { + const MutableSpan radii = params.drawing.radii_for_write(); + geometry::smooth_curve_attribute(curves.curves_range(), + points_by_curve, + selection_varray, + cyclic, + iterations, + influences, + true, + false, + radii); + curves.tag_radii_changed(); + changed = true; + } + if (sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_UV) { + bke::SpanAttributeWriter rotations = + attributes.lookup_or_add_for_write_span("rotation", bke::AttrDomain::Point); + geometry::smooth_curve_attribute(curves.curves_range(), + points_by_curve, + selection_varray, + cyclic, + iterations, + influences, + true, + false, + rotations.span); + rotations.finish(); + changed = true; + } + return changed; + }); this->stroke_extended(extension_sample); } diff --git a/source/blender/editors/sculpt_paint/grease_pencil_sculpt_strength.cc b/source/blender/editors/sculpt_paint/grease_pencil_sculpt_strength.cc index 6ab4cb56227..27472a1f3aa 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_sculpt_strength.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_sculpt_strength.cc @@ -34,6 +34,7 @@ class StrengthOperation : public GreasePencilStrokeOperationCommon { void StrengthOperation::on_stroke_begin(const bContext &C, const InputSample &start_sample) { this->init_stroke(C, start_sample); + this->init_auto_masking(C, start_sample); } void StrengthOperation::on_stroke_extended(const bContext &C, const InputSample &extension_sample) @@ -43,30 +44,22 @@ void StrengthOperation::on_stroke_extended(const bContext &C, const InputSample const Brush &brush = *BKE_paint_brush(&paint); const bool invert = this->is_inverted(brush); - const bool is_masking = GPENCIL_ANY_SCULPT_MASK( - eGP_Sculpt_SelectMaskFlag(scene.toolsettings->gpencil_selectmode_sculpt)); + this->foreach_editable_drawing_with_automask( + C, [&](const GreasePencilStrokeParams ¶ms, const IndexMask &point_mask) { + Array view_positions = calculate_view_positions(params, point_mask); + MutableSpan opacities = params.drawing.opacities_for_write(); - this->foreach_editable_drawing(C, [&](const GreasePencilStrokeParams ¶ms) { - IndexMaskMemory selection_memory; - const IndexMask selection = point_selection_mask(params, is_masking, selection_memory); - if (selection.is_empty()) { - return false; - } + point_mask.foreach_index(GrainSize(4096), [&](const int64_t point_i) { + float &opacity = opacities[point_i]; + const float influence = brush_point_influence( + scene, brush, view_positions[point_i], extension_sample, params.multi_frame_falloff); + /* Brush influence mapped to opacity by a factor of 0.125. */ + const float delta_opacity = (invert ? -influence : influence) * 0.125f; + opacity = std::clamp(opacity + delta_opacity, 0.0f, 1.0f); + }); - Array view_positions = calculate_view_positions(params, selection); - MutableSpan opacities = params.drawing.opacities_for_write(); - - selection.foreach_index(GrainSize(4096), [&](const int64_t point_i) { - float &opacity = opacities[point_i]; - const float influence = brush_point_influence( - scene, brush, view_positions[point_i], extension_sample, params.multi_frame_falloff); - /* Brush influence mapped to opacity by a factor of 0.125. */ - const float delta_opacity = (invert ? -influence : influence) * 0.125f; - opacity = std::clamp(opacity + delta_opacity, 0.0f, 1.0f); - }); - - return true; - }); + return true; + }); this->stroke_extended(extension_sample); } diff --git a/source/blender/editors/sculpt_paint/grease_pencil_sculpt_thickness.cc b/source/blender/editors/sculpt_paint/grease_pencil_sculpt_thickness.cc index 8f5011a2e1b..b4883fd862e 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_sculpt_thickness.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_sculpt_thickness.cc @@ -34,6 +34,7 @@ class ThicknessOperation : public GreasePencilStrokeOperationCommon { void ThicknessOperation::on_stroke_begin(const bContext &C, const InputSample &start_sample) { this->init_stroke(C, start_sample); + this->init_auto_masking(C, start_sample); } void ThicknessOperation::on_stroke_extended(const bContext &C, const InputSample &extension_sample) @@ -43,33 +44,25 @@ void ThicknessOperation::on_stroke_extended(const bContext &C, const InputSample const Brush &brush = *BKE_paint_brush(&paint); const bool invert = this->is_inverted(brush); - const bool is_masking = GPENCIL_ANY_SCULPT_MASK( - eGP_Sculpt_SelectMaskFlag(scene.toolsettings->gpencil_selectmode_sculpt)); + this->foreach_editable_drawing_with_automask( + C, [&](const GreasePencilStrokeParams ¶ms, const IndexMask &point_mask) { + Array view_positions = calculate_view_positions(params, point_mask); + bke::CurvesGeometry &curves = params.drawing.strokes_for_write(); + BLI_assert(view_positions.size() == curves.points_num()); + MutableSpan radii = params.drawing.radii_for_write(); - this->foreach_editable_drawing(C, [&](const GreasePencilStrokeParams ¶ms) { - IndexMaskMemory selection_memory; - const IndexMask selection = point_selection_mask(params, is_masking, selection_memory); - if (selection.is_empty()) { - return false; - } + point_mask.foreach_index(GrainSize(4096), [&](const int64_t point_i) { + float &radius = radii[point_i]; + const float influence = brush_point_influence( + scene, brush, view_positions[point_i], extension_sample, params.multi_frame_falloff); + /* Factor 1/1000 is used to map arbitrary influence value to a sensible radius. */ + const float delta_radius = (invert ? -influence : influence) * 0.001f; + radius = std::max(radius + delta_radius, 0.0f); + }); - Array view_positions = calculate_view_positions(params, selection); - bke::CurvesGeometry &curves = params.drawing.strokes_for_write(); - BLI_assert(view_positions.size() == curves.points_num()); - MutableSpan radii = params.drawing.radii_for_write(); - - selection.foreach_index(GrainSize(4096), [&](const int64_t point_i) { - float &radius = radii[point_i]; - const float influence = brush_point_influence( - scene, brush, view_positions[point_i], extension_sample, params.multi_frame_falloff); - /* Factor 1/1000 is used to map arbitrary influence value to a sensible radius. */ - const float delta_radius = (invert ? -influence : influence) * 0.001f; - radius = std::max(radius + delta_radius, 0.0f); - }); - - curves.tag_radii_changed(); - return true; - }); + curves.tag_radii_changed(); + return true; + }); this->stroke_extended(extension_sample); } diff --git a/source/blender/editors/sculpt_paint/grease_pencil_sculpt_twist.cc b/source/blender/editors/sculpt_paint/grease_pencil_sculpt_twist.cc index 6ec9cf4782b..8645227c45e 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_sculpt_twist.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_sculpt_twist.cc @@ -42,6 +42,7 @@ static float2 rotate_by_angle(const float2 &vec, const float angle) void TwistOperation::on_stroke_begin(const bContext &C, const InputSample &start_sample) { this->init_stroke(C, start_sample); + this->init_auto_masking(C, start_sample); } void TwistOperation::on_stroke_extended(const bContext &C, const InputSample &extension_sample) @@ -51,25 +52,19 @@ void TwistOperation::on_stroke_extended(const bContext &C, const InputSample &ex const Brush &brush = *BKE_paint_brush(&paint); const bool invert = this->is_inverted(brush); - const bool is_masking = GPENCIL_ANY_SCULPT_MASK( - eGP_Sculpt_SelectMaskFlag(scene.toolsettings->gpencil_selectmode_sculpt)); - - this->foreach_editable_drawing( - C, [&](const GreasePencilStrokeParams ¶ms, const DeltaProjectionFunc &projection_fn) { - IndexMaskMemory selection_memory; - const IndexMask selection = point_selection_mask(params, is_masking, selection_memory); - if (selection.is_empty()) { - return false; - } - + this->foreach_editable_drawing_with_automask( + C, + [&](const GreasePencilStrokeParams ¶ms, + const IndexMask &point_mask, + const DeltaProjectionFunc &projection_fn) { bke::crazyspace::GeometryDeformation deformation = get_drawing_deformation(params); - Array view_positions = calculate_view_positions(params, selection); + Array view_positions = calculate_view_positions(params, point_mask); bke::CurvesGeometry &curves = params.drawing.strokes_for_write(); MutableSpan positions = curves.positions_for_write(); const float2 mouse_pos = extension_sample.mouse_position; - selection.foreach_index(GrainSize(4096), [&](const int64_t point_i) { + point_mask.foreach_index(GrainSize(4096), [&](const int64_t point_i) { const float2 &co = view_positions[point_i]; const float influence = brush_point_influence( scene, brush, co, extension_sample, params.multi_frame_falloff); diff --git a/source/blender/editors/sculpt_paint/grease_pencil_vertex_average.cc b/source/blender/editors/sculpt_paint/grease_pencil_vertex_average.cc index f107b4b541e..c0ef7698c2c 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_vertex_average.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_vertex_average.cc @@ -38,7 +38,7 @@ void VertexAverageOperation::on_stroke_extended(const bContext &C, const float radius = brush_radius(scene, brush, extension_sample.pressure); const float radius_squared = radius * radius; - const bool is_masking = GPENCIL_ANY_VERTEX_MASK( + const bool use_selection_masking = GPENCIL_ANY_VERTEX_MASK( eGP_vertex_SelectMaskFlag(scene.toolsettings->gpencil_selectmode_vertex)); const bool do_points = do_vertex_color_points(brush); @@ -49,7 +49,8 @@ void VertexAverageOperation::on_stroke_extended(const bContext &C, int color_count = 0; this->foreach_editable_drawing(C, [&](const GreasePencilStrokeParams ¶ms) { IndexMaskMemory memory; - const IndexMask point_selection = point_selection_mask(params, is_masking, memory); + const IndexMask point_selection = point_mask_for_stroke_operation( + params, use_selection_masking, memory); if (!point_selection.is_empty() && do_points) { const Array view_positions = calculate_view_positions(params, point_selection); const VArray vertex_colors = params.drawing.vertex_colors(); @@ -64,7 +65,8 @@ void VertexAverageOperation::on_stroke_extended(const bContext &C, } }); } - const IndexMask fill_selection = fill_selection_mask(params, is_masking, memory); + const IndexMask fill_selection = fill_mask_for_stroke_operation( + params, use_selection_masking, memory); if (!fill_selection.is_empty() && do_fill) { const OffsetIndices points_by_curve = params.drawing.strokes().points_by_curve(); const Array view_positions = calculate_view_positions(params, point_selection); @@ -94,7 +96,8 @@ void VertexAverageOperation::on_stroke_extended(const bContext &C, this->foreach_editable_drawing(C, GrainSize(1), [&](const GreasePencilStrokeParams ¶ms) { IndexMaskMemory memory; - const IndexMask point_selection = point_selection_mask(params, is_masking, memory); + const IndexMask point_selection = point_mask_for_stroke_operation( + params, use_selection_masking, memory); if (!point_selection.is_empty() && do_points) { const Array view_positions = calculate_view_positions(params, point_selection); MutableSpan vertex_colors = params.drawing.vertex_colors_for_write(); @@ -108,7 +111,8 @@ void VertexAverageOperation::on_stroke_extended(const bContext &C, }); } - const IndexMask fill_selection = fill_selection_mask(params, is_masking, memory); + const IndexMask fill_selection = fill_mask_for_stroke_operation( + params, use_selection_masking, memory); if (!fill_selection.is_empty() && do_fill) { const OffsetIndices points_by_curve = params.drawing.strokes().points_by_curve(); const Array view_positions = calculate_view_positions(params, point_selection); diff --git a/source/blender/editors/sculpt_paint/grease_pencil_vertex_blur.cc b/source/blender/editors/sculpt_paint/grease_pencil_vertex_blur.cc index 07b5af8f565..03be9eb2834 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_vertex_blur.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_vertex_blur.cc @@ -38,16 +38,18 @@ void VertexBlurOperation::on_stroke_extended(const bContext &C, const float radius = brush_radius(scene, brush, extension_sample.pressure); const float radius_squared = radius * radius; - const bool is_masking = GPENCIL_ANY_VERTEX_MASK( + const bool use_selection_masking = GPENCIL_ANY_VERTEX_MASK( eGP_vertex_SelectMaskFlag(scene.toolsettings->gpencil_selectmode_vertex)); this->foreach_editable_drawing(C, GrainSize(1), [&](const GreasePencilStrokeParams ¶ms) { IndexMaskMemory memory; - const IndexMask stroke_selection = stroke_selection_mask(params, is_masking, memory); + const IndexMask stroke_selection = curve_mask_for_stroke_operation( + params, use_selection_masking, memory); if (stroke_selection.is_empty()) { return false; } - const IndexMask point_selection = point_selection_mask(params, is_masking, memory); + const IndexMask point_selection = point_mask_for_stroke_operation( + params, use_selection_masking, memory); const Array view_positions = calculate_view_positions(params, point_selection); const OffsetIndices points_by_curve = params.drawing.strokes().points_by_curve(); MutableSpan vertex_colors = params.drawing.vertex_colors_for_write(); diff --git a/source/blender/editors/sculpt_paint/grease_pencil_vertex_paint.cc b/source/blender/editors/sculpt_paint/grease_pencil_vertex_paint.cc index bfad906555b..318a97ef63e 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_vertex_paint.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_vertex_paint.cc @@ -39,7 +39,7 @@ void VertexPaintOperation::on_stroke_extended(const bContext &C, const Brush &brush = *BKE_paint_brush(&paint); const bool invert = this->is_inverted(brush); - const bool is_masking = GPENCIL_ANY_VERTEX_MASK( + const bool use_selection_masking = GPENCIL_ANY_VERTEX_MASK( eGP_vertex_SelectMaskFlag(scene.toolsettings->gpencil_selectmode_vertex)); const bool do_points = do_vertex_color_points(brush); @@ -51,7 +51,8 @@ void VertexPaintOperation::on_stroke_extended(const bContext &C, this->foreach_editable_drawing(C, GrainSize(1), [&](const GreasePencilStrokeParams ¶ms) { IndexMaskMemory memory; - const IndexMask point_selection = point_selection_mask(params, is_masking, memory); + const IndexMask point_selection = point_mask_for_stroke_operation( + params, use_selection_masking, memory); if (!point_selection.is_empty() && do_points) { Array view_positions = calculate_view_positions(params, point_selection); MutableSpan vertex_colors = params.drawing.vertex_colors_for_write(); @@ -79,7 +80,8 @@ void VertexPaintOperation::on_stroke_extended(const bContext &C, } } - const IndexMask fill_selection = fill_selection_mask(params, is_masking, memory); + const IndexMask fill_selection = fill_mask_for_stroke_operation( + params, use_selection_masking, memory); if (!fill_selection.is_empty() && do_fill) { const OffsetIndices points_by_curve = params.drawing.strokes().points_by_curve(); Array view_positions = calculate_view_positions(params, point_selection); diff --git a/source/blender/editors/sculpt_paint/grease_pencil_vertex_replace.cc b/source/blender/editors/sculpt_paint/grease_pencil_vertex_replace.cc index f3e815f5d0f..06d68f7b6c8 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_vertex_replace.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_vertex_replace.cc @@ -36,7 +36,7 @@ void VertexReplaceOperation::on_stroke_extended(const bContext &C, Paint &paint = *BKE_paint_get_active_from_context(&C); const Brush &brush = *BKE_paint_brush(&paint); - const bool is_masking = GPENCIL_ANY_VERTEX_MASK( + const bool use_selection_masking = GPENCIL_ANY_VERTEX_MASK( eGP_vertex_SelectMaskFlag(scene.toolsettings->gpencil_selectmode_vertex)); const bool do_points = do_vertex_color_points(brush); @@ -48,7 +48,8 @@ void VertexReplaceOperation::on_stroke_extended(const bContext &C, this->foreach_editable_drawing(C, GrainSize(1), [&](const GreasePencilStrokeParams ¶ms) { IndexMaskMemory memory; - const IndexMask point_selection = point_selection_mask(params, is_masking, memory); + const IndexMask point_selection = point_mask_for_stroke_operation( + params, use_selection_masking, memory); if (!point_selection.is_empty() && do_points) { Array view_positions = calculate_view_positions(params, point_selection); MutableSpan vertex_colors = params.drawing.vertex_colors_for_write(); @@ -61,7 +62,8 @@ void VertexReplaceOperation::on_stroke_extended(const bContext &C, }); } - const IndexMask fill_selection = fill_selection_mask(params, is_masking, memory); + const IndexMask fill_selection = fill_mask_for_stroke_operation( + params, use_selection_masking, memory); if (!fill_selection.is_empty() && do_fill) { const OffsetIndices points_by_curve = params.drawing.strokes().points_by_curve(); Array view_positions = calculate_view_positions(params, point_selection); diff --git a/source/blender/editors/sculpt_paint/grease_pencil_vertex_smear.cc b/source/blender/editors/sculpt_paint/grease_pencil_vertex_smear.cc index 2565ffcdf96..9f43b988bd7 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_vertex_smear.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_vertex_smear.cc @@ -71,7 +71,7 @@ void VertexSmearOperation::init_color_grid(const bContext &C, const float2 start const Scene &scene = *CTX_data_scene(&C); Paint &paint = *BKE_paint_get_active_from_context(&C); const Brush &brush = *BKE_paint_brush(&paint); - const bool is_masking = GPENCIL_ANY_VERTEX_MASK( + const bool use_selection_masking = GPENCIL_ANY_VERTEX_MASK( eGP_vertex_SelectMaskFlag(scene.toolsettings->gpencil_selectmode_vertex)); const float radius = brush_radius(scene, brush, 1.0f); @@ -89,7 +89,8 @@ void VertexSmearOperation::init_color_grid(const bContext &C, const float2 start /* Initialize grid values. */ this->foreach_editable_drawing(C, [&](const GreasePencilStrokeParams ¶ms) { IndexMaskMemory memory; - const IndexMask point_selection = point_selection_mask(params, is_masking, memory); + const IndexMask point_selection = point_mask_for_stroke_operation( + params, use_selection_masking, memory); if (point_selection.is_empty()) { return false; } @@ -154,12 +155,13 @@ void VertexSmearOperation::on_stroke_extended(const bContext &C, const Brush &brush = *BKE_paint_brush(&paint); const float radius = brush_radius(scene, brush, extension_sample.pressure); - const bool is_masking = GPENCIL_ANY_VERTEX_MASK( + const bool use_selection_masking = GPENCIL_ANY_VERTEX_MASK( eGP_vertex_SelectMaskFlag(scene.toolsettings->gpencil_selectmode_vertex)); this->foreach_editable_drawing(C, GrainSize(1), [&](const GreasePencilStrokeParams ¶ms) { IndexMaskMemory memory; - const IndexMask point_selection = point_selection_mask(params, is_masking, memory); + const IndexMask point_selection = point_mask_for_stroke_operation( + params, use_selection_masking, memory); if (point_selection.is_empty()) { return false; }