Blender V4.3
MOD_grease_pencil_util.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
10
11#include "BLI_set.hh"
12#include "BLI_vector_set.hh"
13
15#include "DNA_material_types.h"
16#include "DNA_modifier_types.h"
17#include "DNA_screen_types.h"
18
19#include "BKE_colortools.hh"
20#include "BKE_curves.hh"
21#include "BKE_grease_pencil.hh"
22#include "BKE_lib_query.hh"
23#include "BKE_material.h"
24
25#include "BLT_translation.hh"
26
27#include "BLO_read_write.hh"
28
29#include "RNA_access.hh"
30#include "RNA_prototypes.hh"
31
32#include "UI_interface.hh"
33
35
37
41
43 const bool has_custom_curve)
44{
45 if (has_custom_curve) {
46 influence_data->custom_curve = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
47 BKE_curvemapping_init(influence_data->custom_curve);
48 }
49}
50
52 GreasePencilModifierInfluenceData *influence_data_dst,
53 const int /*flag*/)
54{
55 memcpy(influence_data_dst, influence_data_src, sizeof(GreasePencilModifierInfluenceData));
56 influence_data_dst->custom_curve = BKE_curvemapping_copy(influence_data_src->custom_curve);
57}
58
60{
61 if (influence_data->custom_curve) {
62 BKE_curvemapping_free(influence_data->custom_curve);
63 influence_data->custom_curve = nullptr;
64 }
65}
66
68 Object *ob,
69 IDWalkFunc walk,
70 void *user_data)
71{
72 walk(user_data, ob, (ID **)&influence_data->material, IDWALK_CB_USER);
73}
74
76 const GreasePencilModifierInfluenceData *influence_data)
77{
78 if (influence_data->custom_curve) {
79 BKE_curvemapping_blend_write(writer, influence_data->custom_curve);
80 }
81}
82
85{
86 BLO_read_struct(reader, CurveMapping, &influence_data->custom_curve);
87 if (influence_data->custom_curve) {
88 BKE_curvemapping_blend_read(reader, influence_data->custom_curve);
89 /* Make sure the internal table exists. */
90 BKE_curvemapping_init(influence_data->custom_curve);
91 }
92}
93
95{
96 PointerRNA ob_ptr = RNA_pointer_create(ptr->owner_id, &RNA_Object, ptr->owner_id);
97 PointerRNA obj_data_ptr = RNA_pointer_get(&ob_ptr, "data");
98 const bool use_layer_pass = RNA_boolean_get(ptr, "use_layer_pass_filter");
99 uiLayout *row, *col, *sub, *subsub;
100
101 uiLayoutSetPropSep(layout, true);
102
103 col = uiLayoutColumn(layout, true);
104 row = uiLayoutRow(col, true);
105 uiLayoutSetPropDecorate(row, false);
107 row, ptr, "layer_filter", &obj_data_ptr, "layers", nullptr, ICON_OUTLINER_DATA_GP_LAYER);
108 sub = uiLayoutRow(row, true);
109 uiItemR(sub, ptr, "invert_layer_filter", UI_ITEM_NONE, "", ICON_ARROW_LEFTRIGHT);
110
111 row = uiLayoutRowWithHeading(col, true, IFACE_("Layer Pass"));
112 uiLayoutSetPropDecorate(row, false);
113 sub = uiLayoutRow(row, true);
114 uiItemR(sub, ptr, "use_layer_pass_filter", UI_ITEM_NONE, "", ICON_NONE);
115 subsub = uiLayoutRow(sub, true);
116 uiLayoutSetActive(subsub, use_layer_pass);
117 uiItemR(subsub, ptr, "layer_pass_filter", UI_ITEM_NONE, "", ICON_NONE);
118 uiItemR(subsub, ptr, "invert_layer_pass_filter", UI_ITEM_NONE, "", ICON_ARROW_LEFTRIGHT);
119}
120
122{
123 PointerRNA ob_ptr = RNA_pointer_create(ptr->owner_id, &RNA_Object, ptr->owner_id);
124 PointerRNA obj_data_ptr = RNA_pointer_get(&ob_ptr, "data");
125 const bool use_material_pass = RNA_boolean_get(ptr, "use_material_pass_filter");
126 uiLayout *row, *col, *sub, *subsub;
127
128 uiLayoutSetPropSep(layout, true);
129
130 col = uiLayoutColumn(layout, true);
131 row = uiLayoutRow(col, true);
132 uiLayoutSetPropDecorate(row, false);
134 row, ptr, "material_filter", &obj_data_ptr, "materials", nullptr, ICON_SHADING_TEXTURE);
135 sub = uiLayoutRow(row, true);
136 uiItemR(sub, ptr, "invert_material_filter", UI_ITEM_NONE, "", ICON_ARROW_LEFTRIGHT);
137
138 row = uiLayoutRowWithHeading(col, true, IFACE_("Material Pass"));
139 uiLayoutSetPropDecorate(row, false);
140 sub = uiLayoutRow(row, true);
141 uiItemR(sub, ptr, "use_material_pass_filter", UI_ITEM_NONE, "", ICON_NONE);
142 subsub = uiLayoutRow(sub, true);
143 uiLayoutSetActive(subsub, use_material_pass);
144 uiItemR(subsub, ptr, "material_pass_filter", UI_ITEM_NONE, "", ICON_NONE);
145 uiItemR(subsub, ptr, "invert_material_pass_filter", UI_ITEM_NONE, "", ICON_ARROW_LEFTRIGHT);
146}
147
149{
150 PointerRNA ob_ptr = RNA_pointer_create(ptr->owner_id, &RNA_Object, ptr->owner_id);
151 bool has_vertex_group = RNA_string_length(ptr, "vertex_group_name") != 0;
152 uiLayout *row, *col, *sub;
153
154 uiLayoutSetPropSep(layout, true);
155
156 col = uiLayoutColumn(layout, true);
157 row = uiLayoutRow(col, true);
158 uiLayoutSetPropDecorate(row, false);
159 uiItemPointerR(row, ptr, "vertex_group_name", &ob_ptr, "vertex_groups", nullptr, ICON_NONE);
160 sub = uiLayoutRow(row, true);
161 uiLayoutSetActive(sub, has_vertex_group);
162 uiLayoutSetPropDecorate(sub, false);
163 uiItemR(sub, ptr, "invert_vertex_group", UI_ITEM_NONE, "", ICON_ARROW_LEFTRIGHT);
164}
165
167{
168 bool use_custom_curve = RNA_boolean_get(ptr, "use_custom_curve");
169 uiLayout *row;
170
171 uiLayoutSetPropSep(layout, true);
172 row = uiLayoutRow(layout, true);
173 uiLayoutSetPropDecorate(row, false);
174 uiItemR(row, ptr, "use_custom_curve", UI_ITEM_NONE, IFACE_("Custom Curve"), ICON_NONE);
175 if (use_custom_curve) {
176 uiTemplateCurveMapping(layout, ptr, "custom_curve", 0, false, false, false, false);
177 }
178}
179
186{
187 short *totcol = BKE_object_material_len_p(const_cast<Object *>(ob));
188 Vector<int> result(*totcol);
189 Material *ma = nullptr;
190 for (short i = 0; i < *totcol; i++) {
191 ma = BKE_object_material_get(const_cast<Object *>(ob), i + 1);
192 /* Pass index of the grease pencil material. */
193 result[i] = ma->gp_style->index;
194 }
195 return result;
196}
197
199 const std::optional<StringRef> layer_name_filter,
200 const std::optional<int> layer_pass_filter,
201 const bool layer_filter_invert,
202 const bool layer_pass_filter_invert,
203 IndexMaskMemory &memory)
204{
205 const IndexMask full_mask = grease_pencil.layers().index_range();
206 if (!layer_name_filter && !layer_pass_filter) {
207 return full_mask;
208 }
209
210 bke::AttributeAccessor layer_attributes = grease_pencil.attributes();
211 const Span<const Layer *> layers = grease_pencil.layers();
212 const VArray<int> layer_passes =
213 layer_attributes.lookup_or_default<int>("pass_index", bke::AttrDomain::Layer, 0).varray;
214
216 full_mask, GrainSize(4096), memory, [&](const int64_t layer_i) {
217 if (layer_name_filter) {
218 const Layer &layer = *layers[layer_i];
219 const bool match = (layer.name() == layer_name_filter.value());
220 if (match == layer_filter_invert) {
221 return false;
222 }
223 }
224 if (layer_pass_filter) {
225 const int layer_pass = layer_passes.get(layer_i);
226 const bool match = (layer_pass == layer_pass_filter.value());
227 if (match == layer_pass_filter_invert) {
228 return false;
229 }
230 }
231 return true;
232 });
233 return result;
234}
235
237 const GreasePencilModifierInfluenceData &influence_data,
238 IndexMaskMemory &memory)
239{
241 grease_pencil,
242 influence_data.layer_name[0] != '\0' ?
243 std::make_optional<StringRef>(influence_data.layer_name) :
244 std::nullopt,
246 std::make_optional<int>(influence_data.layer_pass) :
247 std::nullopt,
250 memory);
251}
252
254 const bke::CurvesGeometry &curves,
255 const Material *material_filter,
256 const std::optional<int> material_pass_filter,
257 const bool material_filter_invert,
258 const bool material_pass_filter_invert,
259 IndexMaskMemory &memory)
260{
261 const IndexMask full_mask = curves.curves_range();
262 if (!material_filter && !material_pass_filter) {
263 return full_mask;
264 }
265
266 const int material_filter_index = BKE_object_material_index_get(
267 const_cast<Object *>(ob), const_cast<Material *>(material_filter));
268 const Vector<int> material_pass_by_index = get_grease_pencil_material_passes(ob);
269
270 bke::AttributeAccessor attributes = curves.attributes();
271 VArray<int> stroke_materials =
272 attributes.lookup_or_default<int>("material_index", bke::AttrDomain::Curve, 0).varray;
273
275 full_mask, GrainSize(4096), memory, [&](const int64_t stroke_i) {
276 const int material_index = stroke_materials.get(stroke_i);
277 if (material_filter != nullptr) {
278 const bool match = (material_index == material_filter_index);
279 if (match == material_filter_invert) {
280 return false;
281 }
282 }
283 if (material_pass_filter) {
284 const int material_pass = material_pass_by_index[material_index];
285 const bool match = (material_pass == material_pass_filter.value());
286 if (match == material_pass_filter_invert) {
287 return false;
288 }
289 }
290 return true;
291 });
292 return result;
293}
294
296 const bke::CurvesGeometry &curves,
297 const GreasePencilModifierInfluenceData &influence_data,
298 IndexMaskMemory &memory)
299{
301 ob,
302 curves,
303 influence_data.material,
305 std::make_optional<int>(influence_data.material_pass) :
306 std::nullopt,
309 memory);
310}
311
313 const GreasePencilModifierInfluenceData &influence_data)
314{
315 if (influence_data.vertex_group_name[0] == '\0') {
316 /* If vertex group is not set, use full weight for all vertices. */
317 return VArray<float>::ForSingle(1.0f, curves.point_num);
318 }
319 /* Vertex group weights, with zero weight as fallback. */
320 return *curves.attributes().lookup_or_default<float>(
321 influence_data.vertex_group_name, bke::AttrDomain::Point, 0.0f);
322}
323
325 const IndexMask &layer_mask,
326 const int frame)
327{
328 using namespace blender::bke::greasepencil;
329 VectorSet<Drawing *> drawings;
330 layer_mask.foreach_index([&](const int64_t layer_i) {
331 const Layer &layer = grease_pencil.layer(layer_i);
332 /* Set of owned drawings, ignore drawing references to other data blocks. */
333 if (Drawing *drawing = grease_pencil.get_drawing_at(layer, frame)) {
334 drawings.add(drawing);
335 }
336 });
337 return Vector<Drawing *>(drawings.as_span());
338}
339
341 const IndexMask &layer_mask,
342 const int frame)
343{
344 using namespace blender::bke::greasepencil;
345 Set<Drawing *> drawings;
346 Vector<LayerDrawingInfo> drawing_infos;
347 layer_mask.foreach_index([&](const int64_t layer_i) {
348 const Layer &layer = grease_pencil.layer(layer_i);
349 Drawing *drawing = grease_pencil.get_drawing_at(layer, frame);
350 if (drawing == nullptr) {
351 return;
352 }
353
354 if (!drawings.contains(drawing)) {
355 drawings.add_new(drawing);
356 drawing_infos.append({drawing, int(layer_i)});
357 }
358 });
359 return drawing_infos;
360}
361
363 const IndexMask &layer_mask,
364 const int frame)
365{
366 using namespace blender::bke::greasepencil;
367 Set<Drawing *> drawings;
368 Vector<FrameDrawingInfo> drawing_infos;
369 layer_mask.foreach_index([&](const int64_t layer_i) {
370 const Layer &layer = grease_pencil.layer(layer_i);
371 const std::optional<int> start_frame = layer.start_frame_at(frame);
372 if (!start_frame) {
373 return;
374 }
375 Drawing *drawing = grease_pencil.get_drawing_at(layer, *start_frame);
376 if (drawing == nullptr) {
377 return;
378 }
379
380 if (!drawings.contains(drawing)) {
381 drawings.add_new(drawing);
382 drawing_infos.append({drawing, *start_frame});
383 }
384 });
385 return drawing_infos;
386}
387
389{
390 const bke::CurvesGeometry &curves = drawing.strokes();
391 IndexMaskMemory memory;
392 const IndexMask bezier_selection = curves.indices_for_curve_type(CURVE_TYPE_BEZIER, memory);
393 if (bezier_selection.is_empty()) {
394 return;
395 }
396 drawing.strokes_for_write() = geometry::resample_to_evaluated(curves, bezier_selection);
397 drawing.tag_topology_changed();
398}
399
400} // namespace blender::modifier::greasepencil
void BKE_curvemapping_blend_read(BlendDataReader *reader, CurveMapping *cumap)
CurveMapping * BKE_curvemapping_copy(const CurveMapping *cumap)
void BKE_curvemapping_init(CurveMapping *cumap)
CurveMapping * BKE_curvemapping_add(int tot, float minx, float miny, float maxx, float maxy)
Definition colortools.cc:90
void BKE_curvemapping_free(CurveMapping *cumap)
void BKE_curvemapping_blend_write(BlendWriter *writer, const CurveMapping *cumap)
Low-level operations for curves.
Low-level operations for grease pencil.
@ IDWALK_CB_USER
General operations, lookup, etc. for materials.
struct Material * BKE_object_material_get(struct Object *ob, short act)
short * BKE_object_material_len_p(struct Object *ob)
int BKE_object_material_index_get(Object *ob, const Material *ma)
void(*)(void *user_data, Object *ob, ID **idpoin, int cb_flag) IDWalkFunc
#define BLO_read_struct(reader, struct_name, ptr_p)
#define IFACE_(msgid)
@ CURVE_TYPE_BEZIER
@ GREASE_PENCIL_INFLUENCE_USE_MATERIAL_PASS_FILTER
@ GREASE_PENCIL_INFLUENCE_USE_LAYER_PASS_FILTER
@ GREASE_PENCIL_INFLUENCE_INVERT_LAYER_FILTER
@ GREASE_PENCIL_INFLUENCE_INVERT_MATERIAL_PASS_FILTER
@ GREASE_PENCIL_INFLUENCE_INVERT_MATERIAL_FILTER
@ GREASE_PENCIL_INFLUENCE_INVERT_LAYER_PASS_FILTER
void uiLayoutSetActive(uiLayout *layout, bool active)
void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, const char *propname, int type, bool levels, bool brush, bool neg_slope, bool tone)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
uiLayout * uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading)
#define UI_ITEM_NONE
void uiItemPointerR(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *searchptr, const char *searchpropname, const char *name, int icon)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
bool contains(const Key &key) const
Definition BLI_set.hh:291
T get(const int64_t index) const
static VArray ForSingle(T value, const int64_t size)
Span< Key > as_span() const
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const void *default_value=nullptr) const
bke::CurvesGeometry & strokes_for_write()
const bke::CurvesGeometry & strokes() const
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
void foreach_index(Fn &&fn) const
uint col
void read_influence_data(BlendDataReader *reader, GreasePencilModifierInfluenceData *influence_data)
void init_influence_data(GreasePencilModifierInfluenceData *influence_data, const bool has_custom_curve)
Vector< LayerDrawingInfo > get_drawing_infos_by_layer(GreasePencil &grease_pencil, const IndexMask &layer_mask, const int frame)
Vector< FrameDrawingInfo > get_drawing_infos_by_frame(GreasePencil &grease_pencil, const IndexMask &layer_mask, const int frame)
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)
static Vector< int > get_grease_pencil_material_passes(const Object *ob)
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 ensure_no_bezier_curves(Drawing &drawing)
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
int RNA_string_length(PointerRNA *ptr, const char *name)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
PointerRNA RNA_pointer_create(ID *id, StructRNA *type, void *data)
__int64 int64_t
Definition stdint.h:89
Definition DNA_ID.h:413
struct MaterialGPencilStyle * gp_style
ID * owner_id
Definition RNA_types.hh:40
PointerRNA * ptr
Definition wm_files.cc:4126