32using ed::greasepencil::MutableDrawingInfo;
45 bool active_layer_only_;
56 const float2 mouse_position,
64 const float2 mouse_position,
65 const float fill_strength,
80 if (
brush->gpencil_settings ==
nullptr) {
87 radius_ =
brush->size / 2.0f;
88 strength_ =
brush->alpha;
92 color_linear[3] = 1.0f;
100 if (active_layer_only_) {
102 const Layer *active_layer = grease_pencil.get_active_layer();
107 *scene, grease_pencil, *active_layer);
114 if (drawings_.is_empty()) {
122 screen_positions_per_drawing_.reinitialize(drawings_.size());
125 const int drawing_index = (&drawing_info - drawings_.data());
130 screen_positions_per_drawing_[drawing_index].reinitialize(strokes.
points_num());
134 ob_eval, *obact, drawing_info.
drawing);
140 screen_positions_per_drawing_[drawing_index][point],
150 const float2 mouse_position,
152 const float strength,
157 for (const int curve : curves) {
158 std::atomic<bool> changed = false;
159 threading::parallel_for(points_by_curve[curve], 4096, [&](const IndexRange points) {
160 for (const int point : points) {
161 const float distance = math::distance(screen_space_positions[point], mouse_position);
162 const float influence = strength * BKE_brush_curve_strength(brush, distance, radius);
163 if (influence <= 0.0f) {
168 float &alpha = vertex_colors[point][3];
170 alpha = math::max(alpha, 0.0f);
176 float4 premultiplied;
177 straight_to_premul_v4_v4(premultiplied, vertex_colors[point]);
178 float4 rgba = float4(
179 math::interpolate(float3(premultiplied), float3(color_), influence),
180 vertex_colors[point][3]);
181 rgba[3] = rgba[3] * (1.0f - influence) + influence;
182 premul_to_straight_v4_v4(vertex_colors[point], rgba);
185 changed.store(true, std::memory_order_relaxed);
189 touched_strokes[curve] = changed;
197 const float2 mouse_position,
198 const float fill_strength,
204 if (!bbox.has_value()) {
208 if (mouse.x < box.
min.x || mouse.x > box.
max.x || mouse.y < box.
min.y || mouse.y > box.
max.y) {
212 mouse,
reinterpret_cast<const float (*)[2]
>(points.
data()), points.
size());
216 for (const int curve : curves) {
217 const IndexRange points = points_by_curve[curve];
218 const bool stroke_touched = touched_strokes[curve];
219 const bool fill_effective = stroke_touched ||
220 point_inside_stroke(screen_space_positions.slice(points),
222 if (!fill_effective) {
227 float &alpha = fill_colors[curve][3];
228 alpha -= fill_strength;
229 alpha = math::max(alpha, 0.0f);
232 float4 premultiplied;
233 straight_to_premul_v4_v4(premultiplied, fill_colors[curve]);
234 float4 rgba = float4(
235 math::interpolate(float3(premultiplied), float3(color_), fill_strength),
236 fill_colors[curve][3]);
237 rgba[3] = rgba[3] * (1.0f - fill_strength) + fill_strength;
238 premul_to_straight_v4_v4(fill_colors[curve], rgba);
241 touched_strokes[curve] = true;
246void TintOperation::execute_tint(
const bContext &
C,
const InputSample &extension_sample)
248 if (drawings_.is_empty()) {
252 using namespace blender::bke::greasepencil;
260 const float2 mouse_position = extension_sample.mouse_position;
261 float radius = radius_;
262 float strength = strength_;
272 float fill_strength = strength / 100.0f;
275 fill_strength =
math::clamp(fill_strength, 0.0f, 1.0f);
277 const bool tint_strokes =
ELEM(
279 const bool tint_fills =
ELEM(
284 std::atomic<bool> changed =
false;
285 const auto execute_tint_on_drawing = [&](Drawing &drawing,
const int drawing_index) {
292 const Span<float2> screen_space_positions =
293 screen_positions_per_drawing_[drawing_index].as_span();
295 Array<bool> touched_strokes(strokes.
curves_num(),
false);
297 this->tint_strokes(strokes,
300 screen_space_positions,
305 touched_strokes.as_mutable_span());
308 if (tint_fills && !fill_colors.
is_empty()) {
309 this->tint_fills(strokes,
311 screen_space_positions,
315 touched_strokes.as_mutable_span());
318 for (
const bool touched : touched_strokes) {
320 changed.store(
true, std::memory_order_relaxed);
327 const int drawing_index = (&info - drawings_.data());
328 execute_tint_on_drawing(info.
drawing, drawing_index);
339 execute_tint(
C, extension_sample);
346 return std::make_unique<TintOperation>(temp_eraser);
bool BKE_brush_use_alpha_pressure(const Brush *brush)
const float * BKE_brush_color_get(const Paint *paint, const Brush *brush)
bool BKE_brush_use_size_pressure(const Brush *brush)
void BKE_brush_init_gpencil_settings(Brush *brush)
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
Low-level operations for curves.
Low-level operations for grease pencil.
General operations, lookup, etc. for materials.
Paint * BKE_paint_get_active_from_context(const bContext *C)
Brush * BKE_paint_brush(Paint *paint)
bool isect_point_poly_v2(const float pt[2], const float verts[][2], unsigned int nr)
MINLINE void copy_v3_v3(float r[3], const float a[3])
void DEG_id_tag_update(ID *id, unsigned int flags)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
@ GP_BRUSH_ACTIVE_LAYER_ONLY
struct GreasePencil GreasePencil
eV3DProjStatus ED_view3d_project_float_global(const ARegion *region, const float co[3], float r_co[2], eV3DProjTest flag)
BPy_StructRNA * depsgraph
bke::CurvesGeometry & strokes_for_write()
MutableSpan< ColorGeometry4f > fill_colors_for_write()
MutableSpan< ColorGeometry4f > vertex_colors_for_write()
constexpr bool is_empty() const
constexpr const T * data() const
constexpr int64_t size() const
OffsetIndices< int > points_by_curve() const
IndexRange curves_range() const
IndexRange points_range() const
bke::CurvesGeometry & strokes_for_write()
float4x4 to_world_space(const Object &object) const
TintOperation(bool temp_eraser=false)
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 on_stroke_done(const bContext &C) override
GeometryDeformation get_evaluated_grease_pencil_drawing_deformation(const Object *ob_eval, const Object &ob_orig, const bke::greasepencil::Drawing &drawing_orig)
std::optional< Bounds< T > > min_max(const std::optional< Bounds< T > > &a, const T &b)
Vector< MutableDrawingInfo > retrieve_editable_drawings_from_layer(const Scene &scene, GreasePencil &grease_pencil, const blender::bke::greasepencil::Layer &layer)
Vector< MutableDrawingInfo > retrieve_editable_drawings(const Scene &scene, GreasePencil &grease_pencil)
std::unique_ptr< GreasePencilStrokeOperation > new_tint_operation(bool temp_eraser=false)
T clamp(const T &a, const T &min, const T &max)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
void parallel_for_each(Range &&range, const Function &function)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
VecBase< float, 4 > float4
VecBase< float, 2 > float2
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
struct CurveMapping * curve_sensitivity
struct CurveMapping * curve_strength
struct BrushGpencilSettings * gpencil_settings
struct ToolSettings * toolsettings
bke::greasepencil::Drawing & drawing
bke::greasepencil::Drawing & drawing
void WM_event_add_notifier(const bContext *C, uint type, void *reference)