Blender V4.3
MOD_grease_pencil_opacity.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
9#include "DNA_defaults.h"
10#include "DNA_modifier_types.h"
11
12#include "BKE_colortools.hh"
13#include "BKE_curves.hh"
14#include "BKE_geometry_set.hh"
15#include "BKE_grease_pencil.hh"
16#include "BKE_modifier.hh"
17
18#include "BLO_read_write.hh"
19
20#include "UI_interface.hh"
21#include "UI_resources.hh"
22
23#include "BLT_translation.hh"
24
25#include "WM_types.hh"
26
27#include "RNA_access.hh"
28#include "RNA_prototypes.hh"
29
31#include "MOD_ui_common.hh"
32
33namespace blender {
34
35using bke::greasepencil::Drawing;
37using bke::greasepencil::Layer;
38
39static void init_data(ModifierData *md)
40{
41 auto *omd = reinterpret_cast<GreasePencilOpacityModifierData *>(md);
42
44
47}
48
49static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
50{
51 const auto *omd = reinterpret_cast<const GreasePencilOpacityModifierData *>(md);
52 auto *tomd = reinterpret_cast<GreasePencilOpacityModifierData *>(target);
53
55
57 modifier::greasepencil::copy_influence_data(&omd->influence, &tomd->influence, flag);
58}
59
60static void free_data(ModifierData *md)
61{
62 auto *omd = reinterpret_cast<GreasePencilOpacityModifierData *>(md);
64}
65
66static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
67{
68 auto *omd = reinterpret_cast<GreasePencilOpacityModifierData *>(md);
69 modifier::greasepencil::foreach_influence_ID_link(&omd->influence, ob, walk, user_data);
70}
71
73 bke::CurvesGeometry &curves,
74 const IndexMask &curves_mask)
75{
76 const bool use_uniform_opacity = (omd.flag & MOD_GREASE_PENCIL_OPACITY_USE_UNIFORM_OPACITY);
77 const bool use_weight_as_factor = (omd.flag & MOD_GREASE_PENCIL_OPACITY_USE_WEIGHT_AS_FACTOR);
78 const bool invert_vertex_group = (omd.influence.flag &
80 const bool use_curve = (omd.influence.flag & GREASE_PENCIL_INFLUENCE_USE_CUSTOM_CURVE);
81 const OffsetIndices<int> points_by_curve = curves.points_by_curve();
82
83 bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
84 bke::SpanAttributeWriter<float> opacities = attributes.lookup_or_add_for_write_span<float>(
85 "opacity", bke::AttrDomain::Point);
87 curves, omd.influence);
88
89 curves_mask.foreach_index(GrainSize(512), [&](const int64_t curve_i) {
90 const IndexRange points = points_by_curve[curve_i];
91 for (const int64_t point_i : points) {
92 const float curve_input = points.size() >= 2 ?
93 (float(point_i - points.first()) / float(points.size() - 1)) :
94 0.0f;
95 const float curve_factor = use_curve ? BKE_curvemapping_evaluateF(
96 omd.influence.custom_curve, 0, curve_input) :
97 1.0f;
98
99 if (use_uniform_opacity) {
100 opacities.span[point_i] = std::clamp(omd.color_factor * curve_factor, 0.0f, 1.0f);
101 }
102 else if (use_weight_as_factor) {
103 /* Use vertex group weights as opacity factors. */
104 opacities.span[point_i] = std::clamp(
105 omd.color_factor * curve_factor * vgroup_weights[point_i], 0.0f, 1.0f);
106 }
107 else {
108 /* Use vertex group weights as influence factors. */
109 const float vgroup_weight = vgroup_weights[point_i];
110 const float vgroup_influence = invert_vertex_group ? 1.0f - vgroup_weight : vgroup_weight;
111 opacities.span[point_i] = std::clamp(
112 opacities.span[point_i] + (omd.color_factor * curve_factor - 1.0f) * vgroup_influence,
113 0.0f,
114 1.0f);
115 }
116 }
117 });
118
119 opacities.finish();
120}
121
123 bke::CurvesGeometry &curves,
124 const IndexMask &curves_mask)
125{
126 const bool use_vgroup_opacity = (omd.flag & MOD_GREASE_PENCIL_OPACITY_USE_WEIGHT_AS_FACTOR);
127 const bool invert_vertex_group = (omd.influence.flag &
129 const OffsetIndices<int> points_by_curve = curves.points_by_curve();
130
131 bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
132 /* Fill color opacity per stroke. */
133 bke::SpanAttributeWriter<float> fill_opacities = attributes.lookup_or_add_for_write_span<float>(
134 "fill_opacity",
136 bke::AttributeInitVArray(VArray<float>::ForSingle(1.0f, curves.curves_num())));
138 curves, omd.influence);
139
140 curves_mask.foreach_index(GrainSize(512), [&](int64_t curve_i) {
141 if (use_vgroup_opacity) {
142 /* Use the first stroke point as vertex weight. */
143 const IndexRange points = points_by_curve[curve_i];
144 const float stroke_weight = points.is_empty() ? 1.0f : vgroup_weights[points.first()];
145 const float stroke_influence = invert_vertex_group ? 1.0f - stroke_weight : stroke_weight;
146
147 fill_opacities.span[curve_i] = std::clamp(stroke_influence, 0.0f, 1.0f);
148 }
149 else {
150 fill_opacities.span[curve_i] = std::clamp(omd.color_factor, 0.0f, 1.0f);
151 }
152 });
153
154 fill_opacities.finish();
155}
156
158 bke::CurvesGeometry &curves,
159 const IndexMask &curves_mask)
160{
161 bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
162 bke::SpanAttributeWriter<float> softness = attributes.lookup_or_add_for_write_span<float>(
163 "softness", bke::AttrDomain::Curve);
164
165 curves_mask.foreach_index(GrainSize(512), [&](int64_t curve_i) {
166 softness.span[curve_i] =
167 1.0f - std::clamp((1.0f - softness.span[curve_i]) * omd.hardness_factor, 0.0f, 1.0f);
168 });
169
170 softness.finish();
171}
172
174 const ModifierEvalContext *ctx,
175 bke::CurvesGeometry &curves)
176{
177 const auto *omd = reinterpret_cast<GreasePencilOpacityModifierData *>(md);
178
179 IndexMaskMemory mask_memory;
181 ctx->object, curves, omd->influence, mask_memory);
182
183 switch (omd->color_mode) {
185 modify_stroke_color(*omd, curves, curves_mask);
186 break;
188 modify_fill_color(*omd, curves, curves_mask);
189 break;
191 modify_stroke_color(*omd, curves, curves_mask);
192 modify_fill_color(*omd, curves, curves_mask);
193 break;
195 modify_softness(*omd, curves, curves_mask);
196 break;
197 }
198}
199
201 const ModifierEvalContext *ctx,
202 bke::GeometrySet *geometry_set)
203{
204 const auto *omd = reinterpret_cast<GreasePencilOpacityModifierData *>(md);
205
206 GreasePencil *grease_pencil = geometry_set->get_grease_pencil_for_write();
207 if (grease_pencil == nullptr) {
208 return;
209 }
210
211 IndexMaskMemory mask_memory;
213 *grease_pencil, omd->influence, mask_memory);
214 const int frame = grease_pencil->runtime->eval_frame;
216 *grease_pencil, layer_mask, frame);
218 drawings, [&](Drawing *drawing) { modify_curves(md, ctx, drawing->strokes_for_write()); });
219}
220
221static void panel_draw(const bContext *C, Panel *panel)
222{
223 uiLayout *layout = panel->layout;
224
225 PointerRNA ob_ptr;
227
228 uiLayoutSetPropSep(layout, true);
229
231 RNA_enum_get(ptr, "color_mode"));
232
233 uiItemR(layout, ptr, "color_mode", UI_ITEM_NONE, nullptr, ICON_NONE);
234
235 if (color_mode == MOD_GREASE_PENCIL_COLOR_HARDNESS) {
236 uiItemR(layout, ptr, "hardness_factor", UI_ITEM_NONE, nullptr, ICON_NONE);
237 }
238 else {
239 const bool use_uniform_opacity = RNA_boolean_get(ptr, "use_uniform_opacity");
240 const bool use_weight_as_factor = RNA_boolean_get(ptr, "use_weight_as_factor");
241
242 uiItemR(layout, ptr, "use_uniform_opacity", UI_ITEM_NONE, nullptr, ICON_NONE);
243 const char *text = (use_uniform_opacity) ? IFACE_("Opacity") : IFACE_("Opacity Factor");
244
245 uiLayout *row = uiLayoutRow(layout, true);
246 uiLayoutSetActive(row, !use_weight_as_factor || use_uniform_opacity);
247 uiItemR(row, ptr, "color_factor", UI_ITEM_NONE, text, ICON_NONE);
248 if (!use_uniform_opacity) {
249 uiLayout *sub = uiLayoutRow(row, true);
250 uiLayoutSetActive(sub, true);
251 uiItemR(row, ptr, "use_weight_as_factor", UI_ITEM_NONE, "", ICON_MOD_VERTEX_WEIGHT);
252 }
253 }
254
255 if (uiLayout *influence_panel = uiLayoutPanelProp(
256 C, layout, ptr, "open_influence_panel", IFACE_("Influence")))
257 {
262 }
263
264 modifier_panel_end(layout, ptr);
265}
266
271
272static void blend_write(BlendWriter *writer, const ID * /*id_owner*/, const ModifierData *md)
273{
274 const auto *omd = reinterpret_cast<const GreasePencilOpacityModifierData *>(md);
275
277 modifier::greasepencil::write_influence_data(writer, &omd->influence);
278}
279
280static void blend_read(BlendDataReader *reader, ModifierData *md)
281{
282 auto *omd = reinterpret_cast<GreasePencilOpacityModifierData *>(md);
283
284 modifier::greasepencil::read_influence_data(reader, &omd->influence);
285}
286
287} // namespace blender
288
290 /*idname*/ "GreasePencilOpacity",
291 /*name*/ N_("Opacity"),
292 /*struct_name*/ "GreasePencilOpacityModifierData",
293 /*struct_size*/ sizeof(GreasePencilOpacityModifierData),
294 /*srna*/ &RNA_GreasePencilOpacityModifier,
298 /*icon*/ ICON_MOD_OPACITY,
299
300 /*copy_data*/ blender::copy_data,
301
302 /*deform_verts*/ nullptr,
303 /*deform_matrices*/ nullptr,
304 /*deform_verts_EM*/ nullptr,
305 /*deform_matrices_EM*/ nullptr,
306 /*modify_mesh*/ nullptr,
307 /*modify_geometry_set*/ blender::modify_geometry_set,
308
309 /*init_data*/ blender::init_data,
310 /*required_data_mask*/ nullptr,
311 /*free_data*/ blender::free_data,
312 /*is_disabled*/ nullptr,
313 /*update_depsgraph*/ nullptr,
314 /*depends_on_time*/ nullptr,
315 /*depends_on_normals*/ nullptr,
316 /*foreach_ID_link*/ blender::foreach_ID_link,
317 /*foreach_tex_link*/ nullptr,
318 /*free_runtime_data*/ nullptr,
319 /*panel_register*/ blender::panel_register,
320 /*blend_write*/ blender::blend_write,
321 /*blend_read*/ blender::blend_read,
322 /*foreach_cache*/ nullptr,
323};
float BKE_curvemapping_evaluateF(const CurveMapping *cumap, int cur, float value)
Low-level operations for curves.
Low-level operations for grease pencil.
void BKE_modifier_copydata_generic(const ModifierData *md, ModifierData *md_dst, int flag)
@ eModifierTypeFlag_SupportsMapping
@ eModifierTypeFlag_AcceptsGreasePencil
@ eModifierTypeFlag_EnableInEditmode
@ eModifierTypeFlag_SupportsEditmode
void(*)(void *user_data, Object *ob, ID **idpoin, int cb_flag) IDWalkFunc
#define BLI_assert(a)
Definition BLI_assert.h:50
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define BLO_write_struct(writer, struct_name, data_ptr)
#define IFACE_(msgid)
#define DNA_struct_default_get(struct_name)
@ GREASE_PENCIL_INFLUENCE_INVERT_VERTEX_GROUP
@ GREASE_PENCIL_INFLUENCE_USE_CUSTOM_CURVE
@ MOD_GREASE_PENCIL_OPACITY_USE_WEIGHT_AS_FACTOR
@ MOD_GREASE_PENCIL_OPACITY_USE_UNIFORM_OPACITY
GreasePencilModifierColorMode
@ MOD_GREASE_PENCIL_COLOR_FILL
@ MOD_GREASE_PENCIL_COLOR_STROKE
@ MOD_GREASE_PENCIL_COLOR_BOTH
@ MOD_GREASE_PENCIL_COLOR_HARDNESS
@ eModifierType_GreasePencilOpacity
struct GreasePencilOpacityModifierData GreasePencilOpacityModifierData
ModifierTypeInfo modifierType_GreasePencilOpacity
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void uiLayoutSetActive(uiLayout *layout, bool active)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
#define UI_ITEM_NONE
PanelLayout uiLayoutPanelProp(const bContext *C, uiLayout *layout, PointerRNA *open_prop_owner, const char *open_prop_name)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
bke::CurvesGeometry & strokes_for_write()
void foreach_index(Fn &&fn) const
draw_view in_light_buf[] float
void read_influence_data(BlendDataReader *reader, GreasePencilModifierInfluenceData *influence_data)
void init_influence_data(GreasePencilModifierInfluenceData *influence_data, const bool has_custom_curve)
static IndexMask get_filtered_layer_mask(const GreasePencil &grease_pencil, const std::optional< StringRef > layer_name_filter, const std::optional< int > layer_pass_filter, const bool layer_filter_invert, const bool layer_pass_filter_invert, IndexMaskMemory &memory)
static IndexMask get_filtered_stroke_mask(const Object *ob, const bke::CurvesGeometry &curves, const Material *material_filter, const std::optional< int > material_pass_filter, const bool material_filter_invert, const bool material_pass_filter_invert, IndexMaskMemory &memory)
void write_influence_data(BlendWriter *writer, const GreasePencilModifierInfluenceData *influence_data)
void draw_vertex_group_settings(const bContext *, uiLayout *layout, PointerRNA *ptr)
VArray< float > get_influence_vertex_weights(const bke::CurvesGeometry &curves, const GreasePencilModifierInfluenceData &influence_data)
Vector< bke::greasepencil::Drawing * > get_drawings_for_write(GreasePencil &grease_pencil, const IndexMask &layer_mask, const int frame)
void draw_material_filter_settings(const bContext *, uiLayout *layout, PointerRNA *ptr)
void draw_layer_filter_settings(const bContext *, uiLayout *layout, PointerRNA *ptr)
void draw_custom_curve_settings(const bContext *, uiLayout *layout, PointerRNA *ptr)
void free_influence_data(GreasePencilModifierInfluenceData *influence_data)
void foreach_influence_ID_link(GreasePencilModifierInfluenceData *influence_data, Object *ob, IDWalkFunc walk, void *user_data)
void copy_influence_data(const GreasePencilModifierInfluenceData *influence_data_src, GreasePencilModifierInfluenceData *influence_data_dst, const int)
void parallel_for_each(Range &&range, const Function &function)
Definition BLI_task.hh:58
static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
static void blend_write(BlendWriter *writer, const ID *, const ModifierData *md)
static void modify_curves(ModifierData &md, const ModifierEvalContext &ctx, Drawing &drawing)
static void modify_softness(const GreasePencilOpacityModifierData &omd, bke::CurvesGeometry &curves, const IndexMask &curves_mask)
static void init_data(ModifierData *md)
static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
static void panel_draw(const bContext *C, Panel *panel)
static void modify_geometry_set(ModifierData *md, const ModifierEvalContext *ctx, bke::GeometrySet *geometry_set)
static void modify_fill_color(Object &ob, const GreasePencilColorModifierData &cmd, Drawing &drawing, const IndexMask &curves_mask)
static void free_data(ModifierData *md)
static void panel_register(ARegionType *region_type)
static void modify_stroke_color(Object &ob, const GreasePencilColorModifierData &cmd, bke::CurvesGeometry &curves, const IndexMask &curves_mask, const MutableSpan< ColorGeometry4f > vertex_colors)
static void blend_read(BlendDataReader *reader, ModifierData *md)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
__int64 int64_t
Definition stdint.h:89
GreasePencilModifierInfluenceData influence
GreasePencilRuntimeHandle * runtime
Definition DNA_ID.h:413
struct uiLayout * layout
GreasePencil * get_grease_pencil_for_write()
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4126
uint8_t flag
Definition wm_window.cc:138