Blender V4.3
grease_pencil_vertex_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
5#include "BKE_brush.hh"
6#include "BKE_context.hh"
7#include "BKE_curves.hh"
9#include "BKE_paint.hh"
10
12
14
17
18 public:
19 void on_stroke_begin(const bContext &C, const InputSample &start_sample) override;
20 void on_stroke_extended(const bContext &C, const InputSample &extension_sample) override;
21 void on_stroke_done(const bContext &C) override;
22};
23
25{
26 this->init_stroke(C, start_sample);
27 this->on_stroke_extended(C, start_sample);
28}
29
31 const InputSample &extension_sample)
32{
33 const Scene &scene = *CTX_data_scene(&C);
35 const Brush &brush = *BKE_paint_brush(&paint);
36 const float radius = brush_radius(scene, brush, extension_sample.pressure);
37 const float radius_squared = radius * radius;
38
39 const bool is_masking = GPENCIL_ANY_VERTEX_MASK(
40 eGP_vertex_SelectMaskFlag(scene.toolsettings->gpencil_selectmode_vertex));
41
42 const bool do_points = do_vertex_color_points(brush);
43 const bool do_fill = do_vertex_color_fill(brush);
44
45 /* Compute the average color under the brush. */
46 float3 average_color;
47 int color_count = 0;
49 IndexMaskMemory memory;
50 const IndexMask point_selection = point_selection_mask(params, is_masking, memory);
51 if (!point_selection.is_empty() && do_points) {
52 const Array<float2> view_positions = calculate_view_positions(params, point_selection);
53 const VArray<ColorGeometry4f> vertex_colors = params.drawing.vertex_colors();
54
55 point_selection.foreach_index([&](const int64_t point_i) {
56 const ColorGeometry4f color = vertex_colors[point_i];
57 if (color.a > 0.0f && math::distance_squared(extension_sample.mouse_position,
58 view_positions[point_i]) < radius_squared)
59 {
60 average_color += float3(color.r, color.g, color.b);
61 color_count++;
62 }
63 });
64 }
65 const IndexMask fill_selection = fill_selection_mask(params, is_masking, memory);
66 if (!fill_selection.is_empty() && do_fill) {
67 const OffsetIndices<int> points_by_curve = params.drawing.strokes().points_by_curve();
68 const Array<float2> view_positions = calculate_view_positions(params, point_selection);
69 const VArray<ColorGeometry4f> fill_colors = params.drawing.fill_colors();
70
71 fill_selection.foreach_index([&](const int64_t curve_i) {
72 const IndexRange points = points_by_curve[curve_i];
73 const Span<float2> curve_view_positions = view_positions.as_span().slice(points);
74 const ColorGeometry4f color = fill_colors[curve_i];
75 if (color.a > 0.0f && closest_distance_to_surface_2d(extension_sample.mouse_position,
76 curve_view_positions) < radius)
77 {
78 average_color += float3(color.r, color.g, color.b);
79 color_count++;
80 }
81 });
82 }
83 return true;
84 });
85
86 if (color_count <= 0) {
87 return;
88 }
89 average_color = average_color / color_count;
90 /* The average color is the color that will be mixed in. */
91 const ColorGeometry4f mix_color(average_color.x, average_color.y, average_color.z, 1.0f);
92
94 IndexMaskMemory memory;
95 const IndexMask point_selection = point_selection_mask(params, is_masking, memory);
96 if (!point_selection.is_empty() && do_points) {
97 const Array<float2> view_positions = calculate_view_positions(params, point_selection);
98 MutableSpan<ColorGeometry4f> vertex_colors = params.drawing.vertex_colors_for_write();
99
100 point_selection.foreach_index(GrainSize(4096), [&](const int64_t point_i) {
101 const float influence = brush_point_influence(
102 scene, brush, view_positions[point_i], extension_sample, params.multi_frame_falloff);
103
104 ColorGeometry4f &color = vertex_colors[point_i];
105 color = math::interpolate(color, mix_color, influence);
106 });
107 }
108
109 const IndexMask fill_selection = fill_selection_mask(params, is_masking, memory);
110 if (!fill_selection.is_empty() && do_fill) {
111 const OffsetIndices<int> points_by_curve = params.drawing.strokes().points_by_curve();
112 const Array<float2> view_positions = calculate_view_positions(params, point_selection);
113 MutableSpan<ColorGeometry4f> fill_colors = params.drawing.fill_colors_for_write();
114
115 fill_selection.foreach_index(GrainSize(1024), [&](const int64_t curve_i) {
116 const IndexRange points = points_by_curve[curve_i];
117 const Span<float2> curve_view_positions = view_positions.as_span().slice(points);
118 const float influence = brush_fill_influence(
119 scene, brush, curve_view_positions, extension_sample, params.multi_frame_falloff);
120
121 ColorGeometry4f &color = fill_colors[curve_i];
122 color = math::interpolate(color, mix_color, influence);
123 });
124 }
125 return true;
126 });
127}
128
130
131std::unique_ptr<GreasePencilStrokeOperation> new_vertex_average_operation()
132{
133 return std::make_unique<VertexAverageOperation>();
134}
135
136} // 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
#define GPENCIL_ANY_VERTEX_MASK(flag)
eGP_vertex_SelectMaskFlag
Span< T > as_span() const
Definition BLI_array.hh:232
void foreach_editable_drawing(const bContext &C, FunctionRef< bool(const GreasePencilStrokeParams &params)> fn) const
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 foreach_index(Fn &&fn) const
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
float closest_distance_to_surface_2d(const float2 pt, const Span< float2 > verts)
IndexMask point_selection_mask(const GreasePencilStrokeParams &params, const bool use_masking, IndexMaskMemory &memory)
Array< float2 > calculate_view_positions(const GreasePencilStrokeParams &params, const IndexMask &selection)
IndexMask fill_selection_mask(const GreasePencilStrokeParams &params, const bool use_masking, IndexMaskMemory &memory)
float brush_point_influence(const Scene &scene, const Brush &brush, const float2 &co, const InputSample &sample, float multi_frame_falloff)
float brush_fill_influence(const Scene &scene, const Brush &brush, Span< float2 > fill_positions, const InputSample &sample, float multi_frame_falloff)
std::unique_ptr< GreasePencilStrokeOperation > new_vertex_average_operation()
float brush_radius(const Scene &scene, const Brush &brush, float pressure)
T interpolate(const T &a, const T &b, const FactorT &t)
T distance_squared(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
__int64 int64_t
Definition stdint.h:89