Blender V5.0
grease_pencil_weight_average.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
6
8
10 /* Get the average weight of all points in the brush buffer. */
11 float get_average_weight_in_brush_buffer(const Span<DrawingWeightData> drawing_weights)
12 {
13 float average_sum = 0.0f;
14 float point_num = 0;
15 for (const DrawingWeightData &drawing_weight : drawing_weights) {
16 for (const BrushPoint &point : drawing_weight.points_in_brush) {
17 average_sum += drawing_weight.deform_weights[point.drawing_point_index];
18 point_num++;
19 }
20 }
21
22 if (point_num == 0) {
23 return 0.0f;
24 }
25 return math::clamp(average_sum / point_num, 0.0f, 1.0f);
26 }
27
28 public:
29 void on_stroke_begin(const bContext &C, const InputSample &start_sample) override
30 {
31 using namespace blender::ed::greasepencil;
32
33 this->get_brush_settings(C, start_sample);
36
37 /* Get editable drawings grouped per frame number. When multi-frame editing is disabled, this
38 * is just one group for the current frame. When multi-frame editing is enabled, the selected
39 * keyframes are grouped per frame number. This way we can use Average on multiple layers
40 * together instead of on every layer individually. */
41 const Scene *scene = CTX_data_scene(&C);
42 Array<Vector<MutableDrawingInfo>> drawings_per_frame =
44
45 this->drawing_weight_data = Array<Array<DrawingWeightData>>(drawings_per_frame.size());
46
47 /* Get weight data for all drawings in this frame group. */
48 for (const int frame_group : drawings_per_frame.index_range()) {
49 const Vector<MutableDrawingInfo> &drawings = drawings_per_frame[frame_group];
50 this->init_weight_data_for_drawings(C, drawings, frame_group);
51 }
52 }
53
54 void on_stroke_extended(const bContext &C, const InputSample &extension_sample) override
55 {
56 using namespace blender::ed::greasepencil;
57
58 this->get_mouse_input_sample(extension_sample);
59
60 /* Iterate over the drawings grouped per frame number. Collect all stroke points under the
61 * brush and average them. */
62 std::atomic<bool> drawing_changed = false;
64 this->drawing_weight_data.index_range(), [&](const int frame_group) {
65 Array<DrawingWeightData> &drawing_weights = this->drawing_weight_data[frame_group];
66
67 /* For all layers at this key frame, collect the stroke points under the brush in a
68 * buffer. */
69 threading::parallel_for_each(drawing_weights, [&](DrawingWeightData &drawing_weight) {
70 for (const int point_index : drawing_weight.point_positions.index_range()) {
71 const float2 &co = drawing_weight.point_positions[point_index];
72
73 /* When the point is under the brush, add it to the brush point buffer. */
74 this->add_point_under_brush_to_brush_buffer(co, drawing_weight, point_index);
75 }
76 });
77
78 /* Get the average weight of the points in the brush buffer. */
79 const float average_weight = this->get_average_weight_in_brush_buffer(drawing_weights);
80
81 /* Apply the Average brush to all points in the brush buffer. */
82 threading::parallel_for_each(drawing_weights, [&](DrawingWeightData &drawing_weight) {
83 bool point_changed = false;
84 for (const BrushPoint &point : drawing_weight.points_in_brush) {
85 if (drawing_weight.point_is_read_only[point.drawing_point_index]) {
86 continue;
87 }
88
89 this->apply_weight_to_point(point, average_weight, drawing_weight);
90 point_changed = true;
91
92 /* Normalize weights of bone-deformed vertex groups to 1.0f. */
93 if (this->auto_normalize) {
95 drawing_weight.active_vertex_group,
96 drawing_weight.locked_vgroups,
97 drawing_weight.bone_deformed_vgroups);
98 }
99 }
100
101 if (point_changed) {
102 drawing_changed.store(true, std::memory_order_relaxed);
103 }
104 drawing_weight.points_in_brush.clear();
105 });
106 });
107
108 if (drawing_changed) {
111 }
112 }
113
114 void on_stroke_done(const bContext & /*C*/) override {}
115};
116
117std::unique_ptr<GreasePencilStrokeOperation> new_weight_paint_average_operation()
118{
119 return std::make_unique<AverageWeightPaintOperation>();
120}
121
122} // namespace blender::ed::sculpt_paint::greasepencil
Scene * CTX_data_scene(const bContext *C)
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
#define C
Definition RandGen.cpp:29
#define NC_GEOM
Definition WM_types.hh:393
#define ND_DATA
Definition WM_types.hh:509
int64_t size() const
Definition BLI_array.hh:256
IndexRange index_range() const
Definition BLI_array.hh:360
void on_stroke_begin(const bContext &C, const InputSample &start_sample) override
void on_stroke_extended(const bContext &C, const InputSample &extension_sample) override
void get_mouse_input_sample(const InputSample &input_sample, const float brush_widen_factor=1.0f)
void get_brush_settings(const bContext &C, const InputSample &start_sample)
void init_weight_data_for_drawings(const bContext &C, const Span< ed::greasepencil::MutableDrawingInfo > &drawings, const int frame_group)
void apply_weight_to_point(const BrushPoint &point, const float target_weight, DrawingWeightData &drawing_weight)
void normalize_vertex_weights(MDeformVert &dvert, const int active_vertex_group, const Span< bool > vertex_group_is_locked, const Span< bool > vertex_group_is_bone_deformed)
Array< Vector< MutableDrawingInfo > > retrieve_editable_drawings_grouped_per_frame(const Scene &scene, GreasePencil &grease_pencil)
std::unique_ptr< GreasePencilStrokeOperation > new_weight_paint_average_operation()
T clamp(const T &a, const T &min, const T &max)
void parallel_for_each(Range &&range, const Function &function)
Definition BLI_task.hh:56
void WM_event_add_notifier(const bContext *C, uint type, void *reference)