Blender V4.3
grease_pencil/intern/grease_pencil_vertex_paint.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
8
9#include "BKE_brush.hh"
10#include "BKE_context.hh"
11#include "BKE_curves.hh"
12#include "BKE_grease_pencil.hh"
13#include "BKE_paint.hh"
14#include "BKE_report.hh"
15
17
18#include "RNA_access.hh"
19#include "RNA_define.hh"
20
21#include "ED_curves.hh"
22#include "ED_grease_pencil.hh"
23
25
26enum class VertexColorMode : int8_t {
27 Stroke = 0,
28 Fill = 1,
29 Both = 2,
30};
31
33 {int(VertexColorMode::Stroke), "STROKE", 0, "Stroke", ""},
34 {int(VertexColorMode::Fill), "FILL", 0, "Fill", ""},
35 {int(VertexColorMode::Both), "BOTH", 0, "Stroke & Fill", ""},
36 {0, nullptr, 0, nullptr, nullptr},
37};
38
39template<typename Fn>
41 Object &object,
43 Fn &&fn)
44{
45 bool changed = false;
46 IndexMaskMemory memory;
48 if (info.drawing.strokes().attributes().contains("vertex_color")) {
50 object, info.drawing, info.layer_index, memory);
51 if (!points.is_empty()) {
53 points.foreach_index(GrainSize(4096), [&](const int64_t point_i) {
54 ColorGeometry4f &color = vertex_colors[point_i];
55 if (color.a > 0.0f) {
56 color = fn(color);
57 }
58 });
59 changed = true;
60 }
61 }
62 }
64 if (info.drawing.strokes().attributes().contains("fill_color")) {
66 object, info.drawing, info.layer_index, memory);
67 if (!strokes.is_empty()) {
69 strokes.foreach_index(GrainSize(1024), [&](const int64_t curve_i) {
70 ColorGeometry4f &color = fill_colors[curve_i];
71 if (color.a > 0.0f) {
72 color = fn(color);
73 }
74 });
75 changed = true;
76 }
77 }
78 }
79 return changed;
80}
81
83{
84 const Scene &scene = *CTX_data_scene(C);
86 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object.data);
87 const VertexColorMode mode = VertexColorMode(RNA_enum_get(op->ptr, "mode"));
88 const float brightness = RNA_float_get(op->ptr, "brightness");
89 const float contrast = RNA_float_get(op->ptr, "contrast");
90 float delta = contrast / 2.0f;
91 /*
92 * The algorithm is by Werner D. Streidt
93 * (http://visca.com/ffactory/archives/5-99/msg00021.html)
94 * Extracted of OpenCV `demhist.c`.
95 */
96 float gain, offset;
97 if (contrast > 0.0f) {
98 gain = 1.0f - delta * 2.0f;
99 gain = 1.0f / math::max(gain, FLT_EPSILON);
100 offset = gain * (brightness - delta);
101 }
102 else {
103 delta *= -1.0f;
104 gain = math::max(1.0f - delta * 2.0f, 0.0f);
105 offset = gain * brightness + delta;
106 }
107
108 std::atomic<bool> any_changed;
109 Vector<MutableDrawingInfo> drawings = retrieve_editable_drawings(scene, grease_pencil);
112 if (curves.curves_num() == 0) {
113 return;
114 }
115 const bool changed = apply_color_operation_for_mode(
116 mode, object, info, [&](const ColorGeometry4f &color) -> ColorGeometry4f {
117 const float3 result = float3(color) * gain + offset;
118 return ColorGeometry4f(result[0], result[1], result[2], color.a);
119 });
120 any_changed.store(any_changed | changed, std::memory_order_relaxed);
121 });
122
123 if (any_changed) {
124 DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
125 WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
126 }
127 return OPERATOR_FINISHED;
128}
129
131{
132 /* identifiers */
133 ot->name = "Vertex Paint Brightness/Contrast";
134 ot->idname = "GREASE_PENCIL_OT_vertex_color_brightness_contrast";
135 ot->description = "Adjust vertex color brightness/contrast";
136
137 /* api callbacks */
140
141 /* flags */
143
144 /* params */
145 ot->prop = RNA_def_enum(
146 ot->srna, "mode", prop_grease_pencil_vertex_mode, int(VertexColorMode::Both), "Mode", "");
147
148 RNA_def_float(ot->srna, "brightness", 0.0f, -1.0f, 1.0f, "Brightness", "", -1.0f, 1.0f);
149 RNA_def_float(ot->srna, "contrast", 0.0f, -1.0f, 1.0f, "Contrast", "", -1.0f, 1.0f);
150}
151
153{
154 const Scene &scene = *CTX_data_scene(C);
155 Object &object = *CTX_data_active_object(C);
156 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object.data);
157 const VertexColorMode mode = VertexColorMode(RNA_enum_get(op->ptr, "mode"));
158 const float hue = RNA_float_get(op->ptr, "h");
159 const float sat = RNA_float_get(op->ptr, "s");
160 const float val = RNA_float_get(op->ptr, "v");
161
162 std::atomic<bool> any_changed;
163 Vector<MutableDrawingInfo> drawings = retrieve_editable_drawings(scene, grease_pencil);
166 if (curves.curves_num() == 0) {
167 return;
168 }
169 const bool changed = apply_color_operation_for_mode(
170 mode, object, info, [&](const ColorGeometry4f &color) -> ColorGeometry4f {
171 float3 hsv;
173
174 hsv[0] += (hue - 0.5f);
175 if (hsv[0] > 1.0f) {
176 hsv[0] -= 1.0f;
177 }
178 else if (hsv[0] < 0.0f) {
179 hsv[0] += 1.0f;
180 }
181 hsv[1] *= sat;
182 hsv[2] *= val;
183
184 float3 rgb_result;
185 hsv_to_rgb_v(hsv, rgb_result);
186 return ColorGeometry4f(rgb_result[0], rgb_result[1], rgb_result[2], color.a);
187 });
188 any_changed.store(any_changed | changed, std::memory_order_relaxed);
189 });
190
191 if (any_changed) {
192 DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
193 WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
194 }
195 return OPERATOR_FINISHED;
196}
197
199{
200 /* identifiers */
201 ot->name = "Vertex Paint Hue/Saturation/Value";
202 ot->idname = "GREASE_PENCIL_OT_vertex_color_hsv";
203 ot->description = "Adjust vertex color HSV values";
204
205 /* api callbacks */
208
209 /* flags */
211
212 /* params */
213 ot->prop = RNA_def_enum(
214 ot->srna, "mode", prop_grease_pencil_vertex_mode, int(VertexColorMode::Both), "Mode", "");
215 RNA_def_float(ot->srna, "h", 0.5f, 0.0f, 1.0f, "Hue", "", 0.0f, 1.0f);
216 RNA_def_float(ot->srna, "s", 1.0f, 0.0f, 2.0f, "Saturation", "", 0.0f, 2.0f);
217 RNA_def_float(ot->srna, "v", 1.0f, 0.0f, 2.0f, "Value", "", 0.0f, 2.0f);
218}
219
221{
222 const Scene &scene = *CTX_data_scene(C);
223 Object &object = *CTX_data_active_object(C);
224 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object.data);
225 const VertexColorMode mode = VertexColorMode(RNA_enum_get(op->ptr, "mode"));
226
227 std::atomic<bool> any_changed;
228 Vector<MutableDrawingInfo> drawings = retrieve_editable_drawings(scene, grease_pencil);
231 if (curves.curves_num() == 0) {
232 return;
233 }
234 const bool changed = apply_color_operation_for_mode(
235 mode, object, info, [&](const ColorGeometry4f &color) -> ColorGeometry4f {
236 /* Invert the color. */
237 return ColorGeometry4f(1.0f - color.r, 1.0f - color.g, 1.0f - color.b, color.a);
238 });
239 any_changed.store(any_changed | changed, std::memory_order_relaxed);
240 });
241
242 if (any_changed) {
243 DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
244 WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
245 }
246 return OPERATOR_FINISHED;
247}
248
250{
251 /* identifiers */
252 ot->name = "Vertex Paint Invert";
253 ot->idname = "GREASE_PENCIL_OT_vertex_color_invert";
254 ot->description = "Invert RGB values";
255
256 /* api callbacks */
259
260 /* flags */
262
263 /* params */
264 ot->prop = RNA_def_enum(
265 ot->srna, "mode", prop_grease_pencil_vertex_mode, int(VertexColorMode::Both), "Mode", "");
266}
267
269{
270 const Scene &scene = *CTX_data_scene(C);
271 Object &object = *CTX_data_active_object(C);
272 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object.data);
273 const VertexColorMode mode = VertexColorMode(RNA_enum_get(op->ptr, "mode"));
274 const float gain = RNA_float_get(op->ptr, "gain");
275 const float offset = RNA_float_get(op->ptr, "offset");
276
277 std::atomic<bool> any_changed;
278 Vector<MutableDrawingInfo> drawings = retrieve_editable_drawings(scene, grease_pencil);
281 if (curves.curves_num() == 0) {
282 return;
283 }
284 const bool changed = apply_color_operation_for_mode(
285 mode, object, info, [&](const ColorGeometry4f &color) -> ColorGeometry4f {
286 const float3 result = float3(color) * gain + offset;
287 return ColorGeometry4f(result[0], result[1], result[2], color.a);
288 });
289 any_changed.store(any_changed | changed, std::memory_order_relaxed);
290 });
291
292 if (any_changed) {
293 DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
294 WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
295 }
296 return OPERATOR_FINISHED;
297}
298
300{
301 /* identifiers */
302 ot->name = "Vertex Paint Levels";
303 ot->idname = "GREASE_PENCIL_OT_vertex_color_levels";
304 ot->description = "Adjust levels of vertex colors";
305
306 /* api callbacks */
309
310 /* flags */
312
313 /* params */
314 ot->prop = RNA_def_enum(
315 ot->srna, "mode", prop_grease_pencil_vertex_mode, int(VertexColorMode::Both), "Mode", "");
316
318 ot->srna, "offset", 0.0f, -1.0f, 1.0f, "Offset", "Value to add to colors", -1.0f, 1.0f);
320 ot->srna, "gain", 1.0f, 0.0f, FLT_MAX, "Gain", "Value to multiply colors by", 0.0f, 10.0f);
321}
322
324{
325 const Scene &scene = *CTX_data_scene(C);
326 Object &object = *CTX_data_active_object(C);
328 const Brush &brush = *BKE_paint_brush(&paint);
329 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object.data);
330 const VertexColorMode mode = VertexColorMode(RNA_enum_get(op->ptr, "mode"));
331 const float factor = RNA_float_get(op->ptr, "factor");
332
333 float3 color_linear;
334 srgb_to_linearrgb_v3_v3(color_linear, BKE_brush_color_get(&scene, &paint, &brush));
335 const ColorGeometry4f target_color(color_linear[0], color_linear[1], color_linear[2], 1.0f);
336
337 std::atomic<bool> any_changed;
338 Vector<MutableDrawingInfo> drawings = retrieve_editable_drawings(scene, grease_pencil);
341 if (curves.curves_num() == 0) {
342 return;
343 }
344 /* Create the color attributes if they don't exist. */
346 curves.attributes_for_write().add<ColorGeometry4f>(
348 }
350 curves.attributes_for_write().add<ColorGeometry4f>(
352 }
353 const bool changed = apply_color_operation_for_mode(
354 mode, object, info, [&](const ColorGeometry4f &color) -> ColorGeometry4f {
355 /* Mix in the target color based on the factor. */
356 return math::interpolate(color, target_color, factor);
357 });
358 any_changed.store(any_changed | changed, std::memory_order_relaxed);
359 });
360
361 if (any_changed) {
362 DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
363 WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
364 }
365 return OPERATOR_FINISHED;
366}
367
369{
370 /* identifiers */
371 ot->name = "Vertex Paint Set Color";
372 ot->idname = "GREASE_PENCIL_OT_vertex_color_set";
373 ot->description = "Set active color to all selected vertex";
374
375 /* api callbacks */
378
379 /* flags */
381
382 /* params */
383 ot->prop = RNA_def_enum(
384 ot->srna, "mode", prop_grease_pencil_vertex_mode, int(VertexColorMode::Both), "Mode", "");
385 RNA_def_float(ot->srna, "factor", 1.0f, 0.0f, 1.0f, "Factor", "Mix Factor", 0.0f, 1.0f);
386}
387
389{
390 const Scene &scene = *CTX_data_scene(C);
391 Object &object = *CTX_data_active_object(C);
392 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object.data);
393 const VertexColorMode mode = VertexColorMode(RNA_enum_get(op->ptr, "mode"));
394
395 std::atomic<bool> any_changed;
396 Vector<MutableDrawingInfo> drawings = retrieve_editable_drawings(scene, grease_pencil);
399 if (curves.curves_num() == 0) {
400 return;
401 }
402 /* Remove the color attributes. */
403 bool changed = false;
405 changed |= curves.attributes_for_write().remove("vertex_color");
406 }
408 changed |= curves.attributes_for_write().remove("fill_color");
409 }
410 any_changed.store(any_changed | changed, std::memory_order_relaxed);
411 });
412
413 if (any_changed) {
414 DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
415 WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
416 }
417 return OPERATOR_FINISHED;
418}
419
421{
422 /* identifiers */
423 ot->name = "Reset Vertex Color";
424 ot->idname = "GREASE_PENCIL_OT_stroke_reset_vertex_color";
425 ot->description = "Reset vertex color for all or selected strokes";
426
427 /* callbacks */
430
431 /* flags */
433
434 /* properties */
435 ot->prop = RNA_def_enum(
436 ot->srna, "mode", prop_grease_pencil_vertex_mode, int(VertexColorMode::Both), "Mode", "");
437}
438
439} // namespace blender::ed::greasepencil
440
const float * BKE_brush_color_get(const Scene *scene, const Paint *paint, const Brush *brush)
Definition brush.cc:1029
Object * CTX_data_active_object(const bContext *C)
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
void hsv_to_rgb_v(const float hsv[3], float r_rgb[3])
Definition math_color.cc:57
void rgb_to_hsv_v(const float rgb[3], float r_hsv[3])
void srgb_to_linearrgb_v3_v3(float linear[3], const float srgb[3])
#define ELEM(...)
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1041
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its hue
#define C
Definition RandGen.cpp:29
#define NC_GEOM
Definition WM_types.hh:360
#define ND_DATA
Definition WM_types.hh:475
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_REGISTER
Definition WM_types.hh:160
bool contains(const StringRef attribute_id) const
bke::CurvesGeometry & strokes_for_write()
const bke::CurvesGeometry & strokes() const
MutableSpan< ColorGeometry4f > fill_colors_for_write()
MutableSpan< ColorGeometry4f > vertex_colors_for_write()
void foreach_index(Fn &&fn) const
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
static int grease_pencil_vertex_paint_invert_exec(bContext *C, wmOperator *op)
IndexMask retrieve_editable_points(Object &object, const bke::greasepencil::Drawing &drawing, int layer_index, IndexMaskMemory &memory)
static void GREASE_PENCIL_OT_vertex_color_levels(wmOperatorType *ot)
bool grease_pencil_vertex_painting_poll(bContext *C)
static int grease_pencil_vertex_paint_reset_exec(bContext *C, wmOperator *op)
static int grease_pencil_vertex_paint_levels_exec(bContext *C, wmOperator *op)
static int grease_pencil_vertex_paint_hsv_exec(bContext *C, wmOperator *op)
static void GREASE_PENCIL_OT_stroke_reset_vertex_color(wmOperatorType *ot)
static void GREASE_PENCIL_OT_vertex_color_brightness_contrast(wmOperatorType *ot)
static void GREASE_PENCIL_OT_vertex_color_set(wmOperatorType *ot)
static void GREASE_PENCIL_OT_vertex_color_invert(wmOperatorType *ot)
static int grease_pencil_vertex_paint_set_exec(bContext *C, wmOperator *op)
static void GREASE_PENCIL_OT_vertex_color_hsv(wmOperatorType *ot)
IndexMask retrieve_editable_strokes(Object &object, const bke::greasepencil::Drawing &drawing, int layer_index, IndexMaskMemory &memory)
Vector< MutableDrawingInfo > retrieve_editable_drawings(const Scene &scene, GreasePencil &grease_pencil)
static int grease_pencil_vertex_paint_brightness_contrast_exec(bContext *C, wmOperator *op)
static bool apply_color_operation_for_mode(const VertexColorMode mode, Object &object, MutableDrawingInfo &info, Fn &&fn)
T interpolate(const T &a, const T &b, const FactorT &t)
T max(const T &a, const T &b)
void parallel_for_each(Range &&range, const Function &function)
Definition BLI_task.hh:58
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
Definition BLI_color.hh:337
VecBase< float, 3 > float3
float RNA_float_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
#define FLT_MAX
Definition stdcycles.h:14
__int64 int64_t
Definition stdint.h:89
signed char int8_t
Definition stdint.h:75
struct PointerRNA * ptr
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition wm_files.cc:4125
void WM_operatortype_append(void(*opfunc)(wmOperatorType *))