Blender V4.3
grease_pencil_sculpt_smooth.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BKE_attribute.hh"
6
7#include "BKE_context.hh"
8#include "BKE_curves.hh"
10#include "BKE_paint.hh"
11
12#include "BLI_virtual_array.hh"
13#include "DNA_brush_enums.h"
14
15#include "GEO_smooth_curves.hh"
16
17#include "ED_grease_pencil.hh"
18#include "ED_view3d.hh"
19
20#include "WM_api.hh"
21#include "WM_types.hh"
22
24#include "paint_intern.hh"
25
27
29 public:
31
32 void on_stroke_begin(const bContext &C, const InputSample &start_sample) override;
33 void on_stroke_extended(const bContext &C, const InputSample &extension_sample) override;
34 void on_stroke_done(const bContext & /*C*/) override {}
35};
36
37void SmoothOperation::on_stroke_begin(const bContext &C, const InputSample &start_sample)
38{
39 this->init_stroke(C, start_sample);
40}
41
42void SmoothOperation::on_stroke_extended(const bContext &C, const InputSample &extension_sample)
43{
44 const Scene &scene = *CTX_data_scene(&C);
46 const Brush &brush = *BKE_paint_brush(&paint);
47 const int sculpt_mode_flag = brush.gpencil_settings->sculpt_mode_flag;
48
49 const bool is_masking = GPENCIL_ANY_SCULPT_MASK(
50 eGP_Sculpt_SelectMaskFlag(scene.toolsettings->gpencil_selectmode_sculpt));
51
53 IndexMaskMemory selection_memory;
54 const IndexMask selection = point_selection_mask(params, is_masking, selection_memory);
55 if (selection.is_empty()) {
56 return false;
57 }
58
59 Array<float2> view_positions = calculate_view_positions(params, selection);
60 bke::CurvesGeometry &curves = params.drawing.strokes_for_write();
61 bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
62 const OffsetIndices points_by_curve = curves.points_by_curve();
63 const VArray<bool> cyclic = curves.cyclic();
64 const int iterations = 2;
65
66 const VArray<float> influences = VArray<float>::ForFunc(
67 view_positions.size(), [&](const int64_t point_) {
68 return brush_point_influence(
69 scene, brush, view_positions[point_], extension_sample, params.multi_frame_falloff);
70 });
71 Array<bool> selection_array(curves.points_num());
72 selection.to_bools(selection_array);
73 const VArray<bool> selection_varray = VArray<bool>::ForSpan(selection_array);
74
75 bool changed = false;
76 if (sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_POSITION) {
77 MutableSpan<float3> positions = curves.positions_for_write();
78 geometry::smooth_curve_attribute(curves.curves_range(),
79 points_by_curve,
80 selection_varray,
81 cyclic,
82 iterations,
83 influences,
84 false,
85 false,
86 positions);
87 params.drawing.tag_positions_changed();
88 changed = true;
89 }
90 if (sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_STRENGTH) {
91 MutableSpan<float> opacities = params.drawing.opacities_for_write();
92 geometry::smooth_curve_attribute(curves.curves_range(),
93 points_by_curve,
94 selection_varray,
95 cyclic,
96 iterations,
97 influences,
98 true,
99 false,
100 opacities);
101 changed = true;
102 }
103 if (sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_THICKNESS) {
104 const MutableSpan<float> radii = params.drawing.radii_for_write();
105 geometry::smooth_curve_attribute(curves.curves_range(),
106 points_by_curve,
107 selection_varray,
108 cyclic,
109 iterations,
110 influences,
111 true,
112 false,
113 radii);
114 curves.tag_radii_changed();
115 changed = true;
116 }
117 if (sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_UV) {
118 bke::SpanAttributeWriter<float> rotations = attributes.lookup_or_add_for_write_span<float>(
119 "rotation", bke::AttrDomain::Point);
120 geometry::smooth_curve_attribute(curves.curves_range(),
121 points_by_curve,
122 selection_varray,
123 cyclic,
124 iterations,
125 influences,
126 true,
127 false,
128 rotations.span);
129 rotations.finish();
130 changed = true;
131 }
132 return changed;
133 });
134 this->stroke_extended(extension_sample);
135}
136
137std::unique_ptr<GreasePencilStrokeOperation> new_smooth_operation(
138 const BrushStrokeMode stroke_mode)
139{
140 return std::make_unique<SmoothOperation>(stroke_mode);
141}
142
143} // namespace blender::ed::sculpt_paint::greasepencil
Scene * CTX_data_scene(const bContext *C)
Low-level operations for curves.
Low-level operations for grease pencil.
Paint * BKE_paint_get_active_from_context(const bContext *C)
Definition paint.cc:477
Brush * BKE_paint_brush(Paint *paint)
Definition paint.cc:649
@ GP_SCULPT_FLAGMODE_APPLY_UV
@ GP_SCULPT_FLAGMODE_APPLY_POSITION
@ GP_SCULPT_FLAGMODE_APPLY_THICKNESS
@ GP_SCULPT_FLAGMODE_APPLY_STRENGTH
#define GPENCIL_ANY_SCULPT_MASK(flag)
eGP_Sculpt_SelectMaskFlag
int64_t size() const
Definition BLI_array.hh:245
static VArray ForSpan(Span< T > values)
static VArray ForFunc(const int64_t size, GetFunc get_func)
void foreach_editable_drawing(const bContext &C, FunctionRef< bool(const GreasePencilStrokeParams &params)> fn) const
void on_stroke_extended(const bContext &C, const InputSample &extension_sample) override
void on_stroke_begin(const bContext &C, const InputSample &start_sample) override
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
IndexMask point_selection_mask(const GreasePencilStrokeParams &params, const bool use_masking, IndexMaskMemory &memory)
Array< float2 > calculate_view_positions(const GreasePencilStrokeParams &params, const IndexMask &selection)
std::unique_ptr< CurvesSculptStrokeOperation > new_smooth_operation()
void smooth_curve_attribute(const IndexMask &curves_to_smooth, const OffsetIndices< int > points_by_curve, const VArray< bool > &point_selection, const VArray< bool > &cyclic, int iterations, float influence, bool smooth_ends, bool keep_shape, GMutableSpan attribute_data)
BrushStrokeMode
__int64 int64_t
Definition stdint.h:89
struct BrushGpencilSettings * gpencil_settings