12 bool brush_direction_is_set;
16 bool get_brush_direction()
22 return this->brush_direction_is_set;
26 this->brush_direction_is_set =
true;
39 const int point_num = BLI_kdtree_2d_find_nearest_n(
49 int smear_point_num = 0;
57 float2(nearest_points[i].co));
60 point_dot_product[i] =
math::dot(direction_nearest_to_point, this->brush_direction);
61 if (point_dot_product[i] <= 0.0f) {
65 min_distance =
math::min(min_distance, nearest_points[i].dist);
66 max_distance =
math::max(max_distance, nearest_points[i].dist);
68 if (smear_point_num == 0) {
74 float max_score = 0.0f;
75 const float distance_normalizer = (min_distance == max_distance) ?
77 (0.95f / (max_distance - min_distance));
79 if (point_dot_product[i] <= 0.0f) {
82 const float score = point_dot_product[i] *
83 (1.0f - (nearest_points[i].dist - min_distance) * distance_normalizer);
84 if (score > max_score) {
89 if (best_match == -1) {
92 const float smear_weight = touched_points.
weights[nearest_points[best_match].index];
112 retrieve_editable_drawings_grouped_per_frame(*scene, *this->
grease_pencil);
117 for (
const int frame_group : drawings_per_frame.
index_range()) {
131 if (!this->get_brush_direction()) {
138 std::atomic<bool> changed =
false;
141 Array<DrawingWeightData> &drawing_weights = this->drawing_weight_data[frame_group];
145 threading::parallel_for_each(drawing_weights, [&](DrawingWeightData &drawing_weight) {
146 for (const int point_index : drawing_weight.point_positions.index_range()) {
147 const float2 &co = drawing_weight.point_positions[point_index];
150 this->add_point_under_brush_to_brush_buffer(co, drawing_weight, point_index);
162 this->apply_smear_tool(point, drawing_weight, touched_points);
166 normalize_vertex_weights(drawing_weight.
deform_verts[point.drawing_point_index],
179 BLI_kdtree_2d_free(touched_points.
kdtree);
193 return std::make_unique<SmearWeightPaintOperation>();
Scene * CTX_data_scene(const bContext *C)
void DEG_id_tag_update(ID *id, unsigned int flags)
IndexRange index_range() const
void on_stroke_extended(const bContext &C, const InputSample &extension_sample) override
void on_stroke_done(const bContext &) override
void on_stroke_begin(const bContext &C, const InputSample &start_sample) override
void ensure_active_vertex_group_in_object()
void get_mouse_input_sample(const InputSample &input_sample, const float brush_widen_factor=1.0f)
Array< Array< DrawingWeightData > > drawing_weight_data
PointsTouchedByBrush create_affected_points_kdtree(const Span< DrawingWeightData > drawing_weights)
float2 mouse_position_previous
void get_brush_settings(const bContext &C, const InputSample &start_sample)
void get_locked_and_bone_deformed_vertex_groups()
GreasePencil * grease_pencil
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)
std::unique_ptr< GreasePencilStrokeOperation > new_weight_paint_smear_operation()
static constexpr float FIND_NEAREST_POINT_EPSILON
static constexpr int SMEAR_NEIGHBOUR_NUM
T length_squared(const VecBase< T, Size > &a)
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
T min(const T &a, const T &b)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
T max(const T &a, const T &b)
void parallel_for_each(Range &&range, const Function &function)
Vector< bool > locked_vgroups
Vector< BrushPoint > points_in_brush
MutableSpan< MDeformVert > deform_verts
Array< float2 > point_positions
Vector< bool > bone_deformed_vgroups
void WM_event_add_notifier(const bContext *C, uint type, void *reference)